File Coverage

blib/lib/Antsy.pm
Criterion Covered Total %
statement 134 342 39.1
branch 2 26 7.6
condition 3 17 17.6
subroutine 24 68 35.2
pod 29 29 100.0
total 192 482 39.8


line stmt bran cond sub pod time code
1 2     2   553138 use v5.26;
  2         5  
2              
3             package Antsy;
4 2     2   7 use strict;
  2         2  
  2         35  
5 2     2   11 use warnings;
  2         3  
  2         103  
6 2     2   931 use utf8;
  2         421  
  2         9  
7 2     2   874 use experimental qw(signatures);
  2         2510  
  2         8  
8              
9 2     2   302 use Carp qw(carp);
  2         3  
  2         83  
10 2     2   7 use Exporter qw(import);
  2         3  
  2         2257  
11              
12             our( @EXPORT, @EXPORT_OK, %EXPORT_TAGS );
13              
14             our $VERSION = '0.907';
15              
16             =encoding utf8
17              
18             =head1 NAME
19              
20             Antsy - Streaming ANSI escape sequences
21              
22             =head1 SYNOPSIS
23              
24             use Antsy qw(:all);
25              
26             print bold, underline, text_red, "Hello", reset;
27              
28             =head1 DESCRIPTION
29              
30             Subroutines to deal with ANSI terminal sequences. You can emit these
31             without knowing what's coming up.
32              
33             =head2 Yet another module?
34              
35             There are several modules that come close to this, but so far
36             everything is incomplete or requires you to know all of the upcoming
37             text ahead of time so you can use of it as an argument to a function.
38             I want to emit the sequence in a stream without knowing what's coming
39             up.
40              
41             =over 4
42              
43             =item * L
44              
45             Wraps ANSI color stuff around text. This comes with Perl v5.10 and
46             later.
47              
48             =item * L
49              
50             Routines for dealing with text that contains ANSI code. For example,
51             ignore the ANSI sequences in computing length.
52              
53             =item * L
54              
55             I don't really know what this does.
56              
57             =item * L
58              
59             =back
60              
61             =head2 Methods
62              
63             =over 4
64              
65             =item * bg_256( N )
66              
67             =item * bg_rgb
68              
69             =item * bg_black
70              
71             =item * bg_blue
72              
73             =item * bg_cyan
74              
75             =item * bg_green
76              
77             =item * bg_magenta
78              
79             =item * bg_orange
80              
81             =item * bg_red
82              
83             =item * bg_white
84              
85             =item * bg_yellow
86              
87             Make the background the named color
88              
89             =item * bg_bright_black
90              
91             =item * bg_bright_blue
92              
93             =item * bg_bright_cyan
94              
95             =item * bg_bright_green
96              
97             =item * bg_bright_magenta
98              
99             =item * bg_bright_red
100              
101             =item * bg_bright_white
102              
103             =item * bg_bright_yellow
104              
105             Make the background the named color and bright (however your terminal
106             does that).
107              
108             =item * blink
109              
110             Make the text blink (however your terminal does that).
111              
112             =item * bold
113              
114             Turn on bold
115              
116             =item * clear_line
117              
118             =item * clear_screen
119              
120             =item * clear_to_line_end
121              
122             =item * clear_to_line_start
123              
124             =item * clear_to_screen_end
125              
126             =item * clear_to_screen_start
127              
128             Clear the part of the screen as indicated. Each of these start at the
129             current cursor position.
130              
131             =item * conceal
132              
133             Make the text invisible (if your terminal handles that).
134              
135             =item * cursor_back( N )
136              
137             Move the cursor back N positions.
138              
139             =item * cursor_column( N )
140              
141             Move the cursor to column N.
142              
143             =item * cursor_down( N )
144              
145             Move the cursor down N positions.
146              
147             =item * cursor_forward( N )
148              
149             Move the cursor forward N positions.
150              
151             =item * cursor_next_line( N )
152              
153             Move the cursor down N lines, to the start of the line
154              
155             =item * cursor_previous_line( N )
156              
157             Move the cursor up N lines, to the start of the line
158              
159             =item * cursor_row_column( N, M )
160              
161             Move the cursor to row N and column M.
162              
163             =item * cursor_up
164              
165             TK: Fill in details
166              
167             =item * dark
168              
169             Make the text dark (however your terminal does that).
170              
171             =item * erase_in_display( [ 0, 1, 2, 3 ] )
172              
173             TK: Fill in details
174              
175             =item * erase_in_line( [ 0, 1, 2, 3 ] )
176              
177             TK: Fill in details
178              
179             =item * hide_cursor
180              
181             Hide the cursor. See also C.
182              
183             =item * italic
184              
185             Turn on italic.
186              
187             =item * reset
188              
189             Turn off all attributes
190              
191             =item * restore_cursor
192              
193             Put the cursor back to where you saved it. See also C.
194              
195             =item * reverse
196              
197             Use the background color for the text color, and the text color
198             for the background.
199              
200             =item * save_cursor
201              
202             Save the current location of the cursor. See also C.
203              
204             =item * scroll_down( N )
205              
206             Scroll down N lines.
207              
208             =item * scroll_up( N )
209              
210             Scroll up N lines.
211              
212             =item * show_cursor
213              
214             Show the cursor. See also C.
215              
216             =item * text_256( N )
217              
218             Make the foreground the color N in the xterm 256 color chart.
219              
220             This dies if N is not a positive number between 0 and 255 (inclusive).
221              
222             =item * text_black
223              
224             =item * text_blue
225              
226             =item * text_cyan
227              
228             =item * text_green
229              
230             =item * text_magenta
231              
232             =item * text_orange
233              
234             =item * text_red
235              
236             =item * text_rgb
237              
238             =item * text_white
239              
240             =item * text_yellow
241              
242             Make foreground text the named color.
243              
244             =item * text_blink
245              
246             Make the text blink.
247              
248             =item * text_bright_black
249              
250             =item * text_bright_blue
251              
252             =item * text_bright_cyan
253              
254             =item * text_bright_green
255              
256             =item * text_bright_magenta
257              
258             =item * text_bright_red
259              
260             =item * text_bright_white
261              
262             =item * text_bright_yellow
263              
264             Make foreground text the named color and bright (however your terminal
265             does that).
266              
267             =item * text_concealed
268              
269             Conceal the text.
270              
271             =item * underline
272              
273             Turn on underlining.
274              
275             =back
276              
277             =cut
278              
279 0     0   0 sub _256 ( $i, $n ) {
  0         0  
  0         0  
  0         0  
280 0 0 0     0 carp "Bad 256 $n" unless( int($n) == $n and $n >= 0 and $n <= 255 );
      0        
281 0         0 _seq( 'm', $i, 5, $n );
282             }
283              
284 2     2   13 sub _bg () { 48 } # a magic number that applies the SGR to the background
  2         6  
  2         31  
