terminal_rb 0.12.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/examples/bbcode.rb +5 -4
- data/lib/terminal/ansi.rb +245 -61
- data/lib/terminal/input/key_event.rb +8 -8
- data/lib/terminal/input.rb +5 -5
- data/lib/terminal/rspec/helper.rb +1 -1
- data/lib/terminal/shell.rb +131 -0
- data/lib/terminal/text/char_width.rb +49 -13
- data/lib/terminal/text.rb +7 -7
- data/lib/terminal/version.rb +1 -1
- data/lib/terminal.rb +82 -41
- metadata +7 -6
- data/lib/terminal/ansi/attributes.rb +0 -206
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 107b7b65dc5f58b1178e01fc86adad127df49fd175e56f7e36d2bfb873fc17a9
|
|
4
|
+
data.tar.gz: dfbf4797df22ac2803034a85a00fce2c480e4530840abd0d2a900bfb98993db5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 115235b382d02c4c5242925e1bf1ff3b9928702b30682dd4a2964282b11df6339118da582e0eebc096806005f781a537688741eab2e94984db391abaf6b4ec72
|
|
7
|
+
data.tar.gz: 2718bf0147fcb7c3d84374f59c4f8ea4862c58dfd6982057196a78bd1f4308eb9c319a55ba3c41339a45a6fa994b1449b2cedb2e00ce6de5548dd3eaa5b98fa0
|
data/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Terminal.rb 
|
|
2
2
|
|
|
3
|
-
Terminal
|
|
3
|
+
Terminal.rb supports you with input and output on your terminal. Simple [BBCode](https://en.wikipedia.org/wiki/BBCode)-like markup for attributes and coloring, word-wise line breaks, and correct special key recognition enable you to implement your CLI app quickly and easily.
|
|
4
4
|
|
|
5
5
|
- Gem: [rubygems.org](https://rubygems.org/gems/terminal_rb)
|
|
6
6
|
- Source: [codeberg.org](https://codeberg.org/mblumtritt/Terminal.rb)
|
|
7
|
-
- Help: [rubydoc.info](https://rubydoc.info/gems/terminal_rb/
|
|
7
|
+
- Help: [rubydoc.info](https://rubydoc.info/gems/terminal_rb/index)
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
data/examples/bbcode.rb
CHANGED
|
@@ -7,12 +7,13 @@ Terminal.puts <<~TEXT
|
|
|
7
7
|
✅ [b bright_green]Terminal.rb::Ansi[/b] — BBCode:[/]
|
|
8
8
|
|
|
9
9
|
[b]Bold[/b] [\\b]...[\\/b] or [\\bold]...[\\/bold]
|
|
10
|
-
[
|
|
11
|
-
[i]Italic[/i] [\\i]...[\\/i] or [
|
|
10
|
+
[dim]Dim[/dim] [\\d]...[\\/d] or [\\dim]...[\\/dim]
|
|
11
|
+
[i]Italic[/i] [\\i]...[\\/i] or [\\italic]...[\\/italic]
|
|
12
|
+
[u]Underline[/u] [\\u]...[\\/u] or [\\|undeline]...[\\/undeline]
|
|
12
13
|
[inv]Invert[/inv] [\\inv]...[\\/inv] or [\\invert]...[\\/invert]
|
|
13
|
-
[strike]Strike[/strike] [\\strike]...[\\/strike]
|
|
14
14
|
[h]Hide[/h] [\\h]...[\\/h] or [\\hide]...[\\/hide] or [\\conceal]...[\\/conceal]
|
|
15
|
-
|
|
15
|
+
[strike]Strike[/strike] [\\strike]...[\\/strike]
|
|
16
|
+
[blink]Blink[/blink] [\\blink]...[\\/blink]
|
|
16
17
|
[u]Underline[/u] [\\u]...[\\/u] or [\\underline]...[\\/underline]
|
|
17
18
|
[uu]Double underline[/uu] [\\uu]...[\\/uu] or [\\double_underline]...[\\/double_underline]
|
|
18
19
|
[cu]Curly underline[/cu] [\\cu]...[\\/cu] or [\\curly_underline]...[\\/curly_underline]
|
data/lib/terminal/ansi.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Terminal
|
|
|
12
12
|
#
|
|
13
13
|
# @attribute [r] attributes
|
|
14
14
|
# @return [Array<Symbol>] all attribute names
|
|
15
|
-
def attributes = @
|
|
15
|
+
def attributes = @attributes.dup
|
|
16
16
|
|
|
17
17
|
# Supported 3/4-bit color names.
|
|
18
18
|
#
|
|
@@ -20,7 +20,7 @@ module Terminal
|
|
|
20
20
|
#
|
|
21
21
|
# @attribute [r] colors
|
|
22
22
|
# @return [Array<Symbol>] all color names
|
|
23
|
-
def colors = @
|
|
23
|
+
def colors = @colors.dup
|
|
24
24
|
|
|
25
25
|
# Supported basic 24-bit (Kitty compatible) color names.
|
|
26
26
|
#
|
|
@@ -99,10 +99,9 @@ module Terminal
|
|
|
99
99
|
.map do |arg|
|
|
100
100
|
case arg
|
|
101
101
|
when String
|
|
102
|
-
@
|
|
102
|
+
@attr_map[arg] || _invalid(arg)
|
|
103
103
|
when Symbol
|
|
104
|
-
@
|
|
105
|
-
_invalid(arg)
|
|
104
|
+
@attrs_map[arg] || _invalid(arg)
|
|
106
105
|
when (0..255)
|
|
107
106
|
"38;5;#{arg}"
|
|
108
107
|
when (256..511)
|
|
@@ -179,11 +178,7 @@ module Terminal
|
|
|
179
178
|
def try_convert(attributes, separator: ' ')
|
|
180
179
|
return unless attributes
|
|
181
180
|
return if (attributes = attributes.to_s.split(separator)).empty?
|
|
182
|
-
"\e[#{
|
|
183
|
-
attributes
|
|
184
|
-
.map! { @attr[_1] || @colors[_1] || _color(_1) || return }
|
|
185
|
-
.join(';')
|
|
186
|
-
}m"
|
|
181
|
+
"\e[#{attributes.map! { @attr_map[_1] || return }.join(';')}m"
|
|
187
182
|
end
|
|
188
183
|
|
|
189
184
|
# Test if all given attributes are valid.
|
|
@@ -196,9 +191,9 @@ module Terminal
|
|
|
196
191
|
attributes.all? do |arg|
|
|
197
192
|
case arg
|
|
198
193
|
when String
|
|
199
|
-
@
|
|
194
|
+
@attr_map[arg]
|
|
200
195
|
when Symbol
|
|
201
|
-
@
|
|
196
|
+
@attrs_map[arg]
|
|
202
197
|
when (0..767)
|
|
203
198
|
true
|
|
204
199
|
end
|
|
@@ -249,7 +244,7 @@ module Terminal
|
|
|
249
244
|
match = Regexp.last_match(1) or next match_str
|
|
250
245
|
next "[#{match[1..]}]" if match[0] == '\\'
|
|
251
246
|
next match_str if (match = match.split).empty?
|
|
252
|
-
next if match.all? { @
|
|
247
|
+
next if match.all? { @attr_map[_1] }
|
|
253
248
|
match_str
|
|
254
249
|
end
|
|
255
250
|
end
|
|
@@ -277,7 +272,7 @@ module Terminal
|
|
|
277
272
|
match = Regexp.last_match(1) or next match_str
|
|
278
273
|
next "[#{match[1..]}]" if match[0] == '\\'
|
|
279
274
|
next match_str if (match = match.split).empty?
|
|
280
|
-
next if match.all? { @
|
|
275
|
+
next if match.all? { @attr_map[_1] }
|
|
281
276
|
match_str
|
|
282
277
|
end
|
|
283
278
|
str.index("\e") ? str.gsub!(@re_test, '') : str
|
|
@@ -392,7 +387,7 @@ module Terminal
|
|
|
392
387
|
|
|
393
388
|
# Erase screen part.
|
|
394
389
|
#
|
|
395
|
-
# @param [:below, :above, :all, :scrollback]
|
|
390
|
+
# @param part [:below, :above, :all, :scrollback] screen part to erase
|
|
396
391
|
# @return (see cursor_up)
|
|
397
392
|
def screen_erase(part = :all)
|
|
398
393
|
"\e[#{
|
|
@@ -449,7 +444,7 @@ module Terminal
|
|
|
449
444
|
|
|
450
445
|
# Erase part of line.
|
|
451
446
|
#
|
|
452
|
-
# @param [:to_end, :to_start, :all]
|
|
447
|
+
# @param part [:to_end, :to_start, :all] line part to erase
|
|
453
448
|
# @return (see cursor_up)
|
|
454
449
|
def line_erase(part = :all)
|
|
455
450
|
"\e[#{
|
|
@@ -473,7 +468,7 @@ module Terminal
|
|
|
473
468
|
# Tabby,
|
|
474
469
|
# WezTerm.
|
|
475
470
|
#
|
|
476
|
-
# @param [#to_s]
|
|
471
|
+
# @param title [#to_s] text
|
|
477
472
|
# @return (see cursor_up)
|
|
478
473
|
def title(title) = "\e]0;#{title}\a"
|
|
479
474
|
|
|
@@ -486,8 +481,8 @@ module Terminal
|
|
|
486
481
|
# Tabby,
|
|
487
482
|
# WezTerm.
|
|
488
483
|
#
|
|
489
|
-
# @param [#to_s]
|
|
490
|
-
# @param [#to_s] text
|
|
484
|
+
# @param url [#to_s] URL to link to
|
|
485
|
+
# @param text [#to_s] text to display for the link
|
|
491
486
|
# @return (see cursor_up)
|
|
492
487
|
def link(url, text) = "\e]8;;#{url}\a#{text}\e]8;;\a"
|
|
493
488
|
|
|
@@ -502,18 +497,19 @@ module Terminal
|
|
|
502
497
|
# @example Half-height Greeting
|
|
503
498
|
# Terminal::Ansi.scale('Hello Ruby!', fracn: 1, fracd: 2, vertical: :centered)
|
|
504
499
|
#
|
|
505
|
-
# @param [#to_s]
|
|
506
|
-
#
|
|
500
|
+
# @param text [#to_s]
|
|
501
|
+
# text to scale
|
|
502
|
+
# @param scale [Integer, nil]
|
|
507
503
|
# overall scale size, range 1..7
|
|
508
|
-
# @param [Integer, nil]
|
|
504
|
+
# @param width [Integer, nil]
|
|
509
505
|
# with in cells, range 0..7
|
|
510
|
-
# @param [Integer, nil]
|
|
506
|
+
# @param fracn [Integer, nil]
|
|
511
507
|
# numerator for the fractional scale, range: 0..15
|
|
512
|
-
# @param [Integer, nil]
|
|
508
|
+
# @param fracd [Integer, nil]
|
|
513
509
|
# denominator for the fractional scale, range: 0..15, > fracn
|
|
514
|
-
# @param [:top, :bottom, :centered, nil]
|
|
510
|
+
# @param vertical [:top, :bottom, :centered, nil]
|
|
515
511
|
# vertical alignment to use for fractionally scaled text
|
|
516
|
-
# @param [:left, :right, :centered, nil]
|
|
512
|
+
# @param horizontal [:left, :right, :centered, nil]
|
|
517
513
|
# horizontal alignment to use for fractionally scaled text
|
|
518
514
|
# @return (see cursor_up)
|
|
519
515
|
def scale(
|
|
@@ -586,9 +582,9 @@ module Terminal
|
|
|
586
582
|
end
|
|
587
583
|
end
|
|
588
584
|
|
|
589
|
-
@cbase =
|
|
590
|
-
|
|
591
|
-
|
|
585
|
+
@cbase = { 'bg' => '48', 'on' => '48', 'ul' => '58' }
|
|
586
|
+
@cbase.default = '38'
|
|
587
|
+
@cbase.freeze
|
|
592
588
|
|
|
593
589
|
@re_test =
|
|
594
590
|
/
|
|
@@ -599,71 +595,259 @@ module Terminal
|
|
|
599
595
|
|
|
600
596
|
@re_bbcode = /(?:\[((?~[\[\]]))\])/
|
|
601
597
|
|
|
602
|
-
|
|
598
|
+
attr_map = {
|
|
599
|
+
'' => 'reset',
|
|
600
|
+
'1' => 'bold',
|
|
601
|
+
'2' => 'faint',
|
|
602
|
+
'3' => 'italic',
|
|
603
|
+
'4' => 'underline',
|
|
604
|
+
'5' => 'blink',
|
|
605
|
+
'6' => 'rapid_blink',
|
|
606
|
+
'7' => 'invert',
|
|
607
|
+
'8' => 'hide',
|
|
608
|
+
'9' => 'strike',
|
|
609
|
+
'10' => 'primary_font',
|
|
610
|
+
'11' => 'font1',
|
|
611
|
+
'12' => 'font2',
|
|
612
|
+
'13' => 'font3',
|
|
613
|
+
'14' => 'font4',
|
|
614
|
+
'15' => 'font5',
|
|
615
|
+
'16' => 'font6',
|
|
616
|
+
'17' => 'font7',
|
|
617
|
+
'18' => 'font8',
|
|
618
|
+
'19' => 'font9',
|
|
619
|
+
'20' => 'fraktur',
|
|
620
|
+
'21' => 'double_underline',
|
|
621
|
+
'22' => 'bold_off', # faint_off
|
|
622
|
+
'23' => 'italic_off', # fraktur_off
|
|
623
|
+
'24' => 'underline_off', # double_underline_off
|
|
624
|
+
'25' => 'blink_off', # rapid_blink_off
|
|
625
|
+
'26' => 'proportional',
|
|
626
|
+
'27' => 'invert_off',
|
|
627
|
+
'28' => 'hide_off',
|
|
628
|
+
'29' => 'strike_off',
|
|
629
|
+
# colors ...
|
|
630
|
+
'50' => 'proportional_off',
|
|
631
|
+
'51' => 'framed',
|
|
632
|
+
'52' => 'encircled',
|
|
633
|
+
'53' => 'overlined',
|
|
634
|
+
'54' => 'framed_off', # encircled_off
|
|
635
|
+
'55' => 'overlined_off',
|
|
636
|
+
# ...
|
|
637
|
+
'73' => 'superscript',
|
|
638
|
+
'74' => 'subscript',
|
|
639
|
+
'75' => 'superscript_off', # subscript_off
|
|
640
|
+
# special underline
|
|
641
|
+
'4:3' => 'curly_underline',
|
|
642
|
+
'4:4' => 'dotted_underline',
|
|
643
|
+
'4:5' => 'dashed_underline',
|
|
644
|
+
'4:0' => 'curly_underline_off' # dotted_underline_off, dashed_underline_off
|
|
645
|
+
}.invert
|
|
646
|
+
attr_alias = ->(t, s) { attr_map[t] = attr_map[s] }
|
|
647
|
+
|
|
648
|
+
clr_map = {
|
|
649
|
+
# foreground
|
|
650
|
+
'30' => 'black',
|
|
651
|
+
'31' => 'red',
|
|
652
|
+
'32' => 'green',
|
|
653
|
+
'33' => 'yellow',
|
|
654
|
+
'34' => 'blue',
|
|
655
|
+
'35' => 'magenta',
|
|
656
|
+
'36' => 'cyan',
|
|
657
|
+
'37' => 'white',
|
|
658
|
+
'39' => 'default', # reset
|
|
659
|
+
# background
|
|
660
|
+
'40' => 'on_black',
|
|
661
|
+
'41' => 'on_red',
|
|
662
|
+
'42' => 'on_green',
|
|
663
|
+
'43' => 'on_yellow',
|
|
664
|
+
'44' => 'on_blue',
|
|
665
|
+
'45' => 'on_magenta',
|
|
666
|
+
'46' => 'on_cyan',
|
|
667
|
+
'47' => 'on_white',
|
|
668
|
+
'49' => 'on_default', # reset
|
|
669
|
+
# underline
|
|
670
|
+
'58;2;0;0;0' => 'ul_black',
|
|
671
|
+
'58;2;0;0;128' => 'ul_blue',
|
|
672
|
+
'58;2;0;0;255' => 'ul_bright_blue',
|
|
673
|
+
'58;2;0;128;0' => 'ul_green',
|
|
674
|
+
'58;2;0;128;128' => 'ul_cyan',
|
|
675
|
+
'58;2;0;255;0' => 'ul_bright_green',
|
|
676
|
+
'58;2;0;255;255' => 'ul_bright_cyan',
|
|
677
|
+
'58;2;128;0;0' => 'ul_red',
|
|
678
|
+
'58;2;128;0;128' => 'ul_magenta',
|
|
679
|
+
'58;2;128;128;0' => 'ul_yellow',
|
|
680
|
+
'58;2;128;128;128' => 'ul_white',
|
|
681
|
+
'58;2;255;0;0' => 'ul_bright_red',
|
|
682
|
+
'58;2;255;0;255' => 'ul_bright_magenta',
|
|
683
|
+
'58;2;255;255;0' => 'ul_bright_yellow',
|
|
684
|
+
'58;2;255;255;255' => 'ul_bright_white',
|
|
685
|
+
'58;2;64;64;64' => 'ul_bright_black',
|
|
686
|
+
'59' => 'ul_default', # reset
|
|
687
|
+
# bright foreground
|
|
688
|
+
'90' => 'bright_black',
|
|
689
|
+
'91' => 'bright_red',
|
|
690
|
+
'92' => 'bright_green',
|
|
691
|
+
'93' => 'bright_yellow',
|
|
692
|
+
'94' => 'bright_blue',
|
|
693
|
+
'95' => 'bright_magenta',
|
|
694
|
+
'96' => 'bright_cyan',
|
|
695
|
+
'97' => 'bright_white',
|
|
696
|
+
# bright background
|
|
697
|
+
'100' => 'on_bright_black',
|
|
698
|
+
'101' => 'on_bright_red',
|
|
699
|
+
'102' => 'on_bright_green',
|
|
700
|
+
'103' => 'on_bright_yellow',
|
|
701
|
+
'104' => 'on_bright_blue',
|
|
702
|
+
'105' => 'on_bright_magenta',
|
|
703
|
+
'106' => 'on_bright_cyan',
|
|
704
|
+
'107' => 'on_bright_white'
|
|
705
|
+
}.invert
|
|
706
|
+
clr_alias = ->(t, s) { clr_map[t] = clr_map[s] }
|
|
707
|
+
|
|
708
|
+
%w[black red green yellow blue magenta cyan white].each do |name|
|
|
709
|
+
clr_alias["fg_#{name}", name]
|
|
710
|
+
clr_alias["bg_#{name}", "on_#{name}"]
|
|
711
|
+
clr_alias["fg_bright_#{name}", "bright_#{name}"]
|
|
712
|
+
clr_alias["bg_bright_#{name}", "on_bright_#{name}"]
|
|
713
|
+
end
|
|
714
|
+
clr_alias['fg_default', 'default']
|
|
715
|
+
clr_alias['bg_default', 'on_default']
|
|
716
|
+
|
|
717
|
+
attr_alias['faint_off', 'bold_off']
|
|
718
|
+
attr_alias['fraktur_off', 'italic_off']
|
|
719
|
+
attr_alias['double_underline_off', 'underline_off']
|
|
720
|
+
attr_alias['rapid_blink_off', 'blink_off']
|
|
721
|
+
attr_alias['encircled_off', 'framed_off']
|
|
722
|
+
attr_alias['subscript_off', 'superscript_off']
|
|
723
|
+
attr_alias['dotted_underline_off', 'curly_underline_off']
|
|
724
|
+
attr_alias['dashed_underline_off', 'curly_underline_off']
|
|
725
|
+
|
|
726
|
+
# extra aliases:
|
|
727
|
+
attr_alias['off', 'reset']
|
|
728
|
+
attr_alias['dim', 'faint']
|
|
729
|
+
attr_alias['dim_off', 'faint_off']
|
|
730
|
+
attr_alias['conceal', 'hide']
|
|
731
|
+
attr_alias['conceal_off', 'hide_off']
|
|
732
|
+
attr_alias['reveal', 'hide_off']
|
|
733
|
+
attr_alias['spacing', 'proportional']
|
|
734
|
+
attr_alias['spacing_off', 'proportional_off']
|
|
735
|
+
|
|
736
|
+
# shortcuts:
|
|
737
|
+
attr_alias['b', 'bold']
|
|
738
|
+
attr_alias['d', 'dim']
|
|
739
|
+
attr_alias['i', 'italic']
|
|
740
|
+
attr_alias['u', 'underline']
|
|
741
|
+
attr_alias['inv', 'invert']
|
|
742
|
+
attr_alias['h', 'hide']
|
|
743
|
+
attr_alias['s', 'strike']
|
|
744
|
+
attr_alias['uu', 'double_underline']
|
|
745
|
+
attr_alias['ovr', 'overlined']
|
|
746
|
+
attr_alias['sup', 'superscript']
|
|
747
|
+
attr_alias['sub', 'subscript']
|
|
748
|
+
attr_alias['cu', 'curly_underline']
|
|
749
|
+
attr_alias['dau', 'dashed_underline']
|
|
750
|
+
attr_alias['dou', 'dotted_underline']
|
|
751
|
+
|
|
752
|
+
@colors = clr_map.keys.map!(&:to_sym).sort!.freeze
|
|
753
|
+
@attributes = attr_map.keys.map!(&:to_sym).sort!.freeze
|
|
754
|
+
|
|
755
|
+
# shortcuts disable:
|
|
756
|
+
attr_map.keys.each do |n|
|
|
757
|
+
attr_alias["/#{n.delete_suffix('_off')}", n] if n.end_with?('_off')
|
|
758
|
+
end
|
|
759
|
+
attr_alias['/b', 'bold_off']
|
|
760
|
+
attr_alias['/d', 'dim_off']
|
|
761
|
+
attr_alias['/i', 'italic_off']
|
|
762
|
+
attr_alias['/u', 'underline_off']
|
|
763
|
+
attr_alias['/inv', 'invert_off']
|
|
764
|
+
attr_alias['/h', 'hide_off']
|
|
765
|
+
attr_alias['/s', 'strike_off']
|
|
766
|
+
attr_alias['/uu', 'double_underline_off']
|
|
767
|
+
attr_alias['/ovr', 'overlined_off']
|
|
768
|
+
attr_alias['/sup', 'superscript_off']
|
|
769
|
+
attr_alias['/sub', 'subscript_off']
|
|
770
|
+
attr_alias['/cu', 'curly_underline_off']
|
|
771
|
+
attr_alias['/dau', 'dashed_underline_off']
|
|
772
|
+
attr_alias['/dou', 'dotted_underline_off']
|
|
773
|
+
|
|
774
|
+
# additional shortcuts disable:
|
|
775
|
+
attr_alias['/', 'reset']
|
|
776
|
+
attr_map['/fg'] = clr_map['default']
|
|
777
|
+
attr_map['/bg'] = clr_map['on_default']
|
|
778
|
+
attr_map['/ul'] = clr_map['ul_default']
|
|
779
|
+
|
|
780
|
+
@attr_map = Hash.new { _color(_2) }
|
|
781
|
+
attr_map.merge!(clr_map).keys.sort!.each { @attr_map[_1] = attr_map[_1] }
|
|
782
|
+
@attr_map.freeze
|
|
783
|
+
|
|
784
|
+
@attrs_map = @attr_map.transform_keys(&:to_sym)
|
|
785
|
+
@attrs_map.default_proc = @attr_map.default_proc
|
|
786
|
+
@attrs_map.compare_by_identity.freeze
|
|
603
787
|
|
|
604
788
|
autoload :NAMED_COLORS, "#{__dir__}/ansi/named_colors.rb"
|
|
605
789
|
private_constant :NAMED_COLORS
|
|
606
790
|
|
|
607
|
-
#
|
|
791
|
+
# @private
|
|
608
792
|
RESET = self[:reset].freeze
|
|
609
793
|
|
|
610
|
-
#
|
|
794
|
+
# @private
|
|
611
795
|
FULL_RESET = "\ec"
|
|
612
796
|
|
|
613
|
-
#
|
|
797
|
+
# @private
|
|
614
798
|
CURSOR_HOME = cursor_pos(nil, nil).freeze
|
|
615
|
-
#
|
|
799
|
+
# @private
|
|
616
800
|
CURSOR_FIRST_ROW = cursor_pos(1).freeze
|
|
617
|
-
#
|
|
801
|
+
# @private
|
|
618
802
|
CURSOR_FIRST_COLUMN = cursor_column(1).freeze
|
|
619
803
|
|
|
620
|
-
#
|
|
804
|
+
# @private
|
|
621
805
|
CURSOR_SHOW = "\e[?25h"
|
|
622
|
-
#
|
|
806
|
+
# @private
|
|
623
807
|
CURSOR_HIDE = "\e[?25l"
|
|
624
808
|
|
|
625
809
|
# @comment CURSOR_POS_SAVE_SCO = "\e[s"
|
|
626
810
|
# @comment CURSOR_POS_SAVE_DEC = "\e7"
|
|
627
|
-
#
|
|
811
|
+
# @private
|
|
628
812
|
CURSOR_POS_SAVE = "\e7"
|
|
629
813
|
|
|
630
814
|
# @comment CURSOR_POS_RESTORE_SCO = "\e[u"
|
|
631
815
|
# @comment CURSOR_POS_RESTORE_DEC = "\e8"
|
|
632
|
-
#
|
|
816
|
+
# @private
|
|
633
817
|
CURSOR_POS_RESTORE = "\e8"
|
|
634
818
|
|
|
635
|
-
#
|
|
819
|
+
# @private
|
|
636
820
|
SCREEN_ERASE = screen_erase.freeze
|
|
637
|
-
#
|
|
821
|
+
# @private
|
|
638
822
|
SCREEN_ERASE_BELOW = screen_erase(:below).freeze
|
|
639
|
-
#
|
|
823
|
+
# @private
|
|
640
824
|
SCREEN_ERASE_ABOVE = screen_erase(:above).freeze
|
|
641
|
-
#
|
|
825
|
+
# @private
|
|
642
826
|
SCREEN_ERASE_SCROLLBACK = screen_erase(:scrollback).freeze
|
|
643
827
|
|
|
644
|
-
#
|
|
828
|
+
# @private
|
|
645
829
|
SCREEN_SAVE = "\e[?47h"
|
|
646
|
-
#
|
|
830
|
+
# @private
|
|
647
831
|
SCREEN_RESTORE = "\e[?47l"
|
|
648
832
|
|
|
649
|
-
#
|
|
833
|
+
# @private
|
|
650
834
|
# @comment at least Kitty requires CURSOR_HOME too
|
|
651
835
|
SCREEN_ALTERNATE = "\e[?1049h#{CURSOR_HOME}".freeze
|
|
652
|
-
#
|
|
836
|
+
# @private
|
|
653
837
|
SCREEN_ALTERNATE_OFF = "\e[?1049l"
|
|
654
838
|
|
|
655
|
-
#
|
|
839
|
+
# @private
|
|
656
840
|
SCREEN_REVERSE_MODE_ON = "\e[?5h"
|
|
657
|
-
#
|
|
841
|
+
# @private
|
|
658
842
|
SCREEN_REVERSE_MODE_OFF = "\e[?5l"
|
|
659
843
|
|
|
660
|
-
#
|
|
844
|
+
# @private
|
|
661
845
|
LINE_ERASE = line_erase.freeze
|
|
662
|
-
#
|
|
846
|
+
# @private
|
|
663
847
|
LINE_ERASE_TO_END = line_erase(:to_end).freeze
|
|
664
|
-
#
|
|
848
|
+
# @private
|
|
665
849
|
LINE_ERASE_TO_START = line_erase(:to_start).freeze
|
|
666
|
-
#
|
|
850
|
+
# @private
|
|
667
851
|
LINE_ERASE_PREV = "#{cursor_prev_line(nil)}#{LINE_ERASE}".freeze
|
|
668
852
|
|
|
669
853
|
# @comment seems not widely supported:
|
|
@@ -689,14 +873,6 @@ module Terminal
|
|
|
689
873
|
#
|
|
690
874
|
# def set_scroll_region(top = nil, bottom = nil) = "\e[#{top};#{bottom}r"
|
|
691
875
|
|
|
692
|
-
# @comment TODO:
|
|
693
|
-
# https://sw.kovidgoyal.net/kitty/desktop-notifications
|
|
694
|
-
# https://sw.kovidgoyal.net/kitty/pointer-shapes
|
|
695
|
-
# https://sw.kovidgoyal.net/kitty/unscroll
|
|
696
|
-
# https://sw.kovidgoyal.net/kitty/color-stack
|
|
697
|
-
# https://sw.kovidgoyal.net/kitty/deccara
|
|
698
|
-
# https://sw.kovidgoyal.net/kitty/clipboard
|
|
699
|
-
|
|
700
876
|
# @comment other:
|
|
701
877
|
# "\eE" same as "\r\n"
|
|
702
878
|
# "\eD" same as "\n" but preserves X coord
|
|
@@ -705,5 +881,13 @@ module Terminal
|
|
|
705
881
|
# "\e[21t report window’s title as ESC ] l title ESC \"
|
|
706
882
|
# "\e[?1004h" report focus lost "\e[O" and focus get "\e[I"
|
|
707
883
|
# (disable by "\e[?1004l")
|
|
884
|
+
|
|
885
|
+
# @comment TODO:
|
|
886
|
+
# https://sw.kovidgoyal.net/kitty/desktop-notifications
|
|
887
|
+
# https://sw.kovidgoyal.net/kitty/pointer-shapes
|
|
888
|
+
# https://sw.kovidgoyal.net/kitty/unscroll
|
|
889
|
+
# https://sw.kovidgoyal.net/kitty/color-stack
|
|
890
|
+
# https://sw.kovidgoyal.net/kitty/deccara
|
|
891
|
+
# https://sw.kovidgoyal.net/kitty/clipboard
|
|
708
892
|
end
|
|
709
893
|
end
|
|
@@ -7,7 +7,7 @@ module Terminal
|
|
|
7
7
|
class KeyEvent
|
|
8
8
|
class << self
|
|
9
9
|
# @attribute [w] caching
|
|
10
|
-
# @return [true, false] whether
|
|
10
|
+
# @return [true, false] whether {KeyEvent}s should be cached
|
|
11
11
|
def caching = !!@cache
|
|
12
12
|
|
|
13
13
|
# @attribute [w] caching
|
|
@@ -21,7 +21,7 @@ module Terminal
|
|
|
21
21
|
|
|
22
22
|
# Translate a keyboard input string into a related KeyEvent
|
|
23
23
|
#
|
|
24
|
-
# @param [String]
|
|
24
|
+
# @param raw [String] keyboard input
|
|
25
25
|
# @return [KeyEvent] related key event
|
|
26
26
|
def [](raw)
|
|
27
27
|
return new(raw, *@single_key[raw.ord]) if raw.size == 1
|
|
@@ -52,7 +52,7 @@ module Terminal
|
|
|
52
52
|
unknown(raw)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
#
|
|
55
|
+
# @private
|
|
56
56
|
def new(raw, key = raw, modifier = 0, extra = nil)
|
|
57
57
|
@cache ? (@cache[raw] ||= super.freeze) : super.freeze
|
|
58
58
|
end
|
|
@@ -164,7 +164,7 @@ module Terminal
|
|
|
164
164
|
attr_reader :modifier
|
|
165
165
|
|
|
166
166
|
# @comment for mouse events
|
|
167
|
-
#
|
|
167
|
+
# @private
|
|
168
168
|
attr_reader :extra
|
|
169
169
|
|
|
170
170
|
# Name of the key event.
|
|
@@ -188,16 +188,16 @@ module Terminal
|
|
|
188
188
|
# @return [Array<Symbol, String>] all pressed keys
|
|
189
189
|
def to_a = @ary.dup
|
|
190
190
|
|
|
191
|
-
#
|
|
191
|
+
# @private
|
|
192
192
|
def to_ary = simple? ? [@raw] : [@raw, @name]
|
|
193
193
|
|
|
194
|
-
#
|
|
194
|
+
# @private
|
|
195
195
|
def to_s = @name.dup
|
|
196
196
|
|
|
197
|
-
#
|
|
197
|
+
# @private
|
|
198
198
|
def inspect = "<#{self.class.name} #{to_ary.map(&:inspect).join(' ')}>"
|
|
199
199
|
|
|
200
|
-
#
|
|
200
|
+
# @private
|
|
201
201
|
def freeze
|
|
202
202
|
@raw.freeze
|
|
203
203
|
@key.freeze
|
data/lib/terminal/input.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Terminal
|
|
|
28
28
|
#
|
|
29
29
|
# @deprecated Use rather {read_key_event} for better input handling.
|
|
30
30
|
#
|
|
31
|
-
# @param [:named, :raw, :both]
|
|
31
|
+
# @param mode [:named, :raw, :both] modifies the result
|
|
32
32
|
# @return [String] key code ("as is") in `:raw` mode
|
|
33
33
|
# @return [String] key name in `:named` mode
|
|
34
34
|
# @return [[String, String]] key code and key name in `:both` mode
|
|
@@ -64,8 +64,8 @@ module Terminal
|
|
|
64
64
|
return :dumb if im == 'dumb'
|
|
65
65
|
return :legacy if im == 'legacy'
|
|
66
66
|
return :dumb unless STDIN.tty?
|
|
67
|
-
if ansi? &&
|
|
68
|
-
at_exit {
|
|
67
|
+
if ansi? && raw_write("\e[>1u\e[?u\e[c") && csi_u?
|
|
68
|
+
at_exit { raw_write("\e[<u") }
|
|
69
69
|
return :csi_u
|
|
70
70
|
end
|
|
71
71
|
:legacy
|
|
@@ -99,10 +99,10 @@ module Terminal
|
|
|
99
99
|
# urxvt: '1015'
|
|
100
100
|
# pixel: '1016'
|
|
101
101
|
opts = each_move ? '1000;1003;1006;1015' : '1000;1006;1015'
|
|
102
|
-
opts =
|
|
102
|
+
opts = raw_write("\e[?#{opts}h") ? "\e[?#{opts}l" : nil
|
|
103
103
|
read_tty
|
|
104
104
|
ensure
|
|
105
|
-
|
|
105
|
+
raw_write(opts) if opts
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def read_tty
|
|
@@ -53,7 +53,7 @@ RSpec.shared_context 'with Terminal.rb' do |ansi: true, application: :kitty, col
|
|
|
53
53
|
nil
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
allow(Terminal).to receive(:
|
|
56
|
+
allow(Terminal).to receive(:raw_write) do |object|
|
|
57
57
|
stdout.push(object = object.to_s)
|
|
58
58
|
object.bytesize
|
|
59
59
|
end
|