terminal_rb 0.14.0 → 0.16.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 -1
- data/examples/info.rb +1 -0
- data/examples/key-codes.rb +6 -3
- data/examples/text.rb +32 -0
- data/lib/terminal/ansi.rb +133 -134
- data/lib/terminal/input/key_event.rb +165 -149
- data/lib/terminal/input.rb +113 -45
- data/lib/terminal/shell.rb +2 -6
- data/lib/terminal/text.rb +76 -80
- data/lib/terminal/version.rb +1 -1
- data/lib/terminal.rb +29 -5
- data/terminal_rb.gemspec +34 -0
- metadata +10 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 05eda4c596ad7060b576cb01f6fe7dafd38e114274b44c14c4c90e1b3a2b322a
|
|
4
|
+
data.tar.gz: '0479860569041d6fb874d38de0d183a2cc778a6803d3eed302425cd795133e06'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ab038b9b4cc9ed41ba09673be9a2e2d25aa2edc2ffbf1fa0cad826ca7f55c8fef3aab734648f13f63750ea7799bce638479839e5f609e597eeb0bf4508b0f0e7
|
|
7
|
+
data.tar.gz: b501721dfd7d6d79ceb8821fa5dd9d877e764e235435f3e6441e9b02b424a5873aba1318365a4b064a9430c135882be39470361d0042b56726be3dd2505e9db5
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Terminal.rb 
|
|
2
2
|
|
|
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,
|
|
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)
|
|
@@ -16,6 +16,7 @@ Terminal.rb supports you with input and output on your terminal. Simple [BBCode]
|
|
|
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
|
+
- mouse events support
|
|
19
20
|
|
|
20
21
|
## Examples
|
|
21
22
|
|
data/examples/info.rb
CHANGED
|
@@ -12,5 +12,6 @@ Terminal.puts <<~TEXT
|
|
|
12
12
|
Terminal Size: [b]#{Terminal.size.join(' x ')}[/]
|
|
13
13
|
Cursor Position: [b]#{Terminal.pos&.join(', ')}[/]
|
|
14
14
|
Input Mode: [b]#{Terminal.input_mode}[/]
|
|
15
|
+
Link Support: [b]#{Terminal::Ansi.link('https://codeberg.org/mblumtritt/Terminal.rb', 'Link')}[/]
|
|
15
16
|
|
|
16
17
|
TEXT
|
data/examples/key-codes.rb
CHANGED
|
@@ -13,10 +13,13 @@ TEXT
|
|
|
13
13
|
Terminal.hide_cursor
|
|
14
14
|
at_exit { Terminal.show_cursor } # required for some terminals :/
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
# if you like to have mouse position changes reported then use
|
|
17
|
+
# 'mouse_move: true' in next line
|
|
18
|
+
Terminal.on_key_event(mouse: true, focus: true, mouse_move: false) do |event|
|
|
18
19
|
str = "[blue]: [yellow]#{event.raw.inspect}"
|
|
19
20
|
str << " [bold bright_green]#{event.name}[/]" unless event.simple?
|
|
21
|
+
str << " [dim]#{event.position.inspect}[/]" if event.position
|
|
20
22
|
Terminal.puts(str)
|
|
21
|
-
|
|
23
|
+
event.name != 'Esc'
|
|
22
24
|
end
|
|
25
|
+
puts
|
data/examples/text.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/terminal'
|
|
4
|
+
|
|
5
|
+
LOREM = <<~IPSUM
|
|
6
|
+
This example outputs [i bright_white]Lorem ipsum[/] text so that it takes up 75% of the screen width and fits the height of your screen.
|
|
7
|
+
|
|
8
|
+
[i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet.
|
|
9
|
+
|
|
10
|
+
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla [red]facilisis[/fg] at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. [i bright_white]Lorem ipsum[/] dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore [b]magna[/b] aliquam erat volutpat.
|
|
11
|
+
|
|
12
|
+
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla [red]facilisis[/fg] at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
|
13
|
+
|
|
14
|
+
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. [i bright_white]Lorem ipsum[/] dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore [b]magna[/b] aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
|
15
|
+
|
|
16
|
+
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla [red]facilisis[/fg].
|
|
17
|
+
|
|
18
|
+
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd [b]magna[/b] no rebum. [yellow]sanctus[/fg] sea sed takimata ut vero voluptua. est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat.
|
|
19
|
+
|
|
20
|
+
Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg].
|
|
21
|
+
|
|
22
|
+
[i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet. [i bright_white]Lorem ipsum[/] dolor sit amet, [green]consetetur[/fg] sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore [b]magna[/b] aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata [yellow]sanctus[/fg] est [i bright_white]Lorem ipsum[/] dolor sit amet.
|
|
23
|
+
|
|
24
|
+
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla [red]facilisis[/fg] at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. [i bright_white]Lorem ipsum[/] dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore [b]magna[/b] aliquam erat volutpat.
|
|
25
|
+
|
|
26
|
+
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla [red]facilisis[/fg] at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
|
27
|
+
|
|
28
|
+
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. [i bright_white]Lorem ipsum[/] dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore [b]magna[/b] aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
|
29
|
+
IPSUM
|
|
30
|
+
|
|
31
|
+
rows, cols = Terminal.size
|
|
32
|
+
puts Terminal::Text.each(LOREM, limit: cols * 0.75).take(rows - 1)
|
data/lib/terminal/ansi.rb
CHANGED
|
@@ -34,8 +34,8 @@ module Terminal
|
|
|
34
34
|
# @!group ANSI control code generator functions
|
|
35
35
|
#
|
|
36
36
|
|
|
37
|
-
# Combine given
|
|
38
|
-
#
|
|
37
|
+
# Combine given {attributes}, {colors}, {named_colors} and color codes to
|
|
38
|
+
# an ANSI control code sequence.
|
|
39
39
|
#
|
|
40
40
|
# Colors can specified by their name for ANSI 3-bit and 4-bit colors.
|
|
41
41
|
# For 8-bit ANSI colors use 2-digit hexadecimal values `00`...`ff`.
|
|
@@ -96,7 +96,7 @@ module Terminal
|
|
|
96
96
|
return +'' if attributes.empty?
|
|
97
97
|
"\e[#{
|
|
98
98
|
attributes
|
|
99
|
-
.map do |arg|
|
|
99
|
+
.map! do |arg|
|
|
100
100
|
case arg
|
|
101
101
|
when String
|
|
102
102
|
@attr_map[arg] || _invalid(arg)
|
|
@@ -154,8 +154,7 @@ module Terminal
|
|
|
154
154
|
# @param str [#to_s] string to be modified
|
|
155
155
|
# @return [String] string without ANSI attributes
|
|
156
156
|
def undecorate(str)
|
|
157
|
-
str = str.to_s
|
|
158
|
-
str.index("\e") ? str.gsub(@re_test, '') : str.dup
|
|
157
|
+
(str = str.to_s).index("\e") ? str.gsub(@re_test, '') : str.dup
|
|
159
158
|
end
|
|
160
159
|
|
|
161
160
|
# Try to combine given ANSI attributes and colors.
|
|
@@ -263,8 +262,7 @@ module Terminal
|
|
|
263
262
|
# @param str [#to_s] string to be modified
|
|
264
263
|
# @return [String] string without BBCode and ANSI control codes.
|
|
265
264
|
def plain(str)
|
|
266
|
-
str = str.to_s
|
|
267
|
-
unless str.index('[')
|
|
265
|
+
unless (str = str.to_s).index('[')
|
|
268
266
|
return str.index("\e") ? str.gsub(@re_test, '') : str.dup
|
|
269
267
|
end
|
|
270
268
|
str =
|
|
@@ -289,16 +287,14 @@ module Terminal
|
|
|
289
287
|
pos = -1
|
|
290
288
|
@pi2_third ||= 2.0 * Math::PI / 3.0
|
|
291
289
|
@pi4_third ||= 4.0 * Math::PI / 3.0
|
|
292
|
-
|
|
293
|
-
.to_s
|
|
294
|
-
.chars
|
|
295
|
-
.map! do |char|
|
|
290
|
+
(
|
|
291
|
+
str.to_s.chars.map! do |char|
|
|
296
292
|
i = (seed + ((pos += 1) / spread)) * frequency
|
|
297
293
|
"\e[38;2;#{(Math.sin(i) * 255).to_i.abs};" \
|
|
298
294
|
"#{(Math.sin(i + @pi2_third) * 255).to_i.abs};" \
|
|
299
295
|
"#{(Math.sin(i + @pi4_third) * 255).to_i.abs}m#{char}"
|
|
300
|
-
end
|
|
301
|
-
|
|
296
|
+
end << RESET
|
|
297
|
+
).join
|
|
302
298
|
end
|
|
303
299
|
|
|
304
300
|
#
|
|
@@ -349,6 +345,21 @@ module Terminal
|
|
|
349
345
|
# @return (see cursor_up)
|
|
350
346
|
def cursor_column(column = 1) = "\e[#{column}G"
|
|
351
347
|
|
|
348
|
+
# Move cursor to given column in the current row relative to the current
|
|
349
|
+
# position.
|
|
350
|
+
# (Skip some columns.)
|
|
351
|
+
#
|
|
352
|
+
# @param (see cursor_column)
|
|
353
|
+
# @return (see cursor_up)
|
|
354
|
+
def cursor_column_rel(column = 1) = "\e[#{column}a"
|
|
355
|
+
|
|
356
|
+
# Move cursor to given row relative to the current position.
|
|
357
|
+
# (Skip some rows.)
|
|
358
|
+
#
|
|
359
|
+
# @param row [Integer] row index
|
|
360
|
+
# @return (see cursor_up)
|
|
361
|
+
def cursor_row_rel(row = 1) = "\e[#{row}e"
|
|
362
|
+
|
|
352
363
|
# Move to given row and column.
|
|
353
364
|
#
|
|
354
365
|
# @param row [Integer] row index
|
|
@@ -389,20 +400,7 @@ module Terminal
|
|
|
389
400
|
#
|
|
390
401
|
# @param part [:below, :above, :all, :scrollback] screen part to erase
|
|
391
402
|
# @return (see cursor_up)
|
|
392
|
-
def screen_erase(part = :all)
|
|
393
|
-
"\e[#{
|
|
394
|
-
case part
|
|
395
|
-
when :below
|
|
396
|
-
# nop
|
|
397
|
-
when :above
|
|
398
|
-
'1'
|
|
399
|
-
when :scrollback
|
|
400
|
-
'3'
|
|
401
|
-
else # all
|
|
402
|
-
'2'
|
|
403
|
-
end
|
|
404
|
-
}J"
|
|
405
|
-
end
|
|
403
|
+
def screen_erase(part = :all) = "\e[#{@screen_erase[part]}J"
|
|
406
404
|
|
|
407
405
|
# Safe current screen.
|
|
408
406
|
#
|
|
@@ -442,22 +440,17 @@ module Terminal
|
|
|
442
440
|
# @!group Other ANSI control functions
|
|
443
441
|
#
|
|
444
442
|
|
|
443
|
+
# Repeat last char.
|
|
444
|
+
#
|
|
445
|
+
# @param count [Integer] repeat count
|
|
446
|
+
# @return (see cursor_up)
|
|
447
|
+
def char_repeat(count = 1) = "\e[#{count}b"
|
|
448
|
+
|
|
445
449
|
# Erase part of line.
|
|
446
450
|
#
|
|
447
451
|
# @param part [:to_end, :to_start, :all] line part to erase
|
|
448
452
|
# @return (see cursor_up)
|
|
449
|
-
def line_erase(part = :all)
|
|
450
|
-
"\e[#{
|
|
451
|
-
case part
|
|
452
|
-
when :to_end
|
|
453
|
-
# nop
|
|
454
|
-
when :to_start
|
|
455
|
-
'1'
|
|
456
|
-
else # :all
|
|
457
|
-
'2'
|
|
458
|
-
end
|
|
459
|
-
}K"
|
|
460
|
-
end
|
|
453
|
+
def line_erase(part = :all) = "\e[#{@line_erase[part]}K"
|
|
461
454
|
|
|
462
455
|
# Set (tab) title.
|
|
463
456
|
# This is not widely supported; works for
|
|
@@ -486,6 +479,17 @@ module Terminal
|
|
|
486
479
|
# @return (see cursor_up)
|
|
487
480
|
def link(url, text) = "\e]8;;#{url}\a#{text}\e]8;;\a"
|
|
488
481
|
|
|
482
|
+
# Show a simple notification.
|
|
483
|
+
# This is not widely supported; works for
|
|
484
|
+
# Ghosty,
|
|
485
|
+
# iTerm2,
|
|
486
|
+
# Kitty,
|
|
487
|
+
# WezTerm.
|
|
488
|
+
#
|
|
489
|
+
# @param text [#to_s] text to display
|
|
490
|
+
# @return (see cursor_up)
|
|
491
|
+
def notify(text) = "\e]9;#{text}\a"
|
|
492
|
+
|
|
489
493
|
# Create scaled text.
|
|
490
494
|
# It uses the
|
|
491
495
|
# [text sizing protocol](https://sw.kovidgoyal.net/kitty/text-sizing-protocol).
|
|
@@ -559,27 +563,6 @@ module Terminal
|
|
|
559
563
|
caller(1)
|
|
560
564
|
)
|
|
561
565
|
end
|
|
562
|
-
|
|
563
|
-
def _color(str)
|
|
564
|
-
b, v = /\A(fg|bg|on|ul)?_?#?([[:xdigit:]]{1,6})\z/.match(str)&.captures
|
|
565
|
-
if v
|
|
566
|
-
return(
|
|
567
|
-
case v.size
|
|
568
|
-
when 1, 2
|
|
569
|
-
"#{@cbase[b]};5;#{v.hex}"
|
|
570
|
-
when 3
|
|
571
|
-
"#{@cbase[b]};2;#{(v[0] * 2).hex};#{
|
|
572
|
-
(v[1] * 2).hex
|
|
573
|
-
};#{(v[2] * 2).hex}"
|
|
574
|
-
when 6
|
|
575
|
-
"#{@cbase[b]};2;#{v[0, 2].hex};#{v[2, 2].hex};#{v[4, 2].hex}"
|
|
576
|
-
end
|
|
577
|
-
)
|
|
578
|
-
end
|
|
579
|
-
b, v = /\A(fg|bg|on|ul)?_?([a-z]{3,}[0-9]{0,3})\z/.match(str)&.captures
|
|
580
|
-
return unless v
|
|
581
|
-
name = NAMED_COLORS[v] and return "#{@cbase[b]};#{name}"
|
|
582
|
-
end
|
|
583
566
|
end
|
|
584
567
|
|
|
585
568
|
@cbase = { 'bg' => '48', 'on' => '48', 'ul' => '58' }
|
|
@@ -588,63 +571,13 @@ module Terminal
|
|
|
588
571
|
|
|
589
572
|
@re_test =
|
|
590
573
|
/
|
|
591
|
-
(?:\e\[[\d
|
|
574
|
+
(?:\e\[[\d;:?]*[ABCDEFGHJKSTfminsuhl])
|
|
592
575
|
|
|
|
593
576
|
(?:\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
|
|
594
577
|
/x
|
|
595
578
|
|
|
596
579
|
@re_bbcode = /(?:\[((?~[\[\]]))\])/
|
|
597
580
|
|
|
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
581
|
clr_map = {
|
|
649
582
|
# foreground
|
|
650
583
|
'30' => 'black',
|
|
@@ -714,6 +647,56 @@ module Terminal
|
|
|
714
647
|
clr_alias['fg_default', 'default']
|
|
715
648
|
clr_alias['bg_default', 'on_default']
|
|
716
649
|
|
|
650
|
+
attr_map = {
|
|
651
|
+
'' => 'reset',
|
|
652
|
+
'1' => 'bold',
|
|
653
|
+
'2' => 'faint',
|
|
654
|
+
'3' => 'italic',
|
|
655
|
+
'4' => 'underline',
|
|
656
|
+
'5' => 'blink',
|
|
657
|
+
'6' => 'rapid_blink',
|
|
658
|
+
'7' => 'invert',
|
|
659
|
+
'8' => 'hide',
|
|
660
|
+
'9' => 'strike',
|
|
661
|
+
'10' => 'primary_font',
|
|
662
|
+
'11' => 'font1',
|
|
663
|
+
'12' => 'font2',
|
|
664
|
+
'13' => 'font3',
|
|
665
|
+
'14' => 'font4',
|
|
666
|
+
'15' => 'font5',
|
|
667
|
+
'16' => 'font6',
|
|
668
|
+
'17' => 'font7',
|
|
669
|
+
'18' => 'font8',
|
|
670
|
+
'19' => 'font9',
|
|
671
|
+
'20' => 'fraktur',
|
|
672
|
+
'21' => 'double_underline',
|
|
673
|
+
'22' => 'bold_off', # faint_off
|
|
674
|
+
'23' => 'italic_off', # fraktur_off
|
|
675
|
+
'24' => 'underline_off', # double_underline_off
|
|
676
|
+
'25' => 'blink_off', # rapid_blink_off
|
|
677
|
+
'26' => 'proportional',
|
|
678
|
+
'27' => 'invert_off',
|
|
679
|
+
'28' => 'hide_off',
|
|
680
|
+
'29' => 'strike_off',
|
|
681
|
+
# colors ...
|
|
682
|
+
'50' => 'proportional_off',
|
|
683
|
+
'51' => 'framed',
|
|
684
|
+
'52' => 'encircled',
|
|
685
|
+
'53' => 'overlined',
|
|
686
|
+
'54' => 'framed_off', # encircled_off
|
|
687
|
+
'55' => 'overlined_off',
|
|
688
|
+
# ...
|
|
689
|
+
'73' => 'superscript',
|
|
690
|
+
'74' => 'subscript',
|
|
691
|
+
'75' => 'superscript_off', # subscript_off
|
|
692
|
+
# special underline
|
|
693
|
+
'4:3' => 'curly_underline',
|
|
694
|
+
'4:4' => 'dotted_underline',
|
|
695
|
+
'4:5' => 'dashed_underline',
|
|
696
|
+
'4:0' => 'curly_underline_off' # dotted_underline_off, dashed_underline_off
|
|
697
|
+
}.invert
|
|
698
|
+
attr_alias = ->(t, s) { attr_map[t] = attr_map[s] }
|
|
699
|
+
|
|
717
700
|
attr_alias['faint_off', 'bold_off']
|
|
718
701
|
attr_alias['fraktur_off', 'italic_off']
|
|
719
702
|
attr_alias['double_underline_off', 'underline_off']
|
|
@@ -777,7 +760,23 @@ module Terminal
|
|
|
777
760
|
attr_map['/bg'] = clr_map['on_default']
|
|
778
761
|
attr_map['/ul'] = clr_map['ul_default']
|
|
779
762
|
|
|
780
|
-
@attr_map =
|
|
763
|
+
@attr_map =
|
|
764
|
+
Hash.new do |_, str|
|
|
765
|
+
b, v = /\A(fg|bg|on|ul)?_?#?([[:xdigit:]]{1,6})\z/.match(str)&.captures
|
|
766
|
+
unless v
|
|
767
|
+
b = /\A(fg|bg|on|ul)?_?([a-z]{3,}[0-9]{0,3})\z/.match(str) or next
|
|
768
|
+
name = NAMED_COLORS[b[2]] or next
|
|
769
|
+
next "#{@cbase[b[1]]};#{name}"
|
|
770
|
+
end
|
|
771
|
+
case v.size
|
|
772
|
+
when 1, 2
|
|
773
|
+
"#{@cbase[b]};5;#{v.hex}"
|
|
774
|
+
when 3
|
|
775
|
+
"#{@cbase[b]};2;#{(v[0] * 2).hex};#{(v[1] * 2).hex};#{(v[2] * 2).hex}"
|
|
776
|
+
when 6
|
|
777
|
+
"#{@cbase[b]};2;#{v[0, 2].hex};#{v[2, 2].hex};#{v[4, 2].hex}"
|
|
778
|
+
end
|
|
779
|
+
end
|
|
781
780
|
attr_map.merge!(clr_map).keys.sort!.each { @attr_map[_1] = attr_map[_1] }
|
|
782
781
|
@attr_map.freeze
|
|
783
782
|
|
|
@@ -785,21 +784,29 @@ module Terminal
|
|
|
785
784
|
@attrs_map.default_proc = @attr_map.default_proc
|
|
786
785
|
@attrs_map.compare_by_identity.freeze
|
|
787
786
|
|
|
787
|
+
@screen_erase = { below: nil, above: '1', scrollback: '3' }
|
|
788
|
+
@screen_erase.default = '2'
|
|
789
|
+
@screen_erase.compare_by_identity.freeze
|
|
790
|
+
|
|
791
|
+
@line_erase = { to_end: nil, to_start: '1' }
|
|
792
|
+
@line_erase.default = '2'
|
|
793
|
+
@line_erase.compare_by_identity.freeze
|
|
794
|
+
|
|
788
795
|
autoload :NAMED_COLORS, "#{__dir__}/ansi/named_colors.rb"
|
|
789
796
|
private_constant :NAMED_COLORS
|
|
790
797
|
|
|
791
798
|
# @private
|
|
792
|
-
RESET = self[:reset]
|
|
799
|
+
RESET = -self[:reset]
|
|
793
800
|
|
|
794
801
|
# @private
|
|
795
802
|
FULL_RESET = "\ec"
|
|
796
803
|
|
|
797
804
|
# @private
|
|
798
|
-
CURSOR_HOME = cursor_pos(nil, nil)
|
|
805
|
+
CURSOR_HOME = -cursor_pos(nil, nil)
|
|
799
806
|
# @private
|
|
800
|
-
CURSOR_FIRST_ROW = cursor_pos(1)
|
|
807
|
+
CURSOR_FIRST_ROW = -cursor_pos(1)
|
|
801
808
|
# @private
|
|
802
|
-
CURSOR_FIRST_COLUMN = cursor_column(1)
|
|
809
|
+
CURSOR_FIRST_COLUMN = -cursor_column(1)
|
|
803
810
|
|
|
804
811
|
# @private
|
|
805
812
|
CURSOR_SHOW = "\e[?25h"
|
|
@@ -817,13 +824,13 @@ module Terminal
|
|
|
817
824
|
CURSOR_POS_RESTORE = "\e8"
|
|
818
825
|
|
|
819
826
|
# @private
|
|
820
|
-
SCREEN_ERASE = screen_erase
|
|
827
|
+
SCREEN_ERASE = -screen_erase
|
|
821
828
|
# @private
|
|
822
|
-
SCREEN_ERASE_BELOW = screen_erase(:below)
|
|
829
|
+
SCREEN_ERASE_BELOW = -screen_erase(:below)
|
|
823
830
|
# @private
|
|
824
|
-
SCREEN_ERASE_ABOVE = screen_erase(:above)
|
|
831
|
+
SCREEN_ERASE_ABOVE = -screen_erase(:above)
|
|
825
832
|
# @private
|
|
826
|
-
SCREEN_ERASE_SCROLLBACK = screen_erase(:scrollback)
|
|
833
|
+
SCREEN_ERASE_SCROLLBACK = -screen_erase(:scrollback)
|
|
827
834
|
|
|
828
835
|
# @private
|
|
829
836
|
SCREEN_SAVE = "\e[?47h"
|
|
@@ -832,7 +839,7 @@ module Terminal
|
|
|
832
839
|
|
|
833
840
|
# @private
|
|
834
841
|
# @comment at least Kitty requires CURSOR_HOME too
|
|
835
|
-
SCREEN_ALTERNATE = "\e[?1049h#{CURSOR_HOME}"
|
|
842
|
+
SCREEN_ALTERNATE = -"\e[?1049h#{CURSOR_HOME}"
|
|
836
843
|
# @private
|
|
837
844
|
SCREEN_ALTERNATE_OFF = "\e[?1049l"
|
|
838
845
|
|
|
@@ -842,21 +849,19 @@ module Terminal
|
|
|
842
849
|
SCREEN_REVERSE_MODE_OFF = "\e[?5l"
|
|
843
850
|
|
|
844
851
|
# @private
|
|
845
|
-
LINE_ERASE = line_erase
|
|
852
|
+
LINE_ERASE = -line_erase
|
|
846
853
|
# @private
|
|
847
|
-
LINE_ERASE_TO_END = line_erase(:to_end)
|
|
854
|
+
LINE_ERASE_TO_END = -line_erase(:to_end)
|
|
848
855
|
# @private
|
|
849
|
-
LINE_ERASE_TO_START = line_erase(:to_start)
|
|
856
|
+
LINE_ERASE_TO_START = -line_erase(:to_start)
|
|
850
857
|
# @private
|
|
851
|
-
LINE_ERASE_PREV = "#{cursor_prev_line(nil)}#{LINE_ERASE}"
|
|
858
|
+
LINE_ERASE_PREV = -"#{cursor_prev_line(nil)}#{LINE_ERASE}"
|
|
852
859
|
|
|
853
860
|
# @comment seems not widely supported:
|
|
854
861
|
# doubled: def cursor_column(column = 1) = "\e[#{column}`"
|
|
855
862
|
# doubled: def cursor_row(row = 1) = "\e[#{row}d"
|
|
856
863
|
# doubled: def cursor_pos(row, col) = "\e[#{row};#{col}f"
|
|
857
864
|
#
|
|
858
|
-
# def cursor_column_rel(columns = 1) = "\e[#{columns}a"
|
|
859
|
-
# def cursor_row_rel(rows = 1) = "\e[#{rows}e"
|
|
860
865
|
# def cursor_tab(count = 1) = "\e[#{column}I"
|
|
861
866
|
# def cursor_reverse_tab(count = 1) = "\e[#{count}Z"
|
|
862
867
|
#
|
|
@@ -867,20 +872,14 @@ module Terminal
|
|
|
867
872
|
# def chars_delete(count = 1) = "\e[#{count}P"
|
|
868
873
|
# def chars_erase(count = 1) = "\e[#{count}X"
|
|
869
874
|
#
|
|
870
|
-
# def chars_repeat_last(count = 1) = "\e[#{count}b"
|
|
871
|
-
#
|
|
872
|
-
# def notify(title) = "\e]9;#{title}\a"
|
|
873
|
-
#
|
|
874
875
|
# def set_scroll_region(top = nil, bottom = nil) = "\e[#{top};#{bottom}r"
|
|
875
876
|
|
|
876
877
|
# @comment other:
|
|
877
878
|
# "\eE" same as "\r\n"
|
|
878
|
-
# "\eD" same as "\n" but preserves
|
|
879
|
+
# "\eD" same as "\n" but preserves column
|
|
879
880
|
# "\eM" reverse "\n"
|
|
880
881
|
# "\e[6n" report Cursor Position as "ESC \[ row ; col R"
|
|
881
882
|
# "\e[21t report window’s title as ESC ] l title ESC \"
|
|
882
|
-
# "\e[?1004h" report focus lost "\e[O" and focus get "\e[I"
|
|
883
|
-
# (disable by "\e[?1004l")
|
|
884
883
|
|
|
885
884
|
# @comment TODO:
|
|
886
885
|
# https://sw.kovidgoyal.net/kitty/desktop-notifications
|