285              
286 0     0   0 sub _erase ( $n, $command ) {
  0         0  
  0         0  
  0         0  
287             carp "Bad value <$n>. Should be 0, 1, or 2"
288 0 0       0 unless grep { $_ == $n } qw(0 1 2);
  0         0  
289             carp "Bad erase command <$command>. Should be J or K"
290 0 0       0 unless grep { $_ == $n } qw(0 1 2);
  0         0  
291 0         0 _seq( $command, $n );
292             }
293              
294 138     138   116 sub _export ( $name, $tag ) {
  138         115  
  138         108  
  138         105  
295 138         136 push @EXPORT_OK, $name;
296 138         198 push $EXPORT_TAGS{all }->@*, $name;
297 138         4593 push $EXPORT_TAGS{$tag}->@*, $name;
298             }
299              
300 4     4   5 sub _rgb ( $i, $r, $g, $b ) {
  4         4  
  4         8  
  4         2  
  4         4  
  4         3  
301             carp "Bad RGB $r;$b;$g" unless
302 4 50 33     5 3 == grep { int($_) == $_ and $_ >= 0 and $_ <= 255 }
  12 50       48  
303             ( $r, $b, $g );
304              
305 4         6 _seq( 'm', $i, 2, $r, $g, $b );
306             }
307              
308             # _seq forms the ANSI escape sequence. There's the start, some arguments
309             # separated by `;`, then a string for the argument
310 120     120   95 sub _seq ( $command, @args ) { join '', "\x1b[", join( ';', @args ), $command }
  120         115  
  120         114  
  120         89  
  120         228  
311              
312 0     0   0 sub _encode_seq ( $string ) {
  0         0  
  0         0  
313 0         0 local $_ = $string;
314              
315 0         0 s/(.)/sprintf '%02X ', ord($1) /ge;
  0         0  
316              
317 0         0 s/1b /ESC /ig;
318 0         0 s/07 /BEL /ig;
319 0         0 s/31 33 33 37 /1337 /;
320              
321 0         0 s/([2-7A-F][0-9A-F])\x20/ chr( hex($1) ) . ' ' /ge;
  0         0  
322 0         0 $_;
323             }
324              
325 0     0   0 sub _start () { "\x1b[" }
  0         0  
  0         0  
