natty-ui 0.8.0 → 0.9.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/.yardopts +3 -2
- data/examples/24bit-colors.rb +11 -7
- data/examples/3bit-colors.rb +3 -2
- data/examples/8bit-colors.rb +2 -2
- data/examples/animate.rb +24 -0
- data/examples/attributes.rb +20 -65
- data/examples/demo.rb +39 -203
- data/examples/illustration.png +0 -0
- data/examples/illustration.rb +26 -23
- data/examples/{list_in_columns.rb → ls.rb} +11 -11
- data/examples/message.rb +30 -0
- data/examples/progress.rb +2 -2
- data/examples/query.rb +6 -2
- data/examples/read_key.rb +13 -0
- data/examples/table.rb +26 -8
- data/lib/natty-ui/ansi.rb +354 -328
- data/lib/natty-ui/ansi_constants.rb +73 -0
- data/lib/natty-ui/ansi_wrapper.rb +68 -23
- data/lib/natty-ui/key_map.rb +119 -0
- data/lib/natty-ui/line_animation/default.rb +35 -0
- data/lib/natty-ui/line_animation/matrix.rb +28 -0
- data/lib/natty-ui/line_animation/rainbow.rb +30 -0
- data/lib/natty-ui/line_animation/test.rb +29 -0
- data/lib/natty-ui/line_animation/type_writer.rb +64 -0
- data/lib/natty-ui/line_animation.rb +54 -0
- data/lib/natty-ui/version.rb +1 -1
- data/lib/natty-ui/wrapper/animate.rb +17 -0
- data/lib/natty-ui/wrapper/ask.rb +2 -8
- data/lib/natty-ui/wrapper/framed.rb +26 -21
- data/lib/natty-ui/wrapper/heading.rb +1 -1
- data/lib/natty-ui/wrapper/horizontal_rule.rb +3 -3
- data/lib/natty-ui/wrapper/list_in_columns.rb +7 -4
- data/lib/natty-ui/wrapper/message.rb +4 -4
- data/lib/natty-ui/wrapper/progress.rb +33 -8
- data/lib/natty-ui/wrapper/query.rb +9 -13
- data/lib/natty-ui/wrapper/request.rb +2 -2
- data/lib/natty-ui/wrapper/section.rb +25 -11
- data/lib/natty-ui/wrapper/table.rb +11 -11
- data/lib/natty-ui/wrapper.rb +19 -14
- data/lib/natty-ui.rb +33 -12
- metadata +16 -4
data/lib/natty-ui/ansi.rb
CHANGED
@@ -5,164 +5,148 @@ module NattyUI
|
|
5
5
|
# Helper module for ANSI escape codes.
|
6
6
|
#
|
7
7
|
module Ansi
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
CURSOR_LEFT = "\e[D"
|
16
|
-
|
17
|
-
# ANSI code to move the cursor right.
|
18
|
-
CURSOR_RIGHT = "\e[C"
|
19
|
-
|
20
|
-
# ANSI code to move the cursor to beginning of the line below.
|
21
|
-
CURSOR_LINE_DOWN = "\e[E"
|
22
|
-
|
23
|
-
# ANSI code to move the cursor to beginning of the line up.
|
24
|
-
CURSOR_LINE_UP = "\e[F"
|
25
|
-
|
26
|
-
# ANSI code to hide the cursor.
|
27
|
-
CURSOR_HIDE = "\e[?25l"
|
28
|
-
|
29
|
-
# ANSI code to show the cursor (again).
|
30
|
-
CURSOR_SHOW = "\e[?25h"
|
31
|
-
|
32
|
-
# ANSI code to save current cursor position.
|
33
|
-
CURSOR_SAVE_POS = "\e[s"
|
34
|
-
|
35
|
-
# ANSI code to restore saved cursor position.
|
36
|
-
CURSOR_RESTORE_POS = "\e[u"
|
37
|
-
|
38
|
-
# ANSI code to set cursor position on upper left corner.
|
39
|
-
CURSOR_HOME = "\e[H"
|
40
|
-
|
41
|
-
# ANSI code to erase current line and position to first column.
|
42
|
-
LINE_CLEAR = "\e[1K\e[0G"
|
43
|
-
|
44
|
-
# ANSI code to erase current line.
|
45
|
-
LINE_ERASE = "\e[2K"
|
46
|
-
|
47
|
-
# ANSI code to erase to end of current line.
|
48
|
-
LINE_ERASE_TO_END = "\e[0K"
|
49
|
-
|
50
|
-
# ANSI code to erase to begin of current line.
|
51
|
-
LINE_ERASE_TO_BEGIN = "\e[1K"
|
52
|
-
|
53
|
-
# ANSI code to save current screen state.
|
54
|
-
SCREEN_SAVE = "\e[?47h"
|
55
|
-
|
56
|
-
# ANSI code to restore screen state.
|
57
|
-
SCREEN_RESTORE = "\e[?47l"
|
8
|
+
class << self
|
9
|
+
# Supported attribute names.
|
10
|
+
# @see []
|
11
|
+
#
|
12
|
+
# @attribute [r] attribute_names
|
13
|
+
# @return [Array<Symbol>] supported attribute names
|
14
|
+
def attribute_names = SATTR.keys.sort!
|
58
15
|
|
59
|
-
|
60
|
-
|
16
|
+
# Supported color names.
|
17
|
+
# @see []
|
18
|
+
#
|
19
|
+
# @attribute [r] color_names
|
20
|
+
# @return [Array<Symbol>] supported color names
|
21
|
+
def color_names = SCLR.keys
|
61
22
|
|
62
|
-
|
63
|
-
SCREEN_ERASE_BELOW = "\e[0J"
|
23
|
+
# @!group Control functions
|
64
24
|
|
65
|
-
|
66
|
-
|
25
|
+
# Move cursor given lines up.
|
26
|
+
#
|
27
|
+
# @param lines [Integer] number of lines to move
|
28
|
+
# @return [String] ANSI control code
|
29
|
+
def cursor_up(lines = 1) = "\e[#{lines}A"
|
67
30
|
|
68
|
-
|
69
|
-
|
31
|
+
# Move cursor given lines down.
|
32
|
+
#
|
33
|
+
# @param (see cursor_up)
|
34
|
+
# @return (see cursor_up)
|
35
|
+
def cursor_down(lines = 1) = "\e[#{lines}B"
|
70
36
|
|
71
|
-
|
72
|
-
|
37
|
+
# Move cursor given colums forward.
|
38
|
+
#
|
39
|
+
# @param columns [Integer] number of columns to move
|
40
|
+
# @return (see cursor_up)
|
41
|
+
def cursor_forward(columns = 1) = "\e[#{columns}C"
|
73
42
|
|
74
|
-
|
75
|
-
|
43
|
+
# Move cursor given colums back.
|
44
|
+
#
|
45
|
+
# @param (see cursor_forward)
|
46
|
+
# @return (see cursor_up)
|
47
|
+
def cursor_back(columns = 1) = "\e[#{columns}D"
|
76
48
|
|
77
|
-
|
78
|
-
|
49
|
+
# Move cursor of beginning of the given next line.
|
50
|
+
#
|
51
|
+
# @param (see cursor_up)
|
52
|
+
# @return (see cursor_up)
|
53
|
+
def cursor_next_line(lines = 1) = "\e[#{lines}E"
|
79
54
|
|
80
|
-
|
81
|
-
|
55
|
+
# Move cursor of beginning of the given previous line.
|
56
|
+
#
|
57
|
+
# @param (see cursor_up)
|
58
|
+
# @return (see cursor_up)
|
59
|
+
def cursor_previous_line(lines = 1) = "\e[#{lines}F"
|
60
|
+
alias cursor_prev_line cursor_previous_line
|
82
61
|
|
83
|
-
|
84
|
-
|
62
|
+
# Move cursor to given column in the current row.
|
63
|
+
#
|
64
|
+
# @param column [Integer] column index
|
65
|
+
# @return (see cursor_up)
|
66
|
+
def cursor_column(column = 1) = "\e[#{column}G"
|
85
67
|
|
86
|
-
|
87
|
-
#
|
88
|
-
# @
|
89
|
-
|
90
|
-
|
91
|
-
# @param lines [Integer] number of lines
|
92
|
-
# @return [String] ANSI code to move the cursor down
|
93
|
-
def cursor_down(lines = nil) = "\e[#{lines}B"
|
94
|
-
|
95
|
-
# @param columns [Integer] number of columns
|
96
|
-
# @return [String] ANSI code to move the cursor right
|
97
|
-
def cursor_right(columns = nil) = "\e[#{columns}C"
|
98
|
-
|
99
|
-
# @param columns [Integer] number of columns
|
100
|
-
# @return [String] ANSI code to move the cursor left
|
101
|
-
def cursor_left(columns = nil) = "\e[#{columns}D"
|
102
|
-
|
103
|
-
# @param lines [Integer] number of lines
|
104
|
-
# @return [String] ANSI code to move the cursor to beginning of some lines
|
105
|
-
# below
|
106
|
-
def cursor_line_down(lines = nil) = "\e[#{lines}E"
|
107
|
-
|
108
|
-
# @param lines [Integer] number of lines
|
109
|
-
# @return [String] ANSI code to move the cursor to beginning of some lines
|
110
|
-
# up
|
111
|
-
def cursor_line_up(lines = nil) = "\e[#{lines}F"
|
112
|
-
|
113
|
-
# @param column [Integer] column number
|
114
|
-
# @return [String] ANSI code to move the cursor to given column
|
115
|
-
def cursor_column(column = nil) = "\e[#{column}G"
|
116
|
-
|
117
|
-
# @param row [Integer] row to set cursor
|
118
|
-
# @param column [Integer] column to set cursor
|
119
|
-
# @return [String] ANSI code to set cursor position
|
68
|
+
# Move cursor to given row and column counting from the top left corner.
|
69
|
+
#
|
70
|
+
# @param row [Integer] row index
|
71
|
+
# @param column [Integer] column index
|
72
|
+
# @return (see cursor_up)
|
120
73
|
def cursor_pos(row, column = nil)
|
121
74
|
return column ? "\e[#{row};#{column}H" : "\e[#{row}H" if row
|
122
75
|
column ? "\e[;#{column}H" : "\e[H"
|
123
76
|
end
|
124
77
|
|
125
|
-
#
|
126
|
-
|
127
|
-
#
|
78
|
+
# @comment ??? def cursor_tab(count = 1) = "\e[#{column}I"
|
79
|
+
|
80
|
+
# Erase screen.
|
128
81
|
#
|
129
|
-
# @param
|
130
|
-
# @
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
82
|
+
# @param part [:below, :above, :scrollback, :entire] part to erase
|
83
|
+
# @return (see cursor_up)
|
84
|
+
def screen_erase(part = :entire)
|
85
|
+
return "\e[0J" if part == :below
|
86
|
+
return "\e[1J" if part == :above
|
87
|
+
return "\e[3J" if part == :scrollback
|
88
|
+
"\e[2J"
|
136
89
|
end
|
137
90
|
|
138
|
-
#
|
91
|
+
# Clear part of current line.
|
139
92
|
#
|
140
|
-
# @
|
93
|
+
# @param part [:to_end, :to_start, :entire] part to delete
|
94
|
+
# @return (see cursor_up)
|
95
|
+
def line_erase(part = :entire)
|
96
|
+
return "\e[0K" if part == :to_end
|
97
|
+
return "\e[1K" if part == :to_start
|
98
|
+
"\e[2K"
|
99
|
+
end
|
100
|
+
|
101
|
+
# @comment ??? def line_insert(lines = 1) = "\e[#{lines}L"
|
102
|
+
# @comment ??? def line_delete(lines = 1) = "\e[#{lines}M"
|
103
|
+
# @comment ??? def chars_delete(count = 1) = "\e[#{count}P"
|
104
|
+
|
105
|
+
# Scroll window given lines up.
|
141
106
|
#
|
142
|
-
# @param
|
143
|
-
# @return
|
144
|
-
def
|
107
|
+
# @param lines [Integer] number of lines to scroll
|
108
|
+
# @return (see cursor_up)
|
109
|
+
def scroll_up(lines = 1) = "\e[;#{lines}S"
|
145
110
|
|
146
|
-
#
|
111
|
+
# Scroll window given lines down.
|
147
112
|
#
|
148
|
-
#
|
113
|
+
# @param (see scroll_up)
|
114
|
+
# @return (see cursor_up)
|
115
|
+
def scroll_down(lines = 1) = "\e[;#{lines}T"
|
116
|
+
|
117
|
+
# @comment ??? def chars_erase(count = 1) = "\e[#{count}X"
|
118
|
+
# @comment ??? def cursor_reverse_tab(count = 1) = "\e[#{count}Z"
|
119
|
+
|
120
|
+
# set absolute col
|
121
|
+
# @comment ??? doubled! def cursor_column(column = 1) = "\e[#{column}`"
|
122
|
+
# set relative column
|
123
|
+
# @comment ??? def cursor_column_rel(column = 1) = "\e[#{column}a"
|
124
|
+
# set absolute row
|
125
|
+
# @comment ??? def cursor_row(row = 1) = "\e[#{row}d"
|
126
|
+
# set relative row
|
127
|
+
# @comment ??? def cursor_row_rel(row = 1) = "\e[#{row}e"
|
128
|
+
|
129
|
+
# Change window title.
|
130
|
+
# This is not widely supported but by XTerm and iTerm.
|
149
131
|
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
|
153
|
-
|
154
|
-
#
|
155
|
-
#
|
156
|
-
# `invert_off`, `reverse_off`, `reveal`, `strike_off`, `proportional_off`,
|
157
|
-
# `spacing_off`, `framed`, `encircled`, `overlined`, `framed_off`,
|
158
|
-
# `encircled_off`, `overlined_off`.
|
132
|
+
# @param [String] title text
|
133
|
+
# @return (see cursor_up)
|
134
|
+
def window_title(title) = "\e]2;#{title}\e\\"
|
135
|
+
|
136
|
+
# Change tab title.
|
137
|
+
# This is not widely supported but by iTerm.
|
159
138
|
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
|
163
|
-
|
164
|
-
#
|
139
|
+
# @param [String] title text
|
140
|
+
# @return (see cursor_up)
|
141
|
+
def tab_title(title) = "\e]0;#{title}\a"
|
142
|
+
|
143
|
+
# @!endgroup
|
144
|
+
|
145
|
+
# @!group Tool functions
|
146
|
+
|
147
|
+
# Combine given ANSI {.attribute_names}, {.color_names} and color codes.
|
165
148
|
#
|
149
|
+
# Colors can specified by their name for ANSI 3-bit and 4-bit colors.
|
166
150
|
# For 8-bit ANSI colors use 2-digit hexadecimal values `00`...`ff`.
|
167
151
|
#
|
168
152
|
# To use RGB ANSI colors (24-bit colors) specify 3-digit or 6-digit
|
@@ -172,11 +156,9 @@ module NattyUI
|
|
172
156
|
#
|
173
157
|
# To use a color as background color prefix the color attribute with `bg_`
|
174
158
|
# or `on_`.
|
175
|
-
#
|
176
159
|
# To use a color as underline color prefix the color attribute with `ul_`.
|
177
|
-
#
|
178
|
-
#
|
179
|
-
# color the color value can be prefixed with `fg_`.
|
160
|
+
# To clarify that a color attribute have to be used as foreground
|
161
|
+
# color use the prefix `fg_`.
|
180
162
|
#
|
181
163
|
# @example Valid Foreground Color Attributes
|
182
164
|
# Ansi[:yellow]
|
@@ -219,12 +201,17 @@ module NattyUI
|
|
219
201
|
attributes
|
220
202
|
.map do |arg|
|
221
203
|
case arg
|
222
|
-
when Symbol
|
223
|
-
|
204
|
+
when Symbol
|
205
|
+
SATTR[arg] || SCLR[arg] || color(arg.to_s) ||
|
206
|
+
invalid_argument(arg)
|
207
|
+
when String
|
208
|
+
ATTR[arg] || CLR[arg] || color(arg) || invalid_argument(arg)
|
224
209
|
when (0..255)
|
225
210
|
"38;5;#{arg}"
|
226
|
-
when (256..
|
211
|
+
when (256..511)
|
227
212
|
"48;5;#{arg}"
|
213
|
+
when (512..767)
|
214
|
+
"58;5;#{arg}"
|
228
215
|
else
|
229
216
|
invalid_argument(arg)
|
230
217
|
end
|
@@ -233,8 +220,29 @@ module NattyUI
|
|
233
220
|
}m"
|
234
221
|
end
|
235
222
|
|
236
|
-
#
|
237
|
-
#
|
223
|
+
# Decorate given `str` with ANSI attributes and colors.
|
224
|
+
#
|
225
|
+
# @see []
|
226
|
+
#
|
227
|
+
# @param str [#to_s] object to be decorated
|
228
|
+
# @param attributes [Symbol, String] attribute names to be used
|
229
|
+
# @param reset [Boolean] whether to include reset code for ANSI attributes
|
230
|
+
# @return [String] `str` converted and decorated with the ANSI `attributes`
|
231
|
+
def embellish(str, *attributes, reset: true)
|
232
|
+
attributes = self[*attributes]
|
233
|
+
attributes.empty? ? str.to_s : "#{attributes}#{str}#{"\e[0m" if reset}"
|
234
|
+
end
|
235
|
+
|
236
|
+
# Remove ANSI functions, attributes and colors from given string.
|
237
|
+
#
|
238
|
+
# @see embellish
|
239
|
+
#
|
240
|
+
# @param str [#to_s] string to be modified
|
241
|
+
# @return [String] string without ANSI attributes
|
242
|
+
def blemish(str) = str.to_s.gsub(/(\e\[(?~[a-zA-Z])[a-zA-Z])/, '')
|
243
|
+
|
244
|
+
# Try to combine given ANSI attributes and colors.
|
245
|
+
# The attributes and colors have to be seperated by space char (" ").
|
238
246
|
#
|
239
247
|
# @example Valid Attribute String
|
240
248
|
# Ansi.try_convert('bold italic blink red on#00ff00')
|
@@ -251,10 +259,41 @@ module NattyUI
|
|
251
259
|
def try_convert(attributes)
|
252
260
|
return if (attributes = attributes.to_s.split).empty?
|
253
261
|
"\e[#{
|
254
|
-
attributes
|
262
|
+
attributes
|
263
|
+
.map! { |a| ATTR[a] || CLR[a] || color(a) || return }
|
264
|
+
.join(';')
|
255
265
|
}m"
|
256
266
|
end
|
257
267
|
|
268
|
+
# @param str [#to_s] plain text string to enrich with color
|
269
|
+
# @param type [:foreground, :background, :underline] type of coloring
|
270
|
+
# @param frequence [Float] color change frequency
|
271
|
+
# @param spread [Float] number of chars with same color
|
272
|
+
# @param seed [Float] start index on sinus curve
|
273
|
+
# @return [String] fancy text
|
274
|
+
def rainbow(
|
275
|
+
str,
|
276
|
+
type: :foreground,
|
277
|
+
frequence: 0.3,
|
278
|
+
spread: 0.8,
|
279
|
+
seed: 1.1
|
280
|
+
)
|
281
|
+
type = color_type(type)
|
282
|
+
pos = -1
|
283
|
+
str
|
284
|
+
.to_s
|
285
|
+
.chars
|
286
|
+
.map! do |char|
|
287
|
+
i = (seed + ((pos += 1) / spread)) * frequence
|
288
|
+
"\e[#{type};2;#{(Math.sin(i) * 255).abs.to_i};" \
|
289
|
+
"#{(Math.sin(i + PI2_THIRD) * 255).abs.to_i};" \
|
290
|
+
"#{(Math.sin(i + PI4_THIRD) * 255).abs.to_i}m#{char}"
|
291
|
+
end
|
292
|
+
.join
|
293
|
+
end
|
294
|
+
|
295
|
+
# @!endgroup
|
296
|
+
|
258
297
|
private
|
259
298
|
|
260
299
|
def invalid_argument(name)
|
@@ -265,195 +304,182 @@ module NattyUI
|
|
265
304
|
)
|
266
305
|
end
|
267
306
|
|
307
|
+
def color_type(type)
|
308
|
+
case type
|
309
|
+
when :background, :bg, 'background', 'bg'
|
310
|
+
48
|
311
|
+
when :underline, :ul, 'underline', 'ul'
|
312
|
+
58
|
313
|
+
else
|
314
|
+
38
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
268
318
|
def color(val)
|
269
|
-
|
270
|
-
base
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
val.delete_prefix!(':') || val.delete_prefix!('_')
|
279
|
-
'48;'
|
280
|
-
else
|
281
|
-
'38;'
|
282
|
-
end
|
283
|
-
val.delete_prefix!('#')
|
284
|
-
case val.size
|
285
|
-
when 1, 2
|
286
|
-
"#{base}5;#{val.hex}" if /\A[[:xdigit:]]+\z/.match?(val)
|
287
|
-
when 3
|
288
|
-
if /\A[[:xdigit:]]+\z/.match?(val)
|
289
|
-
"#{base}2;#{(val[0] * 2).hex};#{(val[1] * 2).hex};#{
|
290
|
-
(val[2] * 2).hex
|
291
|
-
}"
|
292
|
-
end
|
293
|
-
when 6
|
294
|
-
if /\A[[:xdigit:]]+\z/.match?(val)
|
295
|
-
"#{base}2;#{val[0, 2].hex};#{val[2, 2].hex};#{val[4, 2].hex}"
|
296
|
-
end
|
319
|
+
base = CLR_PREFIX[val[0, 2]]
|
320
|
+
idx = base ? 2 : 0
|
321
|
+
base ||= '38'
|
322
|
+
idx += 1 if val[idx] == '_' || val[idx] == ':'
|
323
|
+
idx += 1 if val[idx] == '#'
|
324
|
+
val = val[idx..]
|
325
|
+
return "#{base};5;#{val.hex}" if /\A[[:xdigit:]]{1,2}\z/.match?(val)
|
326
|
+
if /\A[[:xdigit:]]{6}\z/.match?(val)
|
327
|
+
return "#{base};2;#{val[0, 2].hex};#{val[2, 2].hex};#{val[4, 2].hex}"
|
297
328
|
end
|
329
|
+
return unless /\A[[:xdigit:]]{3}\z/.match?(val)
|
330
|
+
"#{base};2;#{(val[0] * 2).hex};#{(val[1] * 2).hex};#{(val[2] * 2).hex}"
|
298
331
|
end
|
299
332
|
end
|
300
333
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
ul_bright_red: '58;2;255;0;0',
|
450
|
-
ul_bright_green: '58;2;0;255;0',
|
451
|
-
ul_bright_yellow: '58;2;255;255;0',
|
452
|
-
ul_bright_blue: '58;2;0;0;255',
|
453
|
-
ul_bright_magenta: '58;2;255;0;255',
|
454
|
-
ul_bright_cyan: '58;2;0;255;255',
|
455
|
-
ul_bright_white: '58;2;255;255;255'
|
456
|
-
}.tap { _1.merge!(_1.transform_keys(&:to_s)).freeze }
|
457
|
-
private_constant :ATTRIBUTES
|
334
|
+
CLR_PREFIX = {
|
335
|
+
'fg' => '38',
|
336
|
+
'bg' => '48',
|
337
|
+
'ul' => '58',
|
338
|
+
'on' => '48'
|
339
|
+
}.freeze
|
340
|
+
|
341
|
+
PI2_THIRD = 2 * Math::PI / 3.0
|
342
|
+
PI4_THIRD = 4 * Math::PI / 3.0
|
343
|
+
|
344
|
+
SATTR =
|
345
|
+
Module
|
346
|
+
.new do
|
347
|
+
def self.to_hash
|
348
|
+
map = {
|
349
|
+
# alternative names
|
350
|
+
slow_blink: 5,
|
351
|
+
conceal: 8,
|
352
|
+
default_font: 10,
|
353
|
+
doubly: 21,
|
354
|
+
faint_off: 22,
|
355
|
+
fraktur_off: 23,
|
356
|
+
spacing: 26,
|
357
|
+
conceal_off: 28,
|
358
|
+
spacing_off: 50,
|
359
|
+
encircled_off: 54,
|
360
|
+
subscript_off: 75,
|
361
|
+
# special
|
362
|
+
curly_underline_off: '4:0',
|
363
|
+
dotted_underline_off: '4:0',
|
364
|
+
dashed_underline_off: '4:0',
|
365
|
+
curly_underline: '4:3',
|
366
|
+
dotted_underline: '4:4',
|
367
|
+
dashed_underline: '4:5'
|
368
|
+
}
|
369
|
+
add = ->(s, n) { n.each_with_index { |a, idx| map[a] = s + idx } }
|
370
|
+
add[
|
371
|
+
0,
|
372
|
+
%i[
|
373
|
+
reset
|
374
|
+
bold
|
375
|
+
faint
|
376
|
+
italic
|
377
|
+
underline
|
378
|
+
blink
|
379
|
+
rapid_blink
|
380
|
+
invert
|
381
|
+
hide
|
382
|
+
strike
|
383
|
+
primary_font
|
384
|
+
font1
|
385
|
+
font2
|
386
|
+
font3
|
387
|
+
font4
|
388
|
+
font5
|
389
|
+
font6
|
390
|
+
font7
|
391
|
+
font8
|
392
|
+
font9
|
393
|
+
fraktur
|
394
|
+
double_underline
|
395
|
+
bold_off
|
396
|
+
italic_off
|
397
|
+
underline_off
|
398
|
+
blink_off
|
399
|
+
proportional
|
400
|
+
invert_off
|
401
|
+
reveal
|
402
|
+
strike_off
|
403
|
+
]
|
404
|
+
]
|
405
|
+
add[
|
406
|
+
50,
|
407
|
+
%i[
|
408
|
+
proportional_off
|
409
|
+
framed
|
410
|
+
encircled
|
411
|
+
overlined
|
412
|
+
framed_off
|
413
|
+
overlined_off
|
414
|
+
]
|
415
|
+
]
|
416
|
+
add[73, %i[superscript subscript superscript_off]]
|
417
|
+
map
|
418
|
+
end
|
419
|
+
end
|
420
|
+
.to_hash
|
421
|
+
.compare_by_identity
|
422
|
+
.freeze
|
423
|
+
|
424
|
+
CLR =
|
425
|
+
Module
|
426
|
+
.new do
|
427
|
+
def self.to_hash
|
428
|
+
clr = {
|
429
|
+
0 => 'black',
|
430
|
+
1 => 'red',
|
431
|
+
2 => 'green',
|
432
|
+
3 => 'yellow',
|
433
|
+
4 => 'blue',
|
434
|
+
5 => 'magenta',
|
435
|
+
6 => 'cyan',
|
436
|
+
7 => 'white'
|
437
|
+
}
|
438
|
+
map = {}
|
439
|
+
add = ->(s, p) { clr.each_pair { |i, n| map["#{p}#{n}"] = s + i } }
|
440
|
+
ul = ->(r, g, b) { "58;2;#{r};#{g};#{b}" }
|
441
|
+
add[30, nil]
|
442
|
+
map['default'] = 39
|
443
|
+
add[90, 'bright_']
|
444
|
+
add[30, 'fg_']
|
445
|
+
map['fg_default'] = 39
|
446
|
+
add[90, 'fg_bright_']
|
447
|
+
add[40, 'bg_']
|
448
|
+
map['bg_default'] = 49
|
449
|
+
add[100, 'bg_bright_']
|
450
|
+
add[40, 'on_']
|
451
|
+
map['on_default'] = 49
|
452
|
+
add[100, 'on_bright_']
|
453
|
+
map.merge!(
|
454
|
+
'ul_black' => ul[0, 0, 0],
|
455
|
+
'ul_red' => ul[128, 0, 0],
|
456
|
+
'ul_green' => ul[0, 128, 0],
|
457
|
+
'ul_yellow' => ul[128, 128, 0],
|
458
|
+
'ul_blue' => ul[0, 0, 128],
|
459
|
+
'ul_magenta' => ul[128, 0, 128],
|
460
|
+
'ul_cyan' => ul[0, 128, 128],
|
461
|
+
'ul_white' => ul[128, 128, 128],
|
462
|
+
'ul_default' => '59',
|
463
|
+
'ul_bright_black' => ul[64, 64, 64],
|
464
|
+
'ul_bright_red' => ul[255, 0, 0],
|
465
|
+
'ul_bright_green' => ul[0, 255, 0],
|
466
|
+
'ul_bright_yellow' => ul[255, 255, 0],
|
467
|
+
'ul_bright_blue' => ul[0, 0, 255],
|
468
|
+
'ul_bright_magenta' => ul[255, 0, 255],
|
469
|
+
'ul_bright_cyan' => ul[0, 255, 255],
|
470
|
+
'ul_bright_white' => ul[255, 255, 255]
|
471
|
+
)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
.to_hash
|
475
|
+
.freeze
|
476
|
+
|
477
|
+
ATTR = SATTR.transform_keys(&:to_s).freeze
|
478
|
+
SCLR = CLR.transform_keys(&:to_sym).compare_by_identity.freeze
|
479
|
+
|
480
|
+
private_constant :CLR_PREFIX, :PI2_THIRD, :PI4_THIRD
|
481
|
+
private_constant :SATTR, :SCLR, :ATTR, :CLR
|
458
482
|
end
|
459
483
|
end
|
484
|
+
|
485
|
+
require_relative 'ansi_constants'
|