terminal_rb 1.0.6 → 1.0.9
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 +13 -13
- data/examples/key-codes.rb +1 -1
- data/lib/terminal/ansi.rb +195 -127
- data/lib/terminal/input/dumb.rb +2 -2
- data/lib/terminal/input/key_event.rb +4 -4
- data/lib/terminal/input.rb +2 -3
- data/lib/terminal/output/ansi.rb +11 -14
- data/lib/terminal/output/dumb.rb +3 -9
- data/lib/terminal/output.rb +2 -3
- data/lib/terminal/rspec/helper.rb +5 -4
- data/lib/terminal/text/char_width.rb +2778 -2744
- data/lib/terminal/text/formatter.rb +233 -69
- data/lib/terminal/text.rb +78 -55
- data/lib/terminal/version.rb +1 -1
- data/lib/terminal.rb +38 -13
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8a5e3a8b375cd45eef93b2316251d14da8732b80e27fb1192bbf8fb87a9bf297
|
|
4
|
+
data.tar.gz: f10bcbf23b3e8ecd01bc51a8772f2099dbe5950bb561bc26d854e6c3d2fb382d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3c0cbfe105fccd17923c6ba7f43faf797b2df1fcc5d76d8bf138b1593156c5e23dc2a9700be17fa61e8f744151bb756943a482f9eca501087ffabb257e7e608
|
|
7
|
+
data.tar.gz: 60616eb76bbc7d01e1759274220390611887bbafe12f2d3b7cda8eb68dcd6cee491ce6b477235ce9a8b5e43b372e6d3e6c7a8ff81962a67eb78a20cb58fe7523
|
data/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Terminal.rb v1.0.
|
|
1
|
+
# Terminal.rb v1.0.9
|
|
2
2
|
|
|
3
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, correct special key recognition and mouse event reporting 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/1.0.
|
|
7
|
+
- Help: [rubydoc.info](https://rubydoc.info/gems/terminal_rb/1.0.9/Terminal)
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
data/examples/bbcode.rb
CHANGED
|
@@ -6,28 +6,28 @@ Terminal.puts <<~TEXT
|
|
|
6
6
|
|
|
7
7
|
✅ [b bright_green]Terminal.rb::Ansi[/b] — BBCode:[/]
|
|
8
8
|
|
|
9
|
-
[b]Bold[/b] [\\b][d]...[/d][\\/b] [\\bold][d]
|
|
10
|
-
[dim]Dim[/dim] [\\d][d]...[/d][\\/d] [\\dim][d]
|
|
11
|
-
[i]Italic[/i] [\\i][d]...[/d][\\/i] [\\italic][d]
|
|
9
|
+
[b]Bold[/b] [\\b][d]...[/d][\\/b] [\\bold][d]........[/d][\\/bold]
|
|
10
|
+
[dim]Dim[/dim] [\\d][d]...[/d][\\/d] [\\dim][d].........[/d][\\/dim]
|
|
11
|
+
[i]Italic[/i] [\\i][d]...[/d][\\/i] [\\italic][d]......[/d][\\/italic]
|
|
12
12
|
[u]Underline[/u] [\\u][d]...[/d][\\/u] [\\underline][d]...[/d][\\/underline]
|
|
13
|
-
[h]Hide[/h] [\\h][d]...[/d][\\/h] [\\hide][d]
|
|
13
|
+
[h]Hide[/h] [\\h][d]...[/d][\\/h] [\\hide][d]........[/d][\\/hide]
|
|
14
14
|
|
|
15
|
-
[inv]Invert[/inv] [\\inv][d]
|
|
15
|
+
[inv]Invert[/inv] [\\inv][d]......[/d][\\/inv] [\\invert][d]...[/d][\\/invert]
|
|
16
16
|
[strike]Strike[/strike] [\\strike][d]...[/d][\\/strike]
|
|
17
|
-
[blink]Blink[/blink] [\\blink][d]
|
|
17
|
+
[blink]Blink[/blink] [\\blink][d]....[/d][\\/blink]
|
|
18
18
|
|
|
19
|
-
[u]Underline[/u] [\\u][d]
|
|
20
|
-
[uu]Double underline[/uu] [\\uu][d]
|
|
21
|
-
[cu]Curly underline[/cu] [\\cu][d]
|
|
19
|
+
[u]Underline[/u] [\\u][d].....[/d][\\/u] [\\underline][d]..........[/d][\\/underline]
|
|
20
|
+
[uu]Double underline[/uu] [\\uu][d]....[/d][\\/uu] [\\double_underline][d]...[/d][\\/double_underline]
|
|
21
|
+
[cu]Curly underline[/cu] [\\cu][d]....[/d][\\/cu] [\\curly_underline][d]...[/d] [\\/curly_underline]
|
|
22
22
|
[dau]Dashed underline[/dau] [\\dau][d]...[/d][\\/dau] [\\dashed_underline][d]...[/d][\\/dashed_underline]
|
|
23
23
|
[dou]Dotted underline[/dou] [\\dou][d]...[/d][\\/dou] [\\dotted_underline][d]...[/d][\\/dotted_underline]
|
|
24
24
|
|
|
25
|
-
[fraktur]Fraktur[/fraktur] [\\fraktur][d]
|
|
26
|
-
[framed]Framed[/framed] [\\framed][d]
|
|
25
|
+
[fraktur]Fraktur[/fraktur] [\\fraktur][d].....[/d][\\/fraktur]
|
|
26
|
+
[framed]Framed[/framed] [\\framed][d]......[/d][\\/framed]
|
|
27
27
|
[encircled]Encircled[/encircled] [\\encircled][d]...[/d][\\/encircled]
|
|
28
28
|
|
|
29
|
-
[ovr]Overlined[/ovr] [\\ovr][d]...[/d][\\/ovr] [\\overlined][d]
|
|
30
|
-
[sub]Subscript[/sub] [\\sub][d]...[/d][\\/sub] [\\subscript][d]
|
|
29
|
+
[ovr]Overlined[/ovr] [\\ovr][d]...[/d][\\/ovr] [\\overlined][d].....[/d][\\/overlined]
|
|
30
|
+
[sub]Subscript[/sub] [\\sub][d]...[/d][\\/sub] [\\subscript][d].....[/d][\\/subscript]
|
|
31
31
|
[sup]Superscript[/sup] [\\sup][d]...[/d][\\/sup] [\\superscript][d]...[/d][\\/superscript]
|
|
32
32
|
|
|
33
33
|
TEXT
|
data/examples/key-codes.rb
CHANGED
|
@@ -6,7 +6,7 @@ Terminal.puts <<~TEXT
|
|
|
6
6
|
|
|
7
7
|
✅ [b bright_green]Terminal.rb[/b] — Key Codes:[/fg]
|
|
8
8
|
Press any key to display it's control code and name.
|
|
9
|
-
[bright_black]([b]#{Terminal.input_mode}[/b] mode
|
|
9
|
+
[bright_black]([b]#{Terminal.input_mode}[/b] mode – exit with ESC)[/fg]
|
|
10
10
|
|
|
11
11
|
TEXT
|
|
12
12
|
|
data/lib/terminal/ansi.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Terminal
|
|
|
16
16
|
# Terminal::Ansi[:on_blue] # => "\e[44m"
|
|
17
17
|
#
|
|
18
18
|
# @example BBCode to ANSI
|
|
19
|
-
# Terminal::Ansi.bbcode('[bold]Hello[/bold]') # => "\e[1mHello\e[
|
|
19
|
+
# Terminal::Ansi.bbcode('[bold]Hello[/bold]') # => "\e[1mHello\e[22m"
|
|
20
20
|
#
|
|
21
21
|
module Ansi
|
|
22
22
|
class << self
|
|
@@ -39,7 +39,7 @@ module Terminal
|
|
|
39
39
|
def named_colors = NAMED_COLORS.keys.map!(&:to_sym)
|
|
40
40
|
|
|
41
41
|
#
|
|
42
|
-
# @!group
|
|
42
|
+
# @!group Text Attribute Code Generation
|
|
43
43
|
#
|
|
44
44
|
|
|
45
45
|
# Generate an ANSI escape sequence from attribute names or color
|
|
@@ -67,20 +67,12 @@ module Terminal
|
|
|
67
67
|
"\e[#{
|
|
68
68
|
attributes
|
|
69
69
|
.map! do |arg|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"38;5;#{arg}"
|
|
77
|
-
when (256..511)
|
|
78
|
-
"48;5;#{arg - 256}"
|
|
79
|
-
when (512..767)
|
|
80
|
-
"58;5;#{arg - 512}"
|
|
81
|
-
else
|
|
82
|
-
_invalid(arg)
|
|
83
|
-
end
|
|
70
|
+
next @attr_str_map[arg] || _invalid(arg) if arg.is_a?(String)
|
|
71
|
+
next @attr_sym_map[arg] || _invalid(arg) if arg.is_a?(Symbol)
|
|
72
|
+
_invalid(arg) unless arg.is_a?(Integer)
|
|
73
|
+
next "38;5;#{arg}" if arg >= 0 && arg <= 255
|
|
74
|
+
next "48;5;#{arg - 256}" if arg >= 256 && arg <= 511
|
|
75
|
+
arg >= 512 && arg <= 767 ? "58;5;#{arg - 512}" : _invalid(arg)
|
|
84
76
|
end
|
|
85
77
|
.join(';')
|
|
86
78
|
}m"
|
|
@@ -130,9 +122,11 @@ module Terminal
|
|
|
130
122
|
# attribute is invalid
|
|
131
123
|
def try_convert(attributes, separator: ' ')
|
|
132
124
|
return unless attributes
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
125
|
+
unless (attributes = attributes.to_s.split(separator)).empty?
|
|
126
|
+
# attributes.uniq!
|
|
127
|
+
codes = attributes.map { @attr_str_map[it] || break }
|
|
128
|
+
"\e[#{codes.join(';')}m" if codes
|
|
129
|
+
end
|
|
136
130
|
end
|
|
137
131
|
|
|
138
132
|
# Generate rainbow-colored text using true color (24-bit) ANSI
|
|
@@ -163,7 +157,7 @@ module Terminal
|
|
|
163
157
|
#
|
|
164
158
|
# @!endgroup
|
|
165
159
|
#
|
|
166
|
-
# @!group
|
|
160
|
+
# @!group BBCode Generation
|
|
167
161
|
#
|
|
168
162
|
|
|
169
163
|
# Convert BBCode markup to ANSI escape codes.
|
|
@@ -186,11 +180,16 @@ module Terminal
|
|
|
186
180
|
def bbcode(str)
|
|
187
181
|
str = str.to_s
|
|
188
182
|
return str.dup unless str.index('[')
|
|
189
|
-
str.gsub(@re_bbcode) do |
|
|
190
|
-
|
|
191
|
-
next
|
|
192
|
-
|
|
193
|
-
|
|
183
|
+
str.gsub(@re_bbcode) do |match|
|
|
184
|
+
hit = @bbcc[match] and next hit
|
|
185
|
+
next "[#{match[2..]}" if (fc = match[1]) == '\\'
|
|
186
|
+
@bbcc.clear if @bbcc.size == 1024
|
|
187
|
+
@bbcc[match] = if fc == ']' || (att = match[1..-2].split).empty?
|
|
188
|
+
match
|
|
189
|
+
else
|
|
190
|
+
att = att.map { @attr_str_map[it] || break }
|
|
191
|
+
att ? "\e[#{att.join(';')}m" : match
|
|
192
|
+
end
|
|
194
193
|
end
|
|
195
194
|
end
|
|
196
195
|
|
|
@@ -206,15 +205,12 @@ module Terminal
|
|
|
206
205
|
def unbbcode(str)
|
|
207
206
|
str = str.to_s
|
|
208
207
|
return str.dup unless str.index('[')
|
|
209
|
-
str.gsub(@re_bbcode) do |
|
|
210
|
-
|
|
211
|
-
if match[
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
next match_str if (match = match.split).empty?
|
|
216
|
-
next if match.all? { @attr_map[it] }
|
|
217
|
-
match_str
|
|
208
|
+
str.gsub(@re_bbcode) do |match|
|
|
209
|
+
hit = @bbcc[match] and next hit[0] == '[' ? hit : nil
|
|
210
|
+
next match if (fc = match[1]) == ']'
|
|
211
|
+
next "[#{match[2..]}" if fc == '\\'
|
|
212
|
+
next match if (att = match[1..-2].split).empty?
|
|
213
|
+
match unless att.map { @attr_str_map[it] || break }
|
|
218
214
|
end
|
|
219
215
|
end
|
|
220
216
|
|
|
@@ -232,13 +228,11 @@ module Terminal
|
|
|
232
228
|
def escape_bbcode(str)
|
|
233
229
|
str = str.to_s
|
|
234
230
|
return str.dup unless str.index('[')
|
|
235
|
-
str.gsub(@re_bbcode) do |
|
|
236
|
-
|
|
237
|
-
next
|
|
238
|
-
match =
|
|
239
|
-
|
|
240
|
-
next "[\\#{match}]" if parts.all? { @attr_map[it] }
|
|
241
|
-
match_str
|
|
231
|
+
str.gsub(@re_bbcode) do |match|
|
|
232
|
+
hit = @bbcc[match] and hit[1] == '\\' ? hit : "[\\#{match[1..]}"
|
|
233
|
+
next match if (fc = match[1]) == '\\' || fc == ']'
|
|
234
|
+
next match if (att = match[1..-2].split).empty?
|
|
235
|
+
att.map { @attr_str_map[it] || break } ? "[\\#{match[1..]}" : match
|
|
242
236
|
end
|
|
243
237
|
end
|
|
244
238
|
|
|
@@ -269,14 +263,9 @@ module Terminal
|
|
|
269
263
|
# @return [true, false]
|
|
270
264
|
def valid?(*attributes)
|
|
271
265
|
attributes.all? do |arg|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
when Symbol
|
|
276
|
-
@attrs_map[arg]
|
|
277
|
-
when (0..767)
|
|
278
|
-
true
|
|
279
|
-
end
|
|
266
|
+
next @attr_str_map[arg] if arg.is_a?(String)
|
|
267
|
+
next @attr_sym_map[arg] if arg.is_a?(Symbol)
|
|
268
|
+
arg.is_a?(Integer) && arg >= 0 && arg <= 767
|
|
280
269
|
end
|
|
281
270
|
end
|
|
282
271
|
|
|
@@ -298,7 +287,7 @@ module Terminal
|
|
|
298
287
|
#
|
|
299
288
|
# @!endgroup
|
|
300
289
|
#
|
|
301
|
-
# @!group
|
|
290
|
+
# @!group Cursor and Screen Control Codes
|
|
302
291
|
#
|
|
303
292
|
|
|
304
293
|
# Move cursor up.
|
|
@@ -453,54 +442,26 @@ module Terminal
|
|
|
453
442
|
# @return (see .[])
|
|
454
443
|
def line_erase(part = :all) = "\e[#{@line_erase[part]}K"
|
|
455
444
|
|
|
456
|
-
# Set the terminal window title.
|
|
457
|
-
# @note Supported by Hyper, iTerm2, Kitty, macOS Terminal, Tabby,
|
|
458
|
-
# WezTerm.
|
|
459
|
-
#
|
|
460
|
-
# @example
|
|
461
|
-
# Terminal.raw_write(Terminal::Ansi.title('My App'))
|
|
462
|
-
#
|
|
463
|
-
# @param title [String] the title text
|
|
464
|
-
# @return (see .[])
|
|
465
|
-
def title(title) = "\e]0;#{title}\a"
|
|
466
|
-
|
|
467
|
-
# Start a hyperlink (OSC 8).
|
|
468
|
-
#
|
|
469
|
-
# @note Supported by Ghostty, iTerm2, Kitty, Rio, Tabby, WezTerm.
|
|
470
|
-
#
|
|
471
|
-
# @see .link
|
|
472
|
-
# @see .link_end
|
|
473
445
|
#
|
|
474
|
-
#
|
|
475
|
-
# @param params [Hash] optional link parameters (e.g., `id:`)
|
|
476
|
-
# @return (see .[])
|
|
477
|
-
def link_start(url, **params)
|
|
478
|
-
"\e]8;#{params.map { it.join('=') }.join(':')};#{url}\a"
|
|
479
|
-
end
|
|
480
|
-
|
|
481
|
-
# End a hyperlink.
|
|
446
|
+
# @!endgroup
|
|
482
447
|
#
|
|
483
|
-
#
|
|
448
|
+
# @!group Terminal Integration Codes
|
|
484
449
|
#
|
|
485
|
-
# @return (see .[])
|
|
486
|
-
def link_end = +LINK_END
|
|
487
450
|
|
|
488
|
-
#
|
|
451
|
+
# Set the terminal window title.
|
|
489
452
|
#
|
|
490
|
-
# @
|
|
491
|
-
#
|
|
453
|
+
# @note Supported by iTerm2, Kitty, macOS Terminal, Tabby,
|
|
454
|
+
# WezTerm.
|
|
492
455
|
#
|
|
493
456
|
# @example
|
|
494
|
-
# Terminal::Ansi.
|
|
457
|
+
# Terminal.raw_write(Terminal::Ansi.title('My App'))
|
|
495
458
|
#
|
|
496
|
-
# @param
|
|
497
|
-
# @param text [String] the visible link text
|
|
459
|
+
# @param title [#to_s] the title text
|
|
498
460
|
# @return (see .[])
|
|
499
|
-
def
|
|
500
|
-
"#{link_start(url, **params)}#{text}#{LINK_END}"
|
|
501
|
-
end
|
|
461
|
+
def title(title) = "\e]0;#{_no_bell(title)}\a"
|
|
502
462
|
|
|
503
463
|
# Send a desktop notification via the terminal.
|
|
464
|
+
#
|
|
504
465
|
# @note Supported by Ghostty, iTerm2, Kitty, WezTerm.
|
|
505
466
|
#
|
|
506
467
|
# @example
|
|
@@ -508,7 +469,7 @@ module Terminal
|
|
|
508
469
|
#
|
|
509
470
|
# @param text [to_s] the notification text
|
|
510
471
|
# @return (see .[])
|
|
511
|
-
def notify(text) = "\e]9;#{text}\a"
|
|
472
|
+
def notify(text) = "\e]9;#{_no_bell(text)}\a"
|
|
512
473
|
|
|
513
474
|
# Show or update a progress indicator in the terminal tab/title
|
|
514
475
|
# bar.
|
|
@@ -545,10 +506,100 @@ module Terminal
|
|
|
545
506
|
"\e]9;4;#{state};#{percent.to_i.clamp(0, 100)}\a"
|
|
546
507
|
end
|
|
547
508
|
|
|
509
|
+
# @comment Should we implement this?
|
|
510
|
+
#
|
|
511
|
+
# # Request attention.
|
|
512
|
+
# #
|
|
513
|
+
# # @note Supported by iTerm2.
|
|
514
|
+
# #
|
|
515
|
+
# # @param action [true, :bounce, :once, :fireworks, false, :stop]
|
|
516
|
+
# # start bouncing dock icon (`true`, `:bounce`),
|
|
517
|
+
# # bounce dock icon once (`:once`)
|
|
518
|
+
# # or stop attention (`false`, `:stop`)
|
|
519
|
+
# # @return (see .[])
|
|
520
|
+
# def attention(action = :bounce)
|
|
521
|
+
# "\e]1337;RequestAttention=#{
|
|
522
|
+
# case action
|
|
523
|
+
# when true, :bounce
|
|
524
|
+
# 'yes'
|
|
525
|
+
# when :once, :fireworks
|
|
526
|
+
# action
|
|
527
|
+
# else
|
|
528
|
+
# 'no'
|
|
529
|
+
# end
|
|
530
|
+
# }\a"
|
|
531
|
+
# end
|
|
532
|
+
|
|
533
|
+
# Create or start a hyperlink.
|
|
534
|
+
#
|
|
535
|
+
# @note Supported by Ghostty, iTerm2, Kitty, Rio, Tabby, WezTerm.
|
|
536
|
+
#
|
|
537
|
+
# @see .link_end
|
|
538
|
+
#
|
|
539
|
+
# @example
|
|
540
|
+
# Terminal::Ansi.link('https://example.com', 'Example')
|
|
541
|
+
#
|
|
542
|
+
# @param url [#to_s] the link URL
|
|
543
|
+
# @param text [nil, #to_s] the visible link text
|
|
544
|
+
# @param params [Hash] optional link parameters (e.g., `id:`)
|
|
545
|
+
# @return (see .[])
|
|
546
|
+
def link(url, text = nil, **params)
|
|
547
|
+
start =
|
|
548
|
+
"\e]8;#{
|
|
549
|
+
_no_bell(params.map { it.join('=') }.join(':'))
|
|
550
|
+
};#{_no_bell(url)}\a"
|
|
551
|
+
text ? "#{start}#{_no_bell(text)}#{LINK_END}" : start
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
# End a hyperlink.
|
|
555
|
+
#
|
|
556
|
+
# @see .link
|
|
557
|
+
#
|
|
558
|
+
# @return (see .[])
|
|
559
|
+
def link_end = +LINK_END
|
|
560
|
+
|
|
561
|
+
# Copy text to clipboard.
|
|
562
|
+
#
|
|
563
|
+
# @note Supported by Ghostty, iTerm2, Kitty, Rio, Tabby, WezTerm.
|
|
564
|
+
#
|
|
565
|
+
# @param text [#to_s] text to copy
|
|
566
|
+
# @return (see .[])
|
|
567
|
+
def clipboard(text) = "\e]52;c;#{[text.to_s].pack('m0')}\a"
|
|
568
|
+
|
|
569
|
+
# Show or update the session status of the terminal.
|
|
570
|
+
#
|
|
571
|
+
# @note Supported by iTerm2.
|
|
572
|
+
#
|
|
573
|
+
# @example
|
|
574
|
+
# Terminal.raw_write(Terminal::Ansi.status(text: 'Working'))
|
|
575
|
+
# Terminal.raw_write(Terminal::Ansi.status(indicator: '#fa00fa'))
|
|
576
|
+
# Terminal.raw_write(Terminal::Ansi.status(indicator: :f00))
|
|
577
|
+
# Terminal.raw_write(Terminal::Ansi.status) # reset the status
|
|
578
|
+
#
|
|
579
|
+
# @param text [nil, #to_s] status text
|
|
580
|
+
# @param detail [nil, #to_s] status detail text
|
|
581
|
+
# @param color [nil, String, Symbol] text color
|
|
582
|
+
# @param indicator [nil, String, Symbol] status indicator color
|
|
583
|
+
# @return (see .[])
|
|
584
|
+
def status(text: nil, detail: nil, color: nil, indicator: nil)
|
|
585
|
+
str = text ? ";status=#{_no_bell(text)}" : ''
|
|
586
|
+
indicator = _try_rgb(indicator) and str << ";indicator=#{indicator}"
|
|
587
|
+
color = _try_rgb(color) and str << ";color=#{color}"
|
|
588
|
+
str << "detail=#{_no_bell(detail)}" if detail
|
|
589
|
+
str.empty? ? +STATUS_RESET : "\e]21337#{str}\a"
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
# Reset session status of the terminal.
|
|
593
|
+
#
|
|
594
|
+
# @see .status
|
|
595
|
+
#
|
|
596
|
+
# @return (see .[])
|
|
597
|
+
def status_reset = +STATUS_RESET
|
|
598
|
+
|
|
548
599
|
# Scale text using the
|
|
549
600
|
# [text sizing protocol](https://sw.kovidgoyal.net/kitty/text-sizing-protocol).
|
|
550
601
|
#
|
|
551
|
-
# @note
|
|
602
|
+
# @note Supported by Kitty.
|
|
552
603
|
#
|
|
553
604
|
# @example Double-height Greeting
|
|
554
605
|
# Terminal::Ansi.scale('Hello Ruby!', scale: 2)
|
|
@@ -614,18 +665,25 @@ module Terminal
|
|
|
614
665
|
caller(1)
|
|
615
666
|
)
|
|
616
667
|
end
|
|
668
|
+
|
|
669
|
+
def _try_rgb(str)
|
|
670
|
+
mt = /\A?#?([[:xdigit:]]{3,6})\z/.match(str.to_s)&.[](1) or return
|
|
671
|
+
"##{mt.size == 6 ? mt : mt[..2]}"
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
def _no_bell(str) = str.to_s.tr("\a", '')
|
|
617
675
|
end
|
|
618
676
|
|
|
619
677
|
@re_test =
|
|
620
678
|
/
|
|
621
|
-
|
|
622
|
-
|
|
|
623
|
-
|
|
624
|
-
/x
|
|
679
|
+
(?:\e\[[\x30-\x3f]*[\x20-\x2f]*[a-zA-Z])
|
|
680
|
+
| (?:\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
|
|
681
|
+
/x
|
|
625
682
|
|
|
626
|
-
@
|
|
683
|
+
@re_bbcode_old = /(?:\[((?~[\[\]]))\])/
|
|
684
|
+
@re_bbcode = /(?:\[(?~[\[\]]))\]/
|
|
627
685
|
|
|
628
|
-
|
|
686
|
+
color_map = {
|
|
629
687
|
# foreground
|
|
630
688
|
'black' => '30',
|
|
631
689
|
'red' => '31',
|
|
@@ -684,9 +742,9 @@ module Terminal
|
|
|
684
742
|
'on_bright_white' => '107'
|
|
685
743
|
}
|
|
686
744
|
|
|
687
|
-
@colors =
|
|
745
|
+
@colors = color_map.keys.map!(&:to_sym).sort!.freeze
|
|
688
746
|
|
|
689
|
-
|
|
747
|
+
@attr_base_map = {
|
|
690
748
|
'reset' => '',
|
|
691
749
|
'bold' => '1',
|
|
692
750
|
'faint' => '2',
|
|
@@ -743,7 +801,7 @@ module Terminal
|
|
|
743
801
|
'dashed_underline_off' => '4:0'
|
|
744
802
|
}
|
|
745
803
|
|
|
746
|
-
attr_alias = ->(t, s) {
|
|
804
|
+
attr_alias = ->(t, s) { @attr_base_map[t] = @attr_base_map[s] }
|
|
747
805
|
|
|
748
806
|
# aliases:
|
|
749
807
|
attr_alias['off', 'reset']
|
|
@@ -768,18 +826,18 @@ module Terminal
|
|
|
768
826
|
attr_alias['sup', 'superscript']
|
|
769
827
|
attr_alias['sub', 'subscript']
|
|
770
828
|
|
|
771
|
-
@attributes =
|
|
829
|
+
@attributes = @attr_base_map.keys.map!(&:to_sym).sort!.freeze
|
|
772
830
|
|
|
773
831
|
# shortcuts disable:
|
|
774
|
-
|
|
832
|
+
@attr_base_map.keys.each do |n|
|
|
775
833
|
attr_alias["/#{n.delete_suffix('_off')}", n] if n.end_with?('_off')
|
|
776
834
|
end
|
|
777
835
|
|
|
778
836
|
# additional shortcuts disable:
|
|
779
837
|
attr_alias['/', 'reset']
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
838
|
+
@attr_base_map['/bg'] = color_map['on_default']
|
|
839
|
+
@attr_base_map['/fg'] = color_map['default']
|
|
840
|
+
@attr_base_map['/ul'] = color_map['ul_default']
|
|
783
841
|
|
|
784
842
|
attr_alias['/b', 'bold_off']
|
|
785
843
|
attr_alias['/d', 'dim_off']
|
|
@@ -800,29 +858,33 @@ module Terminal
|
|
|
800
858
|
@cbase.default = '38'
|
|
801
859
|
@cbase.freeze
|
|
802
860
|
|
|
803
|
-
@
|
|
804
|
-
|
|
805
|
-
|
|
861
|
+
@attr_base_map.merge!(color_map).freeze
|
|
862
|
+
|
|
863
|
+
@attr_str_map = @attr_base_map.dup
|
|
864
|
+
@attr_str_map.default_proc =
|
|
865
|
+
proc do |h, s|
|
|
866
|
+
if h.size > 1024 # cache limit
|
|
867
|
+
h.keep_if { |key, _| @attr_base_map.key?(key) }
|
|
868
|
+
end
|
|
869
|
+
b, v = /\A(on|ul)?_?#?([[:xdigit:]]{1,6})\z/.match(s)&.captures
|
|
806
870
|
unless v
|
|
807
|
-
b = /\A(on|ul)?_?([a-z]{3,}[0-9]{0,3})\z/.match(
|
|
808
|
-
v = NAMED_COLORS[b[2]]
|
|
809
|
-
next "#{@cbase[b[1]]};#{v}"
|
|
871
|
+
b = /\A(on|ul)?_?([a-z]{3,}[0-9]{0,3})\z/.match(s) or next h[s] = nil
|
|
872
|
+
next h[s] = (v = NAMED_COLORS[b[2]]) ? "#{@cbase[b[1]]};#{v}" : nil
|
|
810
873
|
end
|
|
811
|
-
|
|
812
|
-
when 1, 2
|
|
813
|
-
"#{@cbase[b]};5;#{v.hex}"
|
|
814
|
-
when 3
|
|
815
|
-
"#{@cbase[b]};2;#{(v[0] * 2).hex};#{(v[1] * 2).hex};#{(v[2] * 2).hex}"
|
|
816
|
-
when 6
|
|
874
|
+
h[s] = if v.size == 6
|
|
817
875
|
"#{@cbase[b]};2;#{v[0, 2].hex};#{v[2, 2].hex};#{v[4, 2].hex}"
|
|
876
|
+
elsif v.size == 3
|
|
877
|
+
"#{@cbase[b]};2;#{(v[0] * 2).hex};#{(v[1] * 2).hex};#{(v[2] * 2).hex}"
|
|
878
|
+
elsif v.size < 3
|
|
879
|
+
"#{@cbase[b]};5;#{v.hex}"
|
|
818
880
|
end
|
|
819
881
|
end
|
|
820
|
-
attr_map.merge!(clr_map).keys.sort!.each { @attr_map[it] = attr_map[it] }
|
|
821
|
-
@attr_map.freeze
|
|
822
882
|
|
|
823
|
-
@
|
|
824
|
-
@
|
|
825
|
-
@
|
|
883
|
+
@attr_sym_map = @attr_base_map.transform_keys(&:to_sym)
|
|
884
|
+
@attr_sym_map.compare_by_identity
|
|
885
|
+
@attr_sym_map.default_proc = proc { |h, s| h[s] = @attr_str_map[s.to_s] }
|
|
886
|
+
|
|
887
|
+
@bbcc = {} # BBCode cache
|
|
826
888
|
|
|
827
889
|
@screen_erase = { below: nil, above: '1', scrollback: '3' }
|
|
828
890
|
@screen_erase.default = '2'
|
|
@@ -907,6 +969,16 @@ module Terminal
|
|
|
907
969
|
# @private
|
|
908
970
|
LINE_ERASE_PREV = -"#{cursor_prev_line(nil)}#{LINE_ERASE}"
|
|
909
971
|
|
|
972
|
+
# @comment Supported by Terminal, iTerm, WezTerm:
|
|
973
|
+
# @private
|
|
974
|
+
LINE_DOUBLE_HEIGHT_TOP = "\e#3"
|
|
975
|
+
# @private
|
|
976
|
+
LINE_DOUBLE_HEIGHT_BOTTOM = "\e#4"
|
|
977
|
+
# @private
|
|
978
|
+
LINE_SINGLE_WIDTH = "\e#5"
|
|
979
|
+
# @private
|
|
980
|
+
LINE_DOUBLE_WIDTH = "\e#6"
|
|
981
|
+
|
|
910
982
|
# @private
|
|
911
983
|
LINK_END = "\e]8;;\a"
|
|
912
984
|
|
|
@@ -915,6 +987,9 @@ module Terminal
|
|
|
915
987
|
# @private
|
|
916
988
|
PROGRESS_SHOW_INDETERMINATE = "\e]9;4;3;0\a"
|
|
917
989
|
|
|
990
|
+
# @private
|
|
991
|
+
STATUS_RESET = "\e]21337;status=;indicator=;status-color=\a"
|
|
992
|
+
|
|
918
993
|
# @comment seems not widely supported:
|
|
919
994
|
# doubled: def cursor_column(column = 1) = "\e[#{column}`"
|
|
920
995
|
# doubled: def cursor_row(row = 1) = "\e[#{row}d"
|
|
@@ -932,13 +1007,6 @@ module Terminal
|
|
|
932
1007
|
#
|
|
933
1008
|
# def set_scroll_region(top = nil, bottom = nil) = "\e[#{top};#{bottom}r"
|
|
934
1009
|
|
|
935
|
-
# @comment other:
|
|
936
|
-
# "\eE" same as "\r\n"
|
|
937
|
-
# "\eD" same as "\n" but preserves column
|
|
938
|
-
# "\eM" reverse "\n"
|
|
939
|
-
# "\e[6n" report Cursor Position as "ESC \[ row ; col R"
|
|
940
|
-
# "\e[21t report window’s title as ESC ] l title ESC \"
|
|
941
|
-
|
|
942
1010
|
# @comment TODO:
|
|
943
1011
|
# https://sw.kovidgoyal.net/kitty/desktop-notifications
|
|
944
1012
|
# https://sw.kovidgoyal.net/kitty/pointer-shapes
|
data/lib/terminal/input/dumb.rb
CHANGED
|
@@ -9,9 +9,9 @@ module Terminal
|
|
|
9
9
|
# @see Terminal.read_key_event
|
|
10
10
|
#
|
|
11
11
|
# @example Parse a raw escape sequence
|
|
12
|
-
# event = Terminal::KeyEvent["
|
|
13
|
-
# event.key # =>
|
|
14
|
-
# event.name # => "
|
|
12
|
+
# event = Terminal::KeyEvent["a"]
|
|
13
|
+
# event.key # => "a"
|
|
14
|
+
# event.name # => "a"
|
|
15
15
|
# event.simple? # => true
|
|
16
16
|
#
|
|
17
17
|
# @example Inspect modifier keys
|
|
@@ -33,7 +33,7 @@ module Terminal
|
|
|
33
33
|
# @see #modifiers
|
|
34
34
|
# @see #modifier?
|
|
35
35
|
#
|
|
36
|
-
# @return [Integer]
|
|
36
|
+
# @return [Integer] bitmask of the active modifiers
|
|
37
37
|
attr_reader :modifier_bits
|
|
38
38
|
|
|
39
39
|
# Names of active modifier keys.
|
data/lib/terminal/input.rb
CHANGED
|
@@ -14,7 +14,6 @@ module Terminal
|
|
|
14
14
|
# @example
|
|
15
15
|
# Terminal.input_mode # => :csi_u
|
|
16
16
|
#
|
|
17
|
-
# @attribute [r] input_mode
|
|
18
17
|
# @return [Symbol] `:csi_u`, `:legacy`, `:dumb`, or `:error`
|
|
19
18
|
|
|
20
19
|
#
|
|
@@ -33,7 +32,7 @@ module Terminal
|
|
|
33
32
|
#
|
|
34
33
|
# @example
|
|
35
34
|
# Terminal.on_key_event(mouse: true) do |event|
|
|
36
|
-
# break if event.name == '
|
|
35
|
+
# break if event.name == 'Esc'
|
|
37
36
|
# puts event.name
|
|
38
37
|
# end
|
|
39
38
|
#
|
|
@@ -69,7 +68,7 @@ module Terminal
|
|
|
69
68
|
extend AnsiInput
|
|
70
69
|
when :dumb
|
|
71
70
|
require_relative('input/dumb')
|
|
72
|
-
extend
|
|
71
|
+
extend DumbInput
|
|
73
72
|
else
|
|
74
73
|
__input_error
|
|
75
74
|
end
|