326              
327 2     2   2 sub _text () { 38 } # a magic number that applies the SGR to the text
  2         3  
  2         10  
328              
329 0     0 1 0 sub bg_256 ( $n ) { _256( _bg(), $n ) }
  0         0  
  0         0  
  0         0  
330 2     2 1 3 sub bg_rgb ( $r, $g, $b ) { _rgb( _bg(), $r, $g, $b ) }
  2         2  
  2         2  
  2         1  
  2         3  
  2         2  
331              
332 0     0 1 0 sub cursor_row_column ( $n = 1, $m = 1 ) { _seq( 'H', $n, $m ) }
  0         0  
  0         0  
  0         0  
  0         0  
333              
334 0     0 1 0 sub text_256 ( $n ) { _256( _text(), $n ) }
  0         0  
  0         0  
  0         0  
335 2     2 1 3 sub text_rgb ( $r, $g, $b ) { _rgb( _text(), $r, $g, $b ) }
  2         2  
  2         2  
  2         2  
  2         1  
  2         8  
336              
337              
338             # This section takes the subroutines that we've already defined to
339             # adds them to the export lists.
340             BEGIN {
341 2     2   9 my @subs = qw( bg_256 bg_rgb text_256 text_rgb
342             erase_in_display erase_in_line cursor_row_column
343             );
344              
345 2         6 push @EXPORT_OK, @subs;
346 2         15 push $EXPORT_TAGS{all }->@*, @subs;
347 2         5 push $EXPORT_TAGS{bg }->@*, grep { /\Abg_/ } @subs;
  14         25  
348 2         3 push $EXPORT_TAGS{text }->@*, grep { /\Atext_/ } @subs;
  14         29  
349 2         3 push $EXPORT_TAGS{erase }->@*, grep { /\Aerase_/ } @subs;
  14         37  
350 2         2 push $EXPORT_TAGS{cursor}->@*, grep { /\Acursor_/ } @subs;
  14         209  
351             }
352              
353             BEGIN {
354 2     2   9 my @groups = (
355             [ qw( J screen) ],
356             [ qw( K line ) ],
357             );
358              
359 2         2 my @templates = ( 'clear_to_%s_end', 'clear_to_%s_start', 'clear_%s' );
360              
361 2         5 foreach my $group ( @groups ) {
362 2     2   19 no strict 'refs';
  2         2  
  2         343  
363 4         7 foreach my $i ( 0 .. 2 ) {
364 12         26 my $name = sprintf $templates[$i], $group->[1];
365 12         15 my $value = _seq( $group->[0], $i );
366 12     0   35 *{$name} = sub () { $value };
  12         43  
  0         0  
  0            
  0            
367 12         18 _export( $name, 'clear' );
368             }
369             }
370             }
371              
372             BEGIN {
373 2     2   12 my @groups = (
374             [ qw( cursor back D ) ],
375             [ qw( cursor column G ) ],
376             [ qw( cursor down B ) ],
377             [ qw( cursor forward C ) ],
378             [ qw( cursor next_line E ) ],
379             [ qw( cursor previous_line F ) ],
380             [ qw( cursor up A ) ],
381             [ qw( scroll down T ) ],
382             [ qw( scroll up S ) ],
383             );
384              
385 2         4 foreach my $group ( @groups ) {
386 2     2   11 no strict 'refs';
  2         2  
  2         351  
387              
388 18         22 my( $export_tag, $fragment, $command ) = @$group;
389 18         23 my $name = join '_', $export_tag, $fragment;
390              
391 18     0   47 *{$name} = sub ( $n ) {
  0            
  0            
  0            
392 0 0       0 $n = $n =~ /\A([0-9]+)\z/ ? $1 : 0;
393 0         0 _seq( $command, $n );
394 18         33 };
395              
396 18         20 _export( $name, $export_tag );
397             }
398             }
399              
400             BEGIN {
401 2     2   15 my @groups = (
402             # EXPORT_TAG SUB_NAME COMMAND ARGS
403             [ qw( control reset m 0 ) ],
404             [ qw( text bold m 1 ) ],
405             [ qw( text dark m 2 ) ],
406             [ qw( text italic m 3 ) ],
407             [ qw( text underline m 4 ) ],
408             [ qw( text blink m 5 ) ],
409             [ qw( text reverse m 7 ) ],
410             [ qw( text conceal m 8 ) ],
411             [ qw( cursor save_cursor s ) ],
412             [ qw( cursor restore_cursor u ) ],
413             [ qw( cursor hide_cursor h ?25 ) ],
414             [ qw( cursor show_cursor l ?25 ) ],
415             );
416              
417 2         5 foreach my $group ( @groups ) {
418 2     2   11 no strict 'refs';
  2         3  
  2         324  
419              
420 24         30 my( $export_tag, $name, $command, $n ) = @$group;
421 24   100     36 $n //= '';
422 24         26 my $value = _seq( $command, $n );
423              
424 24     0   47 *{$name} = sub () { $value };
  24         70  
  0         0  
  0            
  0            
425              
426 24         25 _export( $name, $export_tag );
427             }
428             }
429              
430             BEGIN {
431 2     2   9 my @colors = qw( black red green yellow blue magenta cyan white );
432 2         2 my %colors = map { state $n = 0; $_ => $n++ } @colors;
  16         29  
  16         48  
433              
434 2         9 my @groups = (
435             [ ( 0, '', '%s' ) ],
436             [ qw( 30 text %s ) ],
437             [ qw( 90 text bright %s ) ],
438             [ qw( 40 bg %s ) ],
439             [ qw( 100 bg bright %s ) ],
440             );
441              
442 2         3 foreach my $group ( @groups ) {
443 10         11 my $offset = shift @$group;
444 10         15 my $template = join "_", @$group;
445              
446 10         15 foreach my $i ( 0 .. $#colors ) {
447 2     2   11 no strict 'refs';
  2         2  
  2         326  
448 80         113 my $name = sprintf $template, $colors[$i];
449 80         108 my $value = _seq( 'm', $offset + $i );
450 80     0   144 *{$name} = sub () { $value };
  80         200  
  0         0  
  0            
  0            
451 80         88 _export( $name, $group->[1] );
452             }
453             }
454              
455 2         5 my @secondary_colors = (
456             [ 'orange', [ 0xFF, 0x8C, 0x00 ] ],
457             );
458              
459 2         3 foreach my $tuple ( @secondary_colors ) {
460 2     2   8 no strict 'refs';
  2         3  
  2         301  
461 2         5 my( $color, $rgb ) = $tuple->@*;
462 2         2 my $name = "text_$color";
463 2         5 my $value = text_rgb( $rgb->@* );
464 2     0   4 *{$name} = sub () { $value };
  2         22  
  0         0  
  0            
  0            
465 2         8 _export( $name, 'text' );
466              
467 2         3 $name = "bg_$color";
468 2         5 $value = bg_rgb( $rgb->@* );
469 2         5 _export( $name, 'bg' );
470             }
471             }
472              
473             =head2 Character shortcuts
474              
475             =over 4
476              
477             =item * BELL - \007
478              
479             =item * CSI - ESC [
480              
481             =item * ESC - \x1b
482              
483             =item * OSC - ESC ]
484              
485             =item * ST - BELL or ESC \
486              
487             =item * SP - literal space
488              
489             =back
490              
491             =cut
492              
493 0     0 1   sub BELL () { "\007" }
  0            
  0            
