terminal_rb 0.12.1 → 0.13.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 +1 -1
- data/examples/bbcode.rb +5 -4
- data/lib/terminal/ansi.rb +209 -26
- data/lib/terminal/input/{as_key_event.rb → key_event.rb} +135 -22
- data/lib/terminal/input.rb +8 -123
- data/lib/terminal/rspec/helper.rb +18 -12
- data/lib/terminal/version.rb +1 -1
- metadata +5 -7
- 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: 756d1e0e016472a063f9d64650f4731ef6e8fe272d6a84c4e001119f050af3ea
|
4
|
+
data.tar.gz: 74c24ba64e08e6dc79605c17b0ded59ecb8784a45f95dbe5be7f231c889fdab7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68bb81c425cb5df44650acc351a28cbbb3eccaea53b405167f1207ba3dc528093de6322bac087fad9301da7470711b4cd399f120233637e9b92f1727e9e2d4c9
|
7
|
+
data.tar.gz: 9e855ec0401d22c615fd6ff25e2adae7717ecbf3578ea40425e5ef580b9520ee23130c8d49814034f682590166d2319070c17c18407962fc8782b18c1fffe4fa
|
data/README.md
CHANGED
@@ -14,7 +14,7 @@ Terminal access with super fast ANSI control codes support and [BBCode-like](htt
|
|
14
14
|
- [NO_COLOR convention](https://no-color.org) support
|
15
15
|
- markup of text attributes and colors using a [BBCode](https://en.wikipedia.org/wiki/BBCode)-like syntax
|
16
16
|
- calculation for correct display width of strings containing Unicdode chars inclusive emojis
|
17
|
-
-
|
17
|
+
- word-wise line break generator
|
18
18
|
- supports [CSIu protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol)
|
19
19
|
|
20
20
|
## Examples
|
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
|
@@ -586,9 +581,9 @@ module Terminal
|
|
586
581
|
end
|
587
582
|
end
|
588
583
|
|
589
|
-
@cbase =
|
590
|
-
|
591
|
-
|
584
|
+
@cbase = { 'bg' => '48', 'on' => '48', 'ul' => '58' }
|
585
|
+
@cbase.default = '38'
|
586
|
+
@cbase.freeze
|
592
587
|
|
593
588
|
@re_test =
|
594
589
|
/
|
@@ -599,7 +594,195 @@ module Terminal
|
|
599
594
|
|
600
595
|
@re_bbcode = /(?:\[((?~[\[\]]))\])/
|
601
596
|
|
602
|
-
|
597
|
+
attr_map = {
|
598
|
+
'' => 'reset',
|
599
|
+
'1' => 'bold',
|
600
|
+
'2' => 'faint',
|
601
|
+
'3' => 'italic',
|
602
|
+
'4' => 'underline',
|
603
|
+
'5' => 'blink',
|
604
|
+
'6' => 'rapid_blink',
|
605
|
+
'7' => 'invert',
|
606
|
+
'8' => 'hide',
|
607
|
+
'9' => 'strike',
|
608
|
+
'10' => 'primary_font',
|
609
|
+
'11' => 'font1',
|
610
|
+
'12' => 'font2',
|
611
|
+
'13' => 'font3',
|
612
|
+
'14' => 'font4',
|
613
|
+
'15' => 'font5',
|
614
|
+
'16' => 'font6',
|
615
|
+
'17' => 'font7',
|
616
|
+
'18' => 'font8',
|
617
|
+
'19' => 'font9',
|
618
|
+
'20' => 'fraktur',
|
619
|
+
'21' => 'double_underline',
|
620
|
+
'22' => 'bold_off', # faint_off
|
621
|
+
'23' => 'italic_off', # fraktur_off
|
622
|
+
'24' => 'underline_off', # double_underline_off
|
623
|
+
'25' => 'blink_off', # rapid_blink_off
|
624
|
+
'26' => 'proportional',
|
625
|
+
'27' => 'invert_off',
|
626
|
+
'28' => 'hide_off',
|
627
|
+
'29' => 'strike_off',
|
628
|
+
# colors ...
|
629
|
+
'50' => 'proportional_off',
|
630
|
+
'51' => 'framed',
|
631
|
+
'52' => 'encircled',
|
632
|
+
'53' => 'overlined',
|
633
|
+
'54' => 'framed_off', # encircled_off
|
634
|
+
'55' => 'overlined_off',
|
635
|
+
# ...
|
636
|
+
'73' => 'superscript',
|
637
|
+
'74' => 'subscript',
|
638
|
+
'75' => 'superscript_off', # subscript_off
|
639
|
+
# special underline
|
640
|
+
'4:3' => 'curly_underline',
|
641
|
+
'4:4' => 'dotted_underline',
|
642
|
+
'4:5' => 'dashed_underline',
|
643
|
+
'4:0' => 'curly_underline_off' # dotted_underline_off, dashed_underline_off
|
644
|
+
}.invert
|
645
|
+
attr_alias = ->(t, s) { attr_map[t] = attr_map[s] }
|
646
|
+
|
647
|
+
clr_map = {
|
648
|
+
# foreground
|
649
|
+
'30' => 'black',
|
650
|
+
'31' => 'red',
|
651
|
+
'32' => 'green',
|
652
|
+
'33' => 'yellow',
|
653
|
+
'34' => 'blue',
|
654
|
+
'35' => 'magenta',
|
655
|
+
'36' => 'cyan',
|
656
|
+
'37' => 'white',
|
657
|
+
'39' => 'default', # reset
|
658
|
+
# background
|
659
|
+
'40' => 'on_black',
|
660
|
+
'41' => 'on_red',
|
661
|
+
'42' => 'on_green',
|
662
|
+
'43' => 'on_yellow',
|
663
|
+
'44' => 'on_blue',
|
664
|
+
'45' => 'on_magenta',
|
665
|
+
'46' => 'on_cyan',
|
666
|
+
'47' => 'on_white',
|
667
|
+
'49' => 'on_default', # reset
|
668
|
+
# underline
|
669
|
+
'58;2;0;0;0' => 'ul_black',
|
670
|
+
'58;2;0;0;128' => 'ul_blue',
|
671
|
+
'58;2;0;0;255' => 'ul_bright_blue',
|
672
|
+
'58;2;0;128;0' => 'ul_green',
|
673
|
+
'58;2;0;128;128' => 'ul_cyan',
|
674
|
+
'58;2;0;255;0' => 'ul_bright_green',
|
675
|
+
'58;2;0;255;255' => 'ul_bright_cyan',
|
676
|
+
'58;2;128;0;0' => 'ul_red',
|
677
|
+
'58;2;128;0;128' => 'ul_magenta',
|
678
|
+
'58;2;128;128;0' => 'ul_yellow',
|
679
|
+
'58;2;128;128;128' => 'ul_white',
|
680
|
+
'58;2;255;0;0' => 'ul_bright_red',
|
681
|
+
'58;2;255;0;255' => 'ul_bright_magenta',
|
682
|
+
'58;2;255;255;0' => 'ul_bright_yellow',
|
683
|
+
'58;2;255;255;255' => 'ul_bright_white',
|
684
|
+
'58;2;64;64;64' => 'ul_bright_black',
|
685
|
+
'59' => 'ul_default', # reset
|
686
|
+
# bright foreground
|
687
|
+
'90' => 'bright_black',
|
688
|
+
'91' => 'bright_red',
|
689
|
+
'92' => 'bright_green',
|
690
|
+
'93' => 'bright_yellow',
|
691
|
+
'94' => 'bright_blue',
|
692
|
+
'95' => 'bright_magenta',
|
693
|
+
'96' => 'bright_cyan',
|
694
|
+
'97' => 'bright_white',
|
695
|
+
# bright background
|
696
|
+
'100' => 'on_bright_black',
|
697
|
+
'101' => 'on_bright_red',
|
698
|
+
'102' => 'on_bright_green',
|
699
|
+
'103' => 'on_bright_yellow',
|
700
|
+
'104' => 'on_bright_blue',
|
701
|
+
'105' => 'on_bright_magenta',
|
702
|
+
'106' => 'on_bright_cyan',
|
703
|
+
'107' => 'on_bright_white'
|
704
|
+
}.invert
|
705
|
+
clr_alias = ->(t, s) { clr_map[t] = clr_map[s] }
|
706
|
+
|
707
|
+
%w[black red green yellow blue magenta cyan white].each do |name|
|
708
|
+
clr_alias["fg_#{name}", name]
|
709
|
+
clr_alias["bg_#{name}", "on_#{name}"]
|
710
|
+
clr_alias["fg_bright_#{name}", "bright_#{name}"]
|
711
|
+
clr_alias["bg_bright_#{name}", "on_bright_#{name}"]
|
712
|
+
end
|
713
|
+
clr_alias['fg_default', 'default']
|
714
|
+
clr_alias['bg_default', 'on_default']
|
715
|
+
|
716
|
+
attr_alias['faint_off', 'bold_off']
|
717
|
+
attr_alias['fraktur_off', 'italic_off']
|
718
|
+
attr_alias['double_underline_off', 'underline_off']
|
719
|
+
attr_alias['rapid_blink_off', 'blink_off']
|
720
|
+
attr_alias['encircled_off', 'framed_off']
|
721
|
+
attr_alias['subscript_off', 'superscript_off']
|
722
|
+
attr_alias['dotted_underline_off', 'curly_underline_off']
|
723
|
+
attr_alias['dashed_underline_off', 'curly_underline_off']
|
724
|
+
|
725
|
+
# extra aliases:
|
726
|
+
attr_alias['off', 'reset']
|
727
|
+
attr_alias['dim', 'faint']
|
728
|
+
attr_alias['dim_off', 'faint_off']
|
729
|
+
attr_alias['conceal', 'hide']
|
730
|
+
attr_alias['conceal_off', 'hide_off']
|
731
|
+
attr_alias['reveal', 'hide_off']
|
732
|
+
attr_alias['spacing', 'proportional']
|
733
|
+
attr_alias['spacing_off', 'proportional_off']
|
734
|
+
|
735
|
+
# shortcuts:
|
736
|
+
attr_alias['b', 'bold']
|
737
|
+
attr_alias['d', 'dim']
|
738
|
+
attr_alias['i', 'italic']
|
739
|
+
attr_alias['u', 'underline']
|
740
|
+
attr_alias['inv', 'invert']
|
741
|
+
attr_alias['h', 'hide']
|
742
|
+
attr_alias['s', 'strike']
|
743
|
+
attr_alias['uu', 'double_underline']
|
744
|
+
attr_alias['ovr', 'overlined']
|
745
|
+
attr_alias['sup', 'superscript']
|
746
|
+
attr_alias['sub', 'subscript']
|
747
|
+
attr_alias['cu', 'curly_underline']
|
748
|
+
attr_alias['dau', 'dashed_underline']
|
749
|
+
attr_alias['dou', 'dotted_underline']
|
750
|
+
|
751
|
+
@colors = clr_map.keys.map!(&:to_sym).sort!.freeze
|
752
|
+
@attributes = attr_map.keys.map!(&:to_sym).sort!.freeze
|
753
|
+
|
754
|
+
# shortcuts disable:
|
755
|
+
attr_map.keys.each do |n|
|
756
|
+
attr_alias["/#{n.delete_suffix('_off')}", n] if n.end_with?('_off')
|
757
|
+
end
|
758
|
+
attr_alias['/b', 'bold_off']
|
759
|
+
attr_alias['/d', 'dim_off']
|
760
|
+
attr_alias['/i', 'italic_off']
|
761
|
+
attr_alias['/u', 'underline_off']
|
762
|
+
attr_alias['/inv', 'invert_off']
|
763
|
+
attr_alias['/h', 'hide_off']
|
764
|
+
attr_alias['/s', 'strike_off']
|
765
|
+
attr_alias['/uu', 'double_underline_off']
|
766
|
+
attr_alias['/ovr', 'overlined_off']
|
767
|
+
attr_alias['/sup', 'superscript_off']
|
768
|
+
attr_alias['/sub', 'subscript_off']
|
769
|
+
attr_alias['/cu', 'curly_underline_off']
|
770
|
+
attr_alias['/dau', 'dashed_underline_off']
|
771
|
+
attr_alias['/dou', 'dotted_underline_off']
|
772
|
+
|
773
|
+
# additional shortcuts disable:
|
774
|
+
attr_alias['/', 'reset']
|
775
|
+
attr_map['/fg'] = clr_map['default']
|
776
|
+
attr_map['/bg'] = clr_map['on_default']
|
777
|
+
attr_map['/ul'] = clr_map['ul_default']
|
778
|
+
|
779
|
+
@attr_map = Hash.new { _color(_2) }
|
780
|
+
attr_map.merge!(clr_map).keys.sort!.each { @attr_map[_1] = attr_map[_1] }
|
781
|
+
@attr_map.freeze
|
782
|
+
|
783
|
+
@attrs_map = @attr_map.transform_keys(&:to_sym)
|
784
|
+
@attrs_map.default_proc = @attr_map.default_proc
|
785
|
+
@attrs_map.compare_by_identity.freeze
|
603
786
|
|
604
787
|
autoload :NAMED_COLORS, "#{__dir__}/ansi/named_colors.rb"
|
605
788
|
private_constant :NAMED_COLORS
|
@@ -689,14 +872,6 @@ module Terminal
|
|
689
872
|
#
|
690
873
|
# def set_scroll_region(top = nil, bottom = nil) = "\e[#{top};#{bottom}r"
|
691
874
|
|
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
875
|
# @comment other:
|
701
876
|
# "\eE" same as "\r\n"
|
702
877
|
# "\eD" same as "\n" but preserves X coord
|
@@ -705,5 +880,13 @@ module Terminal
|
|
705
880
|
# "\e[21t report window’s title as ESC ] l title ESC \"
|
706
881
|
# "\e[?1004h" report focus lost "\e[O" and focus get "\e[I"
|
707
882
|
# (disable by "\e[?1004l")
|
883
|
+
|
884
|
+
# @comment TODO:
|
885
|
+
# https://sw.kovidgoyal.net/kitty/desktop-notifications
|
886
|
+
# https://sw.kovidgoyal.net/kitty/pointer-shapes
|
887
|
+
# https://sw.kovidgoyal.net/kitty/unscroll
|
888
|
+
# https://sw.kovidgoyal.net/kitty/color-stack
|
889
|
+
# https://sw.kovidgoyal.net/kitty/deccara
|
890
|
+
# https://sw.kovidgoyal.net/kitty/clipboard
|
708
891
|
end
|
709
892
|
end
|
@@ -1,19 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Terminal
|
4
|
-
|
4
|
+
#
|
5
|
+
# Key event reported from {read_key_event}.
|
6
|
+
#
|
7
|
+
class KeyEvent
|
5
8
|
class << self
|
9
|
+
# @attribute [w] caching
|
10
|
+
# @return [true, false] whether KeyCodes should be cached
|
11
|
+
def caching = !!@cache
|
12
|
+
|
13
|
+
# @attribute [w] caching
|
14
|
+
def caching=(value)
|
15
|
+
if value
|
16
|
+
@cache ||= {}
|
17
|
+
else
|
18
|
+
@cache = nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Translate a keyboard input string into a related KeyEvent
|
23
|
+
#
|
24
|
+
# @param [String] raw keyboard input
|
25
|
+
# @return [KeyEvent] related key event
|
6
26
|
def [](raw)
|
7
|
-
return
|
8
|
-
return
|
27
|
+
return new(raw, *@single_key[raw.ord]) if raw.size == 1
|
28
|
+
return unknown(raw) if raw[0] != "\e"
|
9
29
|
return esc1(raw, raw[1]) if raw.size == 2 # ESC ?
|
10
30
|
case raw[1]
|
11
31
|
when "\e" # ESC ESC ...
|
12
32
|
return esc_esc(raw)
|
13
33
|
when 'O'
|
14
|
-
return
|
34
|
+
return new(raw, *@ss3[raw[2].ord]) if raw.size == 3 # ESC O ?
|
15
35
|
when '['
|
16
|
-
return
|
36
|
+
return new(raw, *@ss3[raw[2].ord]) if raw.size == 3 # ESC [ ?
|
17
37
|
if raw.size == 6 && raw[2] == 'M' # ESC [ M b c r
|
18
38
|
return mouse_vt200(raw)
|
19
39
|
end
|
@@ -29,18 +49,25 @@ module Terminal
|
|
29
49
|
return mouse_sgr(raw) if raw[2] == '<'
|
30
50
|
end
|
31
51
|
end
|
32
|
-
|
52
|
+
unknown(raw)
|
53
|
+
end
|
54
|
+
|
55
|
+
# @!visibility private
|
56
|
+
def new(raw, key = raw, modifier = 0, extra = nil)
|
57
|
+
@cache ? (@cache[raw] ||= super.freeze) : super.freeze
|
33
58
|
end
|
34
59
|
|
35
60
|
private
|
36
61
|
|
62
|
+
def unknown(raw) = new(raw, nil)
|
63
|
+
|
37
64
|
def csi_u(raw)
|
38
65
|
# ESC [ <code> u
|
39
66
|
# ESC [ <code> ; <modifier> u
|
40
|
-
return
|
67
|
+
return unknown(raw) if raw.size < 4
|
41
68
|
idx = raw.index(';')
|
42
69
|
code = raw[2..(idx ? idx - 1 : -2)].to_i
|
43
|
-
|
70
|
+
new(
|
44
71
|
raw,
|
45
72
|
@csiu[code] || code.chr(Encoding::UTF_8),
|
46
73
|
idx ? [raw[(idx + 1)..-2].to_i - 1, 0].max : 0
|
@@ -50,9 +77,9 @@ module Terminal
|
|
50
77
|
def legacy(raw)
|
51
78
|
# ESC [ <code> ~
|
52
79
|
# ESC [ <code> ; <modifier> ~
|
53
|
-
return
|
80
|
+
return unknown(raw) if raw.size < 4
|
54
81
|
idx = raw.index(';')
|
55
|
-
|
82
|
+
new(
|
56
83
|
raw,
|
57
84
|
@csi[raw[2..(idx ? idx - 1 : -2)].to_i],
|
58
85
|
idx ? [raw[(idx + 1)..-2].to_i - 1, 0].max : 0
|
@@ -62,23 +89,23 @@ module Terminal
|
|
62
89
|
def csi1(raw)
|
63
90
|
# ESC [ 1 ; [~ABCDEFHPQRS]
|
64
91
|
# ESC [ 1 ; <modifier> [~ABCDEFHPQRS]
|
65
|
-
return
|
92
|
+
return unknown(raw) if raw.size < 5
|
66
93
|
key, modifier = @ss3[raw[-1].ord]
|
67
94
|
modifier ||= 0
|
68
|
-
return
|
95
|
+
return new(raw, nil, modifier) unless key
|
69
96
|
modifier |= [raw[4..-2].to_i - 1, 0].max if raw.size > 5
|
70
|
-
|
97
|
+
new(raw, key, modifier)
|
71
98
|
end
|
72
99
|
|
73
100
|
def esc_esc(raw)
|
74
101
|
return esc1(raw, raw[2]) if raw.size == 3 # ESC ESC ?
|
75
102
|
ret = self[raw[1..]]
|
76
|
-
|
103
|
+
new(raw, ret.key, ret.modifier | 2) # ESC ESC ...
|
77
104
|
end
|
78
105
|
|
79
106
|
def esc1(raw, char)
|
80
107
|
key, modifier = @esc1[char.ord]
|
81
|
-
|
108
|
+
new(raw, key || char, modifier || 2)
|
82
109
|
end
|
83
110
|
|
84
111
|
def mouse_vt200(raw)
|
@@ -89,25 +116,25 @@ module Terminal
|
|
89
116
|
def mouse_sgr(raw)
|
90
117
|
# ESC [ < <code> ; <col> ; <row> M
|
91
118
|
# ESC [ < <code> ; <col> ; <row> m
|
92
|
-
return
|
119
|
+
return unknown(raw) if raw.size < 8
|
93
120
|
bcr = raw[3..-2].split(';', 3).map!(&:to_i)
|
94
|
-
bcr.size == 3 ? mouse_event(raw, *bcr) :
|
121
|
+
bcr.size == 3 ? mouse_event(raw, *bcr) : unknown(raw)
|
95
122
|
end
|
96
123
|
|
97
124
|
def mouse_urxvt(raw)
|
98
125
|
# ESC [ <code> ; <col> ; <row> M
|
99
|
-
return
|
126
|
+
return unknown(raw) if raw.size < 8
|
100
127
|
bcr = raw[2..-2].split(';', 3).map!(&:to_i)
|
101
|
-
bcr.size == 3 ? mouse_event(raw, *bcr) :
|
128
|
+
bcr.size == 3 ? mouse_event(raw, *bcr) : unknown(raw)
|
102
129
|
end
|
103
130
|
|
104
131
|
def mouse_event(raw, btn, col, row)
|
105
|
-
return
|
132
|
+
return unknown(raw) if btn < 0 || col < 1 || row < 1
|
106
133
|
key, btn = kind_of_mouse_event(btn)
|
107
134
|
modifier = btn.allbits?(4) ? 1 : 0
|
108
135
|
modifier += 2 if btn.allbits?(8)
|
109
136
|
modifier += 4 if btn.allbits?(16)
|
110
|
-
|
137
|
+
new(raw, key, modifier, [col, row])
|
111
138
|
end
|
112
139
|
|
113
140
|
def mouse_event_key(btn)
|
@@ -118,6 +145,79 @@ module Terminal
|
|
118
145
|
end
|
119
146
|
end
|
120
147
|
|
148
|
+
# Event string received from standard input.
|
149
|
+
# This can be a simple value like `"a"`or more complex input like
|
150
|
+
# `"\e[24;6~"` (for Shift+Ctrl+F12).
|
151
|
+
#
|
152
|
+
# @return [String] received event string
|
153
|
+
attr_reader :raw
|
154
|
+
|
155
|
+
# Pressed key without any modifiers.
|
156
|
+
# This can be a string for simple keys like `"a"` or a Symbol like `:F12`.
|
157
|
+
# @return [String, Symbol] key without modifiers
|
158
|
+
attr_reader :key
|
159
|
+
|
160
|
+
# Modifier key code. This represents the encoded key modifier like `Shift`
|
161
|
+
# or `Alt`.
|
162
|
+
#
|
163
|
+
# @return [Integer] modifier key code
|
164
|
+
attr_reader :modifier
|
165
|
+
|
166
|
+
# @comment for mouse events
|
167
|
+
# @!visibility private
|
168
|
+
attr_reader :extra
|
169
|
+
|
170
|
+
# Name of the key event.
|
171
|
+
# This can be a simple name like `"a"` or `"Shift+Ctrl+F12"` for combined
|
172
|
+
# keys.
|
173
|
+
#
|
174
|
+
# @return [String] key name
|
175
|
+
attr_reader :name
|
176
|
+
|
177
|
+
# @attribute [r] modifier?
|
178
|
+
# @return [true, false] whether a key modifier was pressed
|
179
|
+
def modifier? = @modifier != 0
|
180
|
+
|
181
|
+
# @attribute [r] simple?
|
182
|
+
# @return [true, false] whether a simple key was pressed
|
183
|
+
def simple? = @raw == @name
|
184
|
+
|
185
|
+
# All pressed keys.
|
186
|
+
# This is composed by all {modifier} and the {key}.
|
187
|
+
#
|
188
|
+
# @return [Array<Symbol, String>] all pressed keys
|
189
|
+
def to_a = @ary.dup
|
190
|
+
|
191
|
+
# @!visibility private
|
192
|
+
def to_ary = simple? ? [@raw] : [@raw, @name]
|
193
|
+
|
194
|
+
# @!visibility private
|
195
|
+
def to_s = @name.dup
|
196
|
+
|
197
|
+
# @!visibility private
|
198
|
+
def inspect = "<#{self.class.name} #{to_ary.map(&:inspect).join(' ')}>"
|
199
|
+
|
200
|
+
# @!visibility private
|
201
|
+
def freeze
|
202
|
+
@raw.freeze
|
203
|
+
@key.freeze
|
204
|
+
@extra.freeze
|
205
|
+
@name.freeze
|
206
|
+
super
|
207
|
+
end
|
208
|
+
|
209
|
+
private
|
210
|
+
|
211
|
+
def initialize(raw, key, modifier, extra)
|
212
|
+
@raw = raw
|
213
|
+
@key = key
|
214
|
+
@modifier = modifier
|
215
|
+
@extra = extra
|
216
|
+
@ary = MODIFIERS.filter_map { |b, n| n if modifier.allbits?(b) }
|
217
|
+
@ary << key if key
|
218
|
+
@name = @ary.join('+') # .encode(Encoding::UTF_8)
|
219
|
+
end
|
220
|
+
|
121
221
|
@mouse_kind = %i[
|
122
222
|
MButton1
|
123
223
|
MButton2
|
@@ -310,6 +410,19 @@ module Terminal
|
|
310
410
|
0x20 => :Space,
|
311
411
|
0x7f => :Back
|
312
412
|
}.compare_by_identity.freeze
|
413
|
+
|
414
|
+
@cache = {}
|
415
|
+
|
416
|
+
MODIFIERS = {
|
417
|
+
1 => :Shift,
|
418
|
+
2 => :Alt,
|
419
|
+
4 => :Ctrl,
|
420
|
+
8 => :Super,
|
421
|
+
16 => :Hyper,
|
422
|
+
32 => :Meta,
|
423
|
+
64 => :Caps,
|
424
|
+
128 => :Num
|
425
|
+
}.freeze
|
426
|
+
private_constant :MODIFIERS
|
313
427
|
end
|
314
|
-
private_constant :AsKeyEvent
|
315
428
|
end
|
data/lib/terminal/input.rb
CHANGED
@@ -26,13 +26,13 @@ module Terminal
|
|
26
26
|
# The input will be returned as named key codes like "Ctrl+c" by default.
|
27
27
|
# This can be changed by `mode`.
|
28
28
|
#
|
29
|
-
# @deprecated Use
|
29
|
+
# @deprecated Use rather {read_key_event} for better input handling.
|
30
30
|
#
|
31
31
|
# @param [:named, :raw, :both] mode 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
|
35
|
-
# @return [nil] in
|
35
|
+
# @return [nil] in error case
|
36
36
|
def read_key(mode: :named)
|
37
37
|
event = read_key_event or return
|
38
38
|
return event.raw if mode == :raw
|
@@ -43,7 +43,7 @@ module Terminal
|
|
43
43
|
# Read next {KeyEvent} from standard input.
|
44
44
|
#
|
45
45
|
# @return [KeyEvent] next event
|
46
|
-
# @return [nil]
|
46
|
+
# @return [nil] in error case
|
47
47
|
def read_key_event
|
48
48
|
case input_mode
|
49
49
|
when :dumb
|
@@ -52,23 +52,23 @@ module Terminal
|
|
52
52
|
KeyEvent.new(raw, *opts)
|
53
53
|
when :csi_u, :legacy
|
54
54
|
# raw = with_mouse ? read_tty_with_mouse : read_tty
|
55
|
-
|
55
|
+
KeyEvent[raw] if (raw = read_tty)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
private
|
60
60
|
|
61
61
|
def find_input_mode
|
62
|
+
# order is important!
|
62
63
|
im = ENV['INPUT_MODE']
|
63
64
|
return :dumb if im == 'dumb'
|
64
65
|
return :legacy if im == 'legacy'
|
65
66
|
return :dumb unless STDIN.tty?
|
66
67
|
if ansi? && _write("\e[>1u\e[?u\e[c") && csi_u?
|
67
68
|
at_exit { _write("\e[<u") }
|
68
|
-
:csi_u
|
69
|
-
else
|
70
|
-
:legacy
|
69
|
+
return :csi_u
|
71
70
|
end
|
71
|
+
:legacy
|
72
72
|
rescue Interrupt
|
73
73
|
:legacy
|
74
74
|
rescue IOError, SystemCallError
|
@@ -130,120 +130,5 @@ module Terminal
|
|
130
130
|
private_constant :DUMB_KEYS
|
131
131
|
end
|
132
132
|
|
133
|
-
#
|
134
|
-
# Key event reported from {read_key_event}.
|
135
|
-
#
|
136
|
-
class KeyEvent
|
137
|
-
class << self
|
138
|
-
# @attribute [w] caching
|
139
|
-
# @return [true, false] whether KeyCodes should be cached
|
140
|
-
def caching = !!@cache
|
141
|
-
|
142
|
-
# @attribute [w] caching
|
143
|
-
def caching=(value)
|
144
|
-
if value
|
145
|
-
@cache ||= {}
|
146
|
-
else
|
147
|
-
@cache = nil
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
# @!visibility private
|
152
|
-
def new(raw, key = raw, modifier = 0, extra = nil)
|
153
|
-
@cache ? (@cache[raw] ||= super.freeze) : super.freeze
|
154
|
-
end
|
155
|
-
|
156
|
-
# @!visibility private
|
157
|
-
def unknown(raw) = new(raw, nil)
|
158
|
-
end
|
159
|
-
|
160
|
-
# Event string received from standard input.
|
161
|
-
# This can be a simple value like `"a"`or `"\e[24;6~"` (for Shift+Ctrl+F12).
|
162
|
-
#
|
163
|
-
# @return [String] received event string
|
164
|
-
attr_reader :raw
|
165
|
-
|
166
|
-
# Pressed key without any modifiers.
|
167
|
-
# This can be a string for simple keys like `"a"` or a Symbol like `:F12`.
|
168
|
-
# @return [String, Symbol] key without modifiers
|
169
|
-
attr_reader :key
|
170
|
-
|
171
|
-
# Modifier key code. This represents the encoded key modifier like `Shift`
|
172
|
-
# or `Alt`.
|
173
|
-
#
|
174
|
-
# @return [Integer] modifier key code
|
175
|
-
attr_reader :modifier
|
176
|
-
|
177
|
-
# @comment for mouse events
|
178
|
-
# @!visibility private
|
179
|
-
attr_reader :extra
|
180
|
-
|
181
|
-
# Name of the key event.
|
182
|
-
# This can be a simple name like `"a"` or `"Shift+Ctrl+F12"` for combined
|
183
|
-
# keys.
|
184
|
-
#
|
185
|
-
# @return [String] key name
|
186
|
-
attr_reader :name
|
187
|
-
|
188
|
-
# @attribute [r] modifier?
|
189
|
-
# @return [true, false] whether a key modifier was pressed
|
190
|
-
def modifier? = @modifier != 0
|
191
|
-
|
192
|
-
# @attribute [r] simple?
|
193
|
-
# @return [true, false] whether a simple char was pressed
|
194
|
-
def simple? = @raw == @name
|
195
|
-
|
196
|
-
# All pressed keys.
|
197
|
-
# This is composed by all {modifier} and the {key}.
|
198
|
-
#
|
199
|
-
# @return [Array<Symbol, String>] all pressed keys
|
200
|
-
def to_a = @ary.dup
|
201
|
-
|
202
|
-
# @!visibility private
|
203
|
-
def to_ary = simple? ? [@raw] : [@raw, @name]
|
204
|
-
|
205
|
-
# @!visibility private
|
206
|
-
def to_s = @name.dup
|
207
|
-
|
208
|
-
# @!visibility private
|
209
|
-
def inspect = "<#{self.class.name} #{to_ary.map(&:inspect).join(' ')}>"
|
210
|
-
|
211
|
-
# @!visibility private
|
212
|
-
def freeze
|
213
|
-
@raw.freeze
|
214
|
-
@key.freeze
|
215
|
-
@extra.freeze
|
216
|
-
@name.freeze
|
217
|
-
super
|
218
|
-
end
|
219
|
-
|
220
|
-
private
|
221
|
-
|
222
|
-
def initialize(raw, key, modifier, extra)
|
223
|
-
@raw = raw
|
224
|
-
@key = key
|
225
|
-
@modifier = modifier
|
226
|
-
@extra = extra
|
227
|
-
@ary = MODIFIERS.filter_map { |b, n| n if modifier.allbits?(b) }
|
228
|
-
@ary << key if key
|
229
|
-
@name = @ary.join('+').encode(Encoding::UTF_8)
|
230
|
-
end
|
231
|
-
|
232
|
-
@cache = {}
|
233
|
-
|
234
|
-
MODIFIERS = {
|
235
|
-
1 => :Shift,
|
236
|
-
2 => :Alt,
|
237
|
-
4 => :Ctrl,
|
238
|
-
8 => :Super,
|
239
|
-
16 => :Hyper,
|
240
|
-
32 => :Meta,
|
241
|
-
64 => :Caps,
|
242
|
-
128 => :Num
|
243
|
-
}.freeze
|
244
|
-
private_constant :MODIFIERS
|
245
|
-
end
|
246
|
-
|
247
|
-
autoload :AsKeyEvent, "#{__dir__}/input/as_key_event.rb"
|
248
|
-
private_constant :AsKeyEvent
|
133
|
+
autoload :KeyEvent, "#{__dir__}/input/key_event.rb"
|
249
134
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
RSpec.shared_context 'with Terminal.rb' do |ansi: true, application: :kitty, colors: 256, size: [25, 80], pos: [1, 1]|
|
4
4
|
let(:stdout) { [] }
|
5
|
+
let(:stdin) { [] }
|
5
6
|
let(:stdoutstr) { stdout.join }
|
6
7
|
|
7
8
|
before do
|
@@ -9,21 +10,22 @@ RSpec.shared_context 'with Terminal.rb' do |ansi: true, application: :kitty, col
|
|
9
10
|
allow(Terminal).to receive(:application).with(no_args).and_return(
|
10
11
|
application
|
11
12
|
)
|
13
|
+
allow(Terminal).to receive(:input_mode).with(no_args).and_return(
|
14
|
+
ansi ? :csi_u : :dumb
|
15
|
+
)
|
12
16
|
allow(Terminal).to receive(:colors).with(no_args).and_return(
|
13
17
|
colors == :true_color ? 16_777_216 : colors
|
14
18
|
)
|
15
19
|
allow(Terminal).to receive(:size).with(no_args).and_return(size)
|
16
20
|
allow(Terminal).to receive(:pos).with(no_args).and_return(pos)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
nobbc = ->(s) { Terminal::Ansi.undecorate(s) }
|
26
|
-
end
|
21
|
+
|
22
|
+
bbcode_ = {
|
23
|
+
true =>
|
24
|
+
ansi ?
|
25
|
+
->(s) { Terminal::Ansi.bbcode(s) } :
|
26
|
+
->(s) { Terminal::Ansi.plain(s) },
|
27
|
+
false => ansi ? lambda(&:to_s) : ->(s) { Terminal::Ansi.undecorate(s) }
|
28
|
+
}.compare_by_identity
|
27
29
|
|
28
30
|
allow(Terminal).to receive(:<<) do |object|
|
29
31
|
stdout.push(bbcode[object]) unless object.nil?
|
@@ -31,7 +33,7 @@ RSpec.shared_context 'with Terminal.rb' do |ansi: true, application: :kitty, col
|
|
31
33
|
end
|
32
34
|
|
33
35
|
allow(Terminal).to receive(:print) do |*objects, bbcode: true|
|
34
|
-
bbcode = bbcode
|
36
|
+
bbcode = bbcode_[bbcode]
|
35
37
|
objects.flatten.each { stdout.push(bbcode[_1]) unless _1.nil? }
|
36
38
|
nil
|
37
39
|
end
|
@@ -42,7 +44,7 @@ RSpec.shared_context 'with Terminal.rb' do |ansi: true, application: :kitty, col
|
|
42
44
|
stdout.push("\n")
|
43
45
|
next
|
44
46
|
end
|
45
|
-
bbcode = bbcode
|
47
|
+
bbcode = bbcode_[bbcode]
|
46
48
|
objects.each do |s|
|
47
49
|
next stdout.push("\n") if s.nil?
|
48
50
|
stdout.push(s = bbcode[s])
|
@@ -55,5 +57,9 @@ RSpec.shared_context 'with Terminal.rb' do |ansi: true, application: :kitty, col
|
|
55
57
|
stdout.push(object = object.to_s)
|
56
58
|
object.bytesize
|
57
59
|
end
|
60
|
+
|
61
|
+
allow(Terminal).to receive(:read_key_event) do
|
62
|
+
Terminal::KeyEvent[stdin.shift || raise('stdin buffer is empty')]
|
63
|
+
end
|
58
64
|
end
|
59
65
|
end
|
data/lib/terminal/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terminal_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Blumtritt
|
@@ -9,9 +9,8 @@ bindir: bin
|
|
9
9
|
cert_chain: []
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
|
-
description:
|
13
|
-
|
14
|
-
BBCode-like embedded text attribute syntax.
|
12
|
+
description: 'Terminal access with super fast ANSI control codes support, modern CSIu
|
13
|
+
input, word-wise line break, BBCode-like embedded text attribute syntax. '
|
15
14
|
executables:
|
16
15
|
- bbcode
|
17
16
|
extensions: []
|
@@ -30,11 +29,10 @@ files:
|
|
30
29
|
- examples/key-codes.rb
|
31
30
|
- lib/terminal.rb
|
32
31
|
- lib/terminal/ansi.rb
|
33
|
-
- lib/terminal/ansi/attributes.rb
|
34
32
|
- lib/terminal/ansi/named_colors.rb
|
35
33
|
- lib/terminal/detect.rb
|
36
34
|
- lib/terminal/input.rb
|
37
|
-
- lib/terminal/input/
|
35
|
+
- lib/terminal/input/key_event.rb
|
38
36
|
- lib/terminal/rspec/helper.rb
|
39
37
|
- lib/terminal/text.rb
|
40
38
|
- lib/terminal/text/char_width.rb
|
@@ -65,5 +63,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
63
|
requirements: []
|
66
64
|
rubygems_version: 3.7.1
|
67
65
|
specification_version: 4
|
68
|
-
summary: Fast terminal access with ANSI
|
66
|
+
summary: Fast terminal access with ANSI, CSIu, BBCode, word-wise line break support.
|
69
67
|
test_files: []
|
@@ -1,206 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Terminal
|
4
|
-
module Ansi
|
5
|
-
@attr = {
|
6
|
-
'/' => '',
|
7
|
-
'/b' => '22',
|
8
|
-
'/blink' => '25',
|
9
|
-
'/bold' => '22',
|
10
|
-
'/conceal' => '28',
|
11
|
-
'/cu' => '4:0',
|
12
|
-
'/curly_underline' => '4:0',
|
13
|
-
'/dashed_underline' => '4:0',
|
14
|
-
'/dau' => '4:0',
|
15
|
-
'/dim' => '22',
|
16
|
-
'/dotted_underline' => '4:0',
|
17
|
-
'/dou' => '4:0',
|
18
|
-
'/double_underline' => '24',
|
19
|
-
'/encircled' => '54',
|
20
|
-
'/faint' => '22',
|
21
|
-
'/fraktur' => '23',
|
22
|
-
'/framed' => '54',
|
23
|
-
'/h' => '28',
|
24
|
-
'/hide' => '28',
|
25
|
-
'/i' => '23',
|
26
|
-
'/inv' => '27',
|
27
|
-
'/invert' => '27',
|
28
|
-
'/italic' => '23',
|
29
|
-
'/overlined' => '55',
|
30
|
-
'/ovr' => '55',
|
31
|
-
'/proportional' => '50',
|
32
|
-
'/slow_blink' => '25',
|
33
|
-
'/spacing' => '50',
|
34
|
-
'/strike' => '29',
|
35
|
-
'/sub' => '75',
|
36
|
-
'/subscript' => '75',
|
37
|
-
'/sup' => '75',
|
38
|
-
'/superscript' => '75',
|
39
|
-
'/u' => '24',
|
40
|
-
'/underline' => '24',
|
41
|
-
'/uu' => '24',
|
42
|
-
'b' => '1',
|
43
|
-
'blink' => '5',
|
44
|
-
'blink_off' => '25',
|
45
|
-
'bold' => '1',
|
46
|
-
'bold_off' => '22',
|
47
|
-
'conceal' => '8',
|
48
|
-
'cu' => '4:3',
|
49
|
-
'curly_underline' => '4:3',
|
50
|
-
'curly_underline_off' => '4:0',
|
51
|
-
'dashed_underline' => '4:5',
|
52
|
-
'dashed_underline_off' => '4:0',
|
53
|
-
'dau' => '4:5',
|
54
|
-
'default_font' => '10',
|
55
|
-
'dim' => '2',
|
56
|
-
'dotted_underline' => '4:4',
|
57
|
-
'dotted_underline_off' => '4:0',
|
58
|
-
'dou' => '4:4',
|
59
|
-
'double_underline' => '21',
|
60
|
-
'double_underline_off' => '24',
|
61
|
-
'encircled' => '52',
|
62
|
-
'encircled_off' => '54',
|
63
|
-
'faint' => '2',
|
64
|
-
'faint_off' => '22',
|
65
|
-
'font1' => '11',
|
66
|
-
'font2' => '12',
|
67
|
-
'font3' => '13',
|
68
|
-
'font4' => '14',
|
69
|
-
'font5' => '15',
|
70
|
-
'font6' => '16',
|
71
|
-
'font7' => '17',
|
72
|
-
'font8' => '18',
|
73
|
-
'font9' => '19',
|
74
|
-
'fraktur' => '20',
|
75
|
-
'fraktur_off' => '23',
|
76
|
-
'framed' => '51',
|
77
|
-
'framed_off' => '54',
|
78
|
-
'h' => '8',
|
79
|
-
'hide' => '8',
|
80
|
-
'hide_off' => '28',
|
81
|
-
'i' => '3',
|
82
|
-
'inv' => '7',
|
83
|
-
'invert' => '7',
|
84
|
-
'invert_off' => '27',
|
85
|
-
'italic' => '3',
|
86
|
-
'italic_off' => '23',
|
87
|
-
'overlined' => '53',
|
88
|
-
'overlined_off' => '55',
|
89
|
-
'ovr' => '53',
|
90
|
-
'primary_font' => '10',
|
91
|
-
'proportional' => '26',
|
92
|
-
'proportional_off' => '50',
|
93
|
-
'rapid_blink' => '6',
|
94
|
-
'reset' => '',
|
95
|
-
'reveal' => '28',
|
96
|
-
'slow_blink' => '5',
|
97
|
-
'spacing' => '26',
|
98
|
-
'strike' => '9',
|
99
|
-
'strike_off' => '29',
|
100
|
-
'sub' => '74',
|
101
|
-
'subscript' => '74',
|
102
|
-
'subscript_off' => '75',
|
103
|
-
'sup' => '73',
|
104
|
-
'superscript' => '73',
|
105
|
-
'superscript_off' => '75',
|
106
|
-
'u' => '4',
|
107
|
-
'underline' => '4',
|
108
|
-
'underline_off' => '24',
|
109
|
-
'uu' => '21'
|
110
|
-
}.freeze
|
111
|
-
|
112
|
-
@colors = {
|
113
|
-
'/bg' => '49',
|
114
|
-
'/fg' => '39',
|
115
|
-
'/ul' => '59',
|
116
|
-
'bg_black' => '40',
|
117
|
-
'bg_blue' => '44',
|
118
|
-
'bg_bright_black' => '100',
|
119
|
-
'bg_bright_blue' => '104',
|
120
|
-
'bg_bright_cyan' => '106',
|
121
|
-
'bg_bright_green' => '102',
|
122
|
-
'bg_bright_magenta' => '105',
|
123
|
-
'bg_bright_red' => '101',
|
124
|
-
'bg_bright_white' => '107',
|
125
|
-
'bg_bright_yellow' => '103',
|
126
|
-
'bg_cyan' => '46',
|
127
|
-
'bg_default' => '49',
|
128
|
-
'bg_green' => '42',
|
129
|
-
'bg_magenta' => '45',
|
130
|
-
'bg_red' => '41',
|
131
|
-
'bg_white' => '47',
|
132
|
-
'bg_yellow' => '43',
|
133
|
-
'black' => '30',
|
134
|
-
'blue' => '34',
|
135
|
-
'bright_black' => '90',
|
136
|
-
'bright_blue' => '94',
|
137
|
-
'bright_cyan' => '96',
|
138
|
-
'bright_green' => '92',
|
139
|
-
'bright_magenta' => '95',
|
140
|
-
'bright_red' => '91',
|
141
|
-
'bright_white' => '97',
|
142
|
-
'bright_yellow' => '93',
|
143
|
-
'cyan' => '36',
|
144
|
-
'default' => '39',
|
145
|
-
'fg_black' => '30',
|
146
|
-
'fg_blue' => '34',
|
147
|
-
'fg_bright_black' => '90',
|
148
|
-
'fg_bright_blue' => '94',
|
149
|
-
'fg_bright_cyan' => '96',
|
150
|
-
'fg_bright_green' => '92',
|
151
|
-
'fg_bright_magenta' => '95',
|
152
|
-
'fg_bright_red' => '91',
|
153
|
-
'fg_bright_white' => '97',
|
154
|
-
'fg_bright_yellow' => '93',
|
155
|
-
'fg_cyan' => '36',
|
156
|
-
'fg_default' => '39',
|
157
|
-
'fg_green' => '32',
|
158
|
-
'fg_magenta' => '35',
|
159
|
-
'fg_red' => '31',
|
160
|
-
'fg_white' => '37',
|
161
|
-
'fg_yellow' => '33',
|
162
|
-
'green' => '32',
|
163
|
-
'magenta' => '35',
|
164
|
-
'on_black' => '40',
|
165
|
-
'on_blue' => '44',
|
166
|
-
'on_bright_black' => '100',
|
167
|
-
'on_bright_blue' => '104',
|
168
|
-
'on_bright_cyan' => '106',
|
169
|
-
'on_bright_green' => '102',
|
170
|
-
'on_bright_magenta' => '105',
|
171
|
-
'on_bright_red' => '101',
|
172
|
-
'on_bright_white' => '107',
|
173
|
-
'on_bright_yellow' => '103',
|
174
|
-
'on_cyan' => '46',
|
175
|
-
'on_default' => '49',
|
176
|
-
'on_green' => '42',
|
177
|
-
'on_magenta' => '45',
|
178
|
-
'on_red' => '41',
|
179
|
-
'on_white' => '47',
|
180
|
-
'on_yellow' => '43',
|
181
|
-
'red' => '31',
|
182
|
-
'ul_black' => '58;2;0;0;0',
|
183
|
-
'ul_blue' => '58;2;0;0;128',
|
184
|
-
'ul_bright_black' => '58;2;64;64;64',
|
185
|
-
'ul_bright_blue' => '58;2;0;0;255',
|
186
|
-
'ul_bright_cyan' => '58;2;0;255;255',
|
187
|
-
'ul_bright_green' => '58;2;0;255;0',
|
188
|
-
'ul_bright_magenta' => '58;2;255;0;255',
|
189
|
-
'ul_bright_red' => '58;2;255;0;0',
|
190
|
-
'ul_bright_white' => '58;2;255;255;255',
|
191
|
-
'ul_bright_yellow' => '58;2;255;255;0',
|
192
|
-
'ul_cyan' => '58;2;0;128;128',
|
193
|
-
'ul_default' => '59',
|
194
|
-
'ul_green' => '58;2;0;128;0',
|
195
|
-
'ul_magenta' => '58;2;128;0;128',
|
196
|
-
'ul_red' => '58;2;128;0;0',
|
197
|
-
'ul_white' => '58;2;128;128;128',
|
198
|
-
'ul_yellow' => '58;2;128;128;0',
|
199
|
-
'white' => '37',
|
200
|
-
'yellow' => '33'
|
201
|
-
}.freeze
|
202
|
-
|
203
|
-
@attr_sym = @attr.transform_keys(&:to_sym).compare_by_identity.freeze
|
204
|
-
@colors_sym = @colors.transform_keys(&:to_sym).compare_by_identity.freeze
|
205
|
-
end
|
206
|
-
end
|