494 0     0 1   sub CSI () { ESC() . '[' }
  0            
  0            
495 0     0 1   sub ESC () { "\x1b" }
  0            
  0            
496 0     0 1   sub OSC () { ESC() . ']' }
  0            
  0            
497 0     0 1   sub SP () { ' ' }
  0            
  0            
498 0     0 1   sub ST () { BELL() }
  0            
  0            
499              
500             =head2 Editor-specific codes
501              
502             =head3 iTerm2
503              
504             iTerm2 supports proprietary
505              
506             =over 4
507              
508             =item * iterm_bg_color()
509              
510             =item * iterm_fg_color() OSC 4 ; -1; ? ST
511              
512             Returns an array reference of the decimal values for the Red, Green
513             and Blue components of the background or foreground. These triplets
514             may be 2 or 4 digits in each component.
515              
516             =cut
517              
518 0     0     sub _iterm_id { 'iTerm.app' }
519              
520 0     0     sub _is_term_type ( $id ) {
  0            
  0            
521 0           $ENV{TERM_PROGRAM} =~ m/\A\Q$id\E\z/;
522             }
523              
524 0     0     sub _is_iterm { _is_term_type( _iterm_id() ) }
525              
526 0     0     sub _iterm_seq ( $command, @args ) {
  0            
  0            
  0            
527 0 0         unless( _is_iterm() ) {
528 0           my $sub = ( caller(1) )[3];
529 0           carp( "$sub only works in iTerm2" );
530 0           return;
531             }
532              
533 0           OSC() . join( ';', @args, '' ) . $command . ST();
534             }
535              
536 0     0     sub _iterm_query ( $command, @args ) {
  0            
  0            
  0            
537 0           my $terminal = do {
538 0           state $rc = require Term::ReadKey;
539 0           chomp( my $tty = `/usr/bin/tty` );
540             # say "Term: ", $tty;
541 0           open my $terminal, '+<', $tty;
542 0           my $old = select( $terminal );
543 0           $|++;
544 0           select( $old );
545 0           $terminal;
546             };
547              
548 0           print { $terminal } _iterm_seq( $command, @args );;
  0            
549 0           Term::ReadKey::ReadMode('raw');
550 0           my $response;
551             my $key;
552 0           while( defined ($key = Term::ReadKey::ReadKey(0)) ) {
553 0           $response .= $key;
554 0 0         last if ord( $key ) == 3; # Control-C
555 0 0         last if ord( $key ) == 7;
556             }
557 0           Term::ReadKey::ReadMode('normal');
558              
559 0           $response;
560             }
561              
562 0     0     sub _iterm_rgb_query ( $type ) {
  0            
  0            
563 0           state $OSC = qr/ ( \007 | \x1b \\ ) /xn;
564 0           my $response = _iterm_query( '?', 4, $type );
565 0           my( $r, $g, $b ) = $response =~ m|rgb:(.+?)/(.+?)/(.+?)$OSC|;
566 0           [ $r, $g, $b ]
567             }
568              
569 0     0 1   sub iterm_bg_color () { _iterm_rgb_query( -2 ) } # OSC 4 ; -2; ? ST
  0            
  0            
570 0     0 1   sub iterm_fg_color () { _iterm_rgb_query( -1 ) } # OSC 4 ; -1; ? ST
  0            
  0            
571              
572             =item * iterm_start_link( URL [, ID] )
573              
574             =item * iterm_end_link()
575              
576             Mark some text as a clickable URL.
577             OSC 8 ; [params] ; [url] ST id is only param
578              
579             =item * iterm_linked_text( TEXT, URL, [, ID] )
580              
581             =cut
582              
583 0     0 1   sub iterm_start_link ( $url, $id = undef ) {
  0            
  0            
  0            
584 0 0         $id = defined $id ? 'id=$id' : '';
585 0           OSC() . 8 . ';' . $id . ';' . $url . ST();
586             }
587              
588 0     0 1   sub iterm_end_link () { OSC() . 8 . ';;' . ST() }
  0            
  0            
589              
590 0     0 1   sub iterm_linked_text ( $text, $url, $id ) {
  0            
  0            
  0            
  0            
591 0           iterm_start_link( $url, $id ) .
592             $text .
593             iterm_end_link();
594             }
595              
596             =item * set_cursor_shape( N )
597              
598             =over 4
599              
600             =item * 0 Block
601              
602             =item * 1 Vertical bar
603              
604             =item * 2 Underline
605              
606             =back
607              
608             =item * iterm_set_block_cursor
609              
610             =item * iterm_set_bar_cursor
611              
612             =item * iterm_set_underline_cursor
613              
614             =cut
615              
616 0     0     sub _osc_1337 ( $content ) {
  0            
  0            
617 0 0         unless( _is_iterm() ) {
618 0           my $sub = ( caller(1) )[3];
619 0           carp( "$sub only works in iTerm2" );
620 0           return;
621             }
622              
623 0           OSC() . 1337 . ';' . $content . ST()
624             }
625              
626             # OSC 1337 ; CursorShape=[N] ST
627 0     0     sub _iterm_set_cursor ( $n ) {
  0            
  0            
628 0 0 0       unless( $n == 0 or $n == 1 or $n == 2 ) {
      0        
629 0           carp "The cursor type can be 0, 1, or 2, but you specified <$n>";
630 0           return;
631             }
632              
633 0           OSC() . 1337 . ';' . "CursorShape=$n" . 'ST'
634             }
635              
636 0     0 1   sub iterm_set_block_cursor () { state $s = _iterm_set_cursor(0); $s }
  0            
  0            
  0            
637 0     0 1   sub iterm_set_bar_cursor () { state $s = _iterm_set_cursor(1); $s }
  0            
  0            
  0            
638 0     0 1   sub iterm_set_underline_cursor () { state $s = _iterm_set_cursor(2); $s }
  0            
  0            
  0            
639              
640             =item * set_mark
641              
642             Same as Command-Shift-M. Mark the current location and jump back to it
643             with Command-Shift-J.
644              
645             =cut
646              
647             # OSC 1337 ; SetMark ST
648 0     0 1   sub set_mark () { state $s = _osc_1337( 'SetMark' ); $s }
  0            
  0            
  0            
649              
650             =item * steal_focus
651              
652             Bring the window to the foreground.
653              
654             =cut
655              
656             # OSC 1337 ; StealFocus ST
657 0     0 1   sub steal_focus () { state $s = _osc_1337( 'StealFocus' ); $s }
  0            
  0            
  0            
658              
659             =item * clear_scrollback_history
660              
661             Erase the scrollback history.
662              
663             =cut
664              
665             # OSC 1337 ; ClearScrollback ST
666 0     0 1   sub clear_scrollback_history () { state $s = _osc_1337( 'ClearScrollback' ); $s }
  0            
  0            
  0            
667              
668             =item * post_notification
669              
670             =cut
671              
672             # OSC 9 ; [Message content goes here] ST
673              
674             =item * set_current_directory
675              
676             =cut
677              
678             # OSC 1337 ; CurrentDir=[current directory] ST
679              
680             =item * change_profile
681              
682             =cut
683              
684             # OSC 1337 SetProfile=[new profile name] ST
685              
686             =item * start_copy_to_clipboard
687              
688             =item * end_copy_to_clipboard
689              
690             =cut
691              
692             # OSC 1337 ; CopyToClipboard=[clipboard name] ST
693             # OSC 1337 ; EndCopy ST
694              
695             =item * change_color_palette
696              
697             [key] gives the color to change. The accepted values are: fg bg bold link selbg selfg curbg curfg underline tab" black red green yellow blue magenta cyan white br_black br_red br_green br_yellow br_blue br_magenta br_cyan br_white
698              
699             [value] gives the new color. The following formats are accepted:
700              
701             RGB (three hex digits, like fff)
702             RRGGBB (six hex digits, like f0f0f0)
703             cs:RGB (like RGB but cs gives a color space)
704             cs:RRGGBB (like RRGGBB but cs gives a color space)
705             If a color space is given, it should be one of:
706              
707             srgb (the standard sRGB color space)
708             rgb (the device-specific color space)
709             p3 (the standard P3 color space, whose gamut is supported on some newer hardware)
710              
711             =cut
712              
713             # OSC 1337 ; SetColors=[key]=[value] ST
714              
715              
716             =item * add_annotation
717              
718             OSC 1337 ; AddAnnotation=[message] ST
719             OSC 1337 ; AddAnnotation=[length] | [message] ST
720             OSC 1337 ; AddAnnotation=[message] | [length] | [x-coord] | [y-coord] ST
721             OSC 1337 ; AddHiddenAnnotation=[message] ST
722             OSC 1337 ; AddHiddenAnnotation=[length] | [message] ST
723             OSC 1337 ; AddHiddenAnnotation=[message] | [length] | [x-coord] | [y-coord] ST
724             `[message]`: The message to attach to the annotation.
725             `[length]`: The number of cells to annotate. Defaults to the rest of the line beginning at the start of the annotation.
726             `[x-coord]` and `[y-coord]`: The starting coordinate for the annotation. Defaults to the cursor's coordinate.
727              
728             =cut
729              
730             sub add_annotation () {}
731              
732             =item * hide_cursor_guide
733              
734             =item * show_cursor_guide
735              
736             =cut
737              
738             # OSC 1337 ; HighlightCursorLine=[boolean] ST
739 0     0 1   sub hide_cursor_guide () { state $s = _osc_1337( 'HighlightCursorLine=no' ); $s }
  0            
  0            
  0            
740 0     0 1   sub show_cursor_guide () { state $s = _osc_1337( 'HighlightCursorLine=yes' ); $s }
  0            
  0            
  0            
741              
742             =item * iterm_attention
743              
744             Play with the dock icon.
745              
746             =over 4
747              
748             =item * fireworks - animation at the cursor
749              
750             =item * no - stop bouncing the dock icon
751              
752             =item * once - bounce the dock icon once
753              
754             =item * yes - bounce the dock indefinitely
755              
756             =back
757              
758             =cut
759              
760             =item * iterm_bounce_dock_icon
761              
762             Bounce the Dock icon, continuously
763              
764             =item * iterm_bounce_dock_icon_once
765              
766             Bounce the Dock icon, only once
767              
768             =item * iterm_unbounce_dock_icon
769              
770             Stop bouncing the Dock icon
771              
772             =item * iterm_fireworks
773              
774             Show animated fireworks.
775              
776             =cut
777              
778              
779             # OSC 1337 ; RequestAttention=[value] ST
780 0     0 1   sub iterm_attention ( $value ) {
  0            
  0            
781 0           state $allowed = do {
782 0           my %hash = map { $_, 1 } qw( fireworks no once yes );
  0            
783 0           \%hash;
784             };
785 0 0         unless( exists $allowed->{$value} ) {
786 0           carp "iterm_attention argument can be one of <@{[ join ',', sort keys %$allowed ]}>, but you specified <$value>";
  0            
787 0           return;
788             }
789              
790 0           my $r = _osc_1337( "RequestAttention=$value" );
791 0           say _encode_seq( $r );
792 0           $r;
793             }
794 0     0 1   sub iterm_bounce_dock_icon { iterm_attention( 'yes' ) }
795 0     0 1   sub iterm_bounce_dock_icon_once { iterm_attention( 'once' ) }
796 0     0 1   sub iterm_unbounce_dock_icon { iterm_attention( 'no' ) }
797 0     0 1   sub iterm_fireworks { iterm_attention( 'fireworks' ) }
798              
799             =item * background_image_file
800              
801             OSC 1337 ; SetBackgroundImageFile=[base64] ST
802             The value of [base64] is a base64-encoded filename to display as a background image. If it is an empty string then the background image will be removed. User confirmation is required as a security measure.
803              
804             =item * report_cell_cell
805              
806             OSC 1337 ; ReportCellSize ST
807             The terminal responds with either:
808              
809             OSC 1337 ; ReportCellSize=[height];[width] ST
810             Or, in newer versions:
811              
812             OSC 1337 ; ReportCellSize=[height];[width];[scale] ST
813             [scale] gives the number of pixels (physical units) to points (logical units). 1.0 means non-retina, 2.0 means retina. It could take other values in the future.
814              
815             [height] and [width] are floating point values giving the size in points of a single character cell. For example:
816              
817             OSC 1337 ; ReportCellSize=17.50;8.00;2.0 ST
818              
819             =item * copy_to_pasteboard
820              
821             You can place a string in the system's pasteboard with this sequence:
822              
823             OSC 1337 ; Copy=:[base64] ST
824             Where [base64] is the base64-encoded string to copy to the pasteboard.
825              
826             =item * report_variable
827              
828             Each iTerm2 session has internal variables (as described in Scripting Fundamentals). This escape sequence reports a variable's value:
829              
830             OSC 1337 ; ReportVariable=[base64] ST
831             Where [base64] is a base64-encoded variable name, like session.name. It responds with:
832              
833             OSC 1337 ; ReportVariable=[base64] ST
834             Where [base64] is a base64-encoded value.
835              
836             https://iterm2.com/documentation-scripting-fundamentals.html
837              
838             =item * badge
839              
840             The badge may be set with the following control sequence:
841              
842             https://iterm2.com/documentation-badges.html
843              
844             OSC 1337 ; SetBadgeFormat=Base-64 encoded badge format ST
845             Here's an example that works in bash:
846              
847             # Set badge to show the current session name and git branch, if any is set.
848             printf "\e]1337;SetBadgeFormat=%s\a" \
849             $(echo -n "\(session.name) \(user.gitBranch)" | base64)
850              
851             =item * downloads
852              
853             https://iterm2.com/documentation-images.html
854              
855             The width and height are given as a number followed by a unit, or the word "auto".
856              
857             iTerm2 extends the xterm protocol with a set of proprietary escape sequences. In general, the pattern is:
858              
859             ESC ] 1337 ; key = value ^G
860             Whitespace is shown here for ease of reading: in practice, no spaces should be used.
861              
862             For file transfer and inline images, the code is:
863              
864             ESC ] 1337 ; File = [arguments] : base-64 encoded file contents ^G
865             The arguments are formatted as key=value with a semicolon between each key-value pair. They are described below:
866              
867             Key Description of value
868             name base-64 encoded filename. Defaults to "Unnamed file".
869             size File size in bytes. The file transfer will be canceled if this size is exceeded.
870             width Optional. Width to render. See notes below.
871             height Optional. Height to render. See notes below.
872             preserveAspectRatio Optional. If set to 0, then the image's inherent aspect ratio will not be respected; otherwise, it will fill the specified width and height as much as possible without stretching. Defaults to 1.
873             inline Optional. If set to 1, the file will be displayed inline. Otherwise, it will be downloaded with no visual representation in the terminal session. Defaults to 0.
874             N: N character cells.
875             Npx: N pixels.
876             N%: N percent of the session's width or height.
877             auto: The image's inherent size will be used to determine an appropriate dimension.
878             More on File Transfers
879             By omitting the inline argument (or setting its value to 0), files will be downloaded and saved in the Downloads folder instead of being displayed inline. Any kind of file may be downloaded, but only images will display inline. Any image format that macOS supports will display inline, including PDF, PICT, EPS, or any number of bitmap data formats (PNG, GIF, etc.). A new menu item titled Downloads will be added to the menu bar after a download begins, where progress can be monitored and the file can be located, opened, or removed.
880              
881             If the file's size exceeds the declared size, the transfer may be canceled. This is a security measure to prevent a download gone wrong from using unbounded memory.
882              
883             =item * uploads
884              
885             To request the user select one or more files to upload, send:
886              
887             OSC 1337 ; RequestUpload=format=[type] ST
888             In the future the [type] may be configurable, but for now it must always be tgz, which is a tar and gzipped file.
889              
890             When iTerm2 receives this it will respond with a status of ok or abort followed by a newline. If the status is ok then it will be followed by a base-64 encoded tar.gz file.
891              
892             If the user selects multiple files they will be placed in a directory within the tar file.
893              
894             =item * set_touchbar_key_levels
895              
896             You can configure touch bar key labels for function keys and for the "status" button. The code used is:
897              
898             OSC 1337 ; SetKeyLabel=[key]=[value] ST
899             Where [key] is one of F1, F2, ..., F24, to adjust a function key label; or it can be status to adjust the touch bar status button. You can also save and restore sets of key labels using a stack. To push the current key labels on the stack use:
900              
901             OSC 1337 ; PushKeyLabels ST
902             To pop them:
903              
904             OSC 1337 ; PopKeyLabels ST
905             You can optionally label the entry in the stack when you push so that pop will pop multiple sets of key labels if needed. This is useful if a program crashes or an ssh session exits unexpectedly. The corresponding codes with labels are:
906              
907             OSC 1337 ; PushKeyLabels=[label] ST
908             OSC 1337 ; PopKeyLabels=[label] ST
909             Where [label] is an ASCII string that works best if it is unique in the stack.
910              
911             =item * unicode_version
912              
913             iTerm2 by default uses Unicode 9's width tables. The user can opt to use Unicode 8's tables with a preference (for backward compatibility with older locale databases). Since not all apps will be updated at the same time, you can tell iTerm2 to use a particular set of width tables with:
914              
915             OSC 1337 ; UnicodeVersion=[n] ST
916             Where [n] is 8 or 9
917              
918             You can push the current value on a stack and pop it off to return to the previous value by setting n to push or pop. Optionally, you may affix a label after push by setting n to something like push mylabel. This attaches a label to that stack entry. When you pop the same label, entries will be popped until that one is found. Set n to pop mylabel to effect this. This is useful if a program crashes or an ssh session ends unexpectedly.
919              
920             =back
921              
922             =head1 SEE ALSO
923              
924             =over 4
925              
926             =item * Everything you never wanted to know about ANSI escape codes https://notes.burke.libbey.me/ansi-escape-codes/
927              
928             =item * https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
929              
930             =item * iTerm2 ANSI codes https://iterm2.com/documentation-escape-codes.html
931              
932             =back
933              
934             =head1 SOURCE AVAILABILITY
935              
936             This source is in Github:
937              
938             http://github.com/briandfoy/antsy
939              
940             =head1 AUTHOR
941              
942             brian d foy, C<< >>
943              
944             =head1 COPYRIGHT AND LICENSE
945              
946             Copyright © 2021-2025, brian d foy, All Rights Reserved.
947              
948             You may redistribute this under the terms of the Artistic License 2.0.
949              
950             =cut
951              
952             1;