natty-ui 0.9.1 → 0.9.3
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/examples/3bit-colors.rb +2 -2
- data/examples/demo.rb +1 -1
- data/examples/illustration.rb +4 -3
- data/examples/table.rb +17 -12
- data/lib/natty-ui/ansi/constants.rb +75 -0
- data/lib/natty-ui/ansi.rb +15 -9
- data/lib/natty-ui/ansi_wrapper.rb +23 -33
- data/lib/natty-ui/east_asian_width.rb +1271 -0
- data/lib/natty-ui/line_animation/default.rb +1 -1
- data/lib/natty-ui/line_animation/matrix.rb +1 -1
- data/lib/natty-ui/line_animation/rainbow.rb +1 -1
- data/lib/natty-ui/line_animation/type_writer.rb +5 -25
- data/lib/natty-ui/line_animation.rb +2 -8
- data/lib/natty-ui/preload.rb +9 -0
- data/lib/natty-ui/text/east_asian_width.rb +1275 -0
- data/lib/natty-ui/text.rb +213 -0
- data/lib/natty-ui/version.rb +1 -1
- data/lib/natty-ui/wrapper/ask.rb +1 -1
- data/lib/natty-ui/wrapper/element.rb +1 -1
- data/lib/natty-ui/wrapper/horizontal_rule.rb +1 -1
- data/lib/natty-ui/wrapper/list_in_columns.rb +6 -8
- data/lib/natty-ui/wrapper/message.rb +1 -1
- data/lib/natty-ui/wrapper/query.rb +0 -1
- data/lib/natty-ui/wrapper/request.rb +1 -1
- data/lib/natty-ui/wrapper/section.rb +2 -2
- data/lib/natty-ui/wrapper/table.rb +10 -18
- data/lib/natty-ui/wrapper.rb +3 -22
- data/lib/natty-ui.rb +22 -82
- metadata +9 -6
- data/lib/natty-ui/ansi_constants.rb +0 -73
- data/lib/natty-ui/line_animation/test.rb +0 -29
- /data/lib/natty-ui/{features.rb → wrapper/features.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0cf1f1c1bbe16142b1a5dde311305de0f3caa3d67bff7ff2886000b0838dc85e
|
4
|
+
data.tar.gz: b3ae72c58b04e347098a43a96093429e79acb210a218f9250e9e1e258c6f9d50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34ffe4f15d6094e8edd2bc84606787531f1545391d4d7dbc0178d756c4edddc1afe2c9bcec41dbe033bd2af8337f7cfdfa6b0c40d3c229eff062b5a33f013c83
|
7
|
+
data.tar.gz: af06c7464620b0a8012fcd835a1304fce821b7194866b0be7f51af92b3f1c553a89ca9b4f00d98bbf6c7cc99ca1bba7dbef947718a24ddc874afd8d7e349e5f1
|
data/examples/3bit-colors.rb
CHANGED
@@ -6,9 +6,9 @@ ui.space
|
|
6
6
|
ui.h1 'NattyUI: 3/4-bit Color Support'
|
7
7
|
ui.space
|
8
8
|
|
9
|
-
color = ->(n) { "[[#{n}]]#{n.ljust(
|
9
|
+
color = ->(n, j) { "[[#{n}]]#{n.ljust(j)}[[/]] [[on_#{n}]] sample text [[/]]" }
|
10
10
|
%w[black red green yellow blue magenta cyan white].each do |name|
|
11
|
-
ui.puts "#{color[name]} #{color["bright_#{name}"]}"
|
11
|
+
ui.puts "#{color[name, 7]} #{color["bright_#{name}", 14]}"
|
12
12
|
end
|
13
13
|
|
14
14
|
ui.space
|
data/examples/demo.rb
CHANGED
data/examples/illustration.rb
CHANGED
@@ -8,9 +8,10 @@ ui.framed do
|
|
8
8
|
[[c7]]fancy[[/]], [[c8]]neat[[/]], [[c9]]pretty[[/]], [[ca]]cool[[/]],
|
9
9
|
[[cb]]lovely[[/]], [[cc]]natty[[/]] [[bold]]user interface[[/]] you like to
|
10
10
|
have for your command line applications. It contains
|
11
|
-
[[curly_underline
|
12
|
-
[[
|
13
|
-
|
11
|
+
[[italic curly_underline ulc4]]elegant[[/]],
|
12
|
+
[[italic underline ulc7]]simple[[/]] and
|
13
|
+
[[italic dotted_underline ulca]]beautiful[[/]] tools that enhance your
|
14
|
+
command line interfaces functionally and aesthetically.
|
14
15
|
TEXT
|
15
16
|
|
16
17
|
ui.msg('Features', glyph: '⭐️') { ui.ls(<<~FEATURES.lines(chomp: true)) }
|
data/examples/table.rb
CHANGED
@@ -7,6 +7,8 @@ ui.h1 'NattyUI: Tables'
|
|
7
7
|
ui.space
|
8
8
|
|
9
9
|
ui.message 'Constructed Table' do
|
10
|
+
ui.space
|
11
|
+
|
10
12
|
ui.table type: :heavy do |table|
|
11
13
|
table.add 'X', 'O'
|
12
14
|
table.add 'O', 'O', 'X'
|
@@ -17,20 +19,23 @@ end
|
|
17
19
|
ui.space
|
18
20
|
|
19
21
|
User = Struct.new(:id, :name, :mail, :notes)
|
20
|
-
USERS = [
|
21
|
-
User.new(
|
22
|
-
1,
|
23
|
-
'Henry',
|
24
|
-
'henry@some.test',
|
25
|
-
'This is fill text to generate a wide column which maybe rendered as multi line.'
|
26
|
-
),
|
27
|
-
User.new(2, 'Sam', 'sam-sam@some.test', "enforced\nmulti-line"),
|
28
|
-
User.new(3, 'Taylor', 'taylor@some.test'),
|
29
|
-
User.new(3, 'Max', 'maxxx@some.test')
|
30
|
-
].freeze
|
31
22
|
|
32
23
|
ui.message 'Data Table' do
|
33
|
-
ui.
|
24
|
+
ui.space
|
25
|
+
|
26
|
+
users = [
|
27
|
+
User.new(
|
28
|
+
1,
|
29
|
+
'Henry',
|
30
|
+
'henry@some.test',
|
31
|
+
'This is fill text to generate a wide column which maybe rendered as multi line.'
|
32
|
+
),
|
33
|
+
User.new(2, 'Sam', 'sam-sam@some.test', "enforced\nmulti-line"),
|
34
|
+
User.new(3, 'Taylor', 'taylor@some.test'),
|
35
|
+
User.new(4, 'Max', 'maxxx@some.test')
|
36
|
+
]
|
37
|
+
header = User.members.map { "[[bold green]]#{_1.capitalize}[[/]]" }
|
38
|
+
ui.table(header, *users)
|
34
39
|
end
|
35
40
|
|
36
41
|
ui.space
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NattyUI::Ansi
|
4
|
+
CURSOR_SHOW = "\e[?25h"
|
5
|
+
CURSOR_HIDE = "\e[?25l"
|
6
|
+
|
7
|
+
CURSOR_HOME = cursor_pos(nil, nil)
|
8
|
+
CURSOR_FIRST_ROW = cursor_pos(1).freeze
|
9
|
+
CURSOR_FIRST_COLUMN = cursor_column(1).freeze
|
10
|
+
|
11
|
+
CURSOR_SAFE_POS_SCO = "\e[s"
|
12
|
+
CURSOR_SAFE_POS_DEC = "\e7"
|
13
|
+
CURSOR_SAFE_POS = CURSOR_SAFE_POS_DEC
|
14
|
+
|
15
|
+
CURSOR_RESTORE_POS_SCO = "\e[u"
|
16
|
+
CURSOR_RESTORE_POS_DEC = "\e8"
|
17
|
+
CURSOR_RESTORE_POS = CURSOR_RESTORE_POS_DEC
|
18
|
+
|
19
|
+
SCREEN_ERASE = screen_erase(:entire)
|
20
|
+
|
21
|
+
SCREEN_SAVE = "\e[?47h"
|
22
|
+
SCREEN_RESTORE = "\e[?47l"
|
23
|
+
|
24
|
+
SCREEN_ALTERNATE = "\e[?1049h"
|
25
|
+
SCREEN_ALTERNATE_OFF = "\e[?1049l"
|
26
|
+
|
27
|
+
LINE_PREVIOUS = cursor_previous_line(1).freeze
|
28
|
+
LINE_NEXT = cursor_next_line(1).freeze
|
29
|
+
LINE_ERASE = line_erase(:entire)
|
30
|
+
|
31
|
+
RESET = self[:reset].freeze
|
32
|
+
|
33
|
+
BOLD = self[:bold].freeze
|
34
|
+
BOLD_OFF = self[:bold_off].freeze
|
35
|
+
|
36
|
+
FAINT = self[:faint].freeze
|
37
|
+
FAINT_OFF = self[:faint_off].freeze
|
38
|
+
|
39
|
+
ITALIC = self[:italic].freeze
|
40
|
+
ITALIC_OFF = self[:italic_off].freeze
|
41
|
+
|
42
|
+
STRIKE = self[:strike].freeze
|
43
|
+
STRIKE_OFF = self[:strike_off].freeze
|
44
|
+
|
45
|
+
UNDERLINE = self[:underline].freeze
|
46
|
+
DOUBLE_UNDERLINE = self[:double_underline].freeze
|
47
|
+
UNDERLINE_OFF = self[:underline_off].freeze
|
48
|
+
|
49
|
+
CURLY_UNDERLINE = self[:curly_underline].freeze
|
50
|
+
CURLY_UNDERLINE_OFF = self[:curly_underline_off].freeze
|
51
|
+
|
52
|
+
BLINK = self[:blink].freeze
|
53
|
+
BLINK_OFF = self[:blink_off].freeze
|
54
|
+
|
55
|
+
INVERT = self[:invert].freeze
|
56
|
+
INVERT_OFF = self[:invert_off].freeze
|
57
|
+
|
58
|
+
HIDE = self[:hide].freeze
|
59
|
+
REVEAL = self[:reveal].freeze
|
60
|
+
|
61
|
+
# @!visibility private
|
62
|
+
CLS = (CURSOR_HOME + SCREEN_ERASE).freeze
|
63
|
+
|
64
|
+
# @!visibility private
|
65
|
+
CLL = (CURSOR_FIRST_COLUMN + LINE_ERASE).freeze
|
66
|
+
|
67
|
+
# @!visibility private
|
68
|
+
SCREEN_BLANK =
|
69
|
+
(
|
70
|
+
CURSOR_SAFE_POS + SCREEN_ALTERNATE + CURSOR_HOME + SCREEN_ERASE + RESET
|
71
|
+
).freeze
|
72
|
+
|
73
|
+
# @!visibility private
|
74
|
+
SCREEN_UNBLANK = (RESET + SCREEN_ALTERNATE_OFF + CURSOR_RESTORE_POS).freeze
|
75
|
+
end
|
data/lib/natty-ui/ansi.rb
CHANGED
@@ -209,9 +209,9 @@ module NattyUI
|
|
209
209
|
when (0..255)
|
210
210
|
"38;5;#{arg}"
|
211
211
|
when (256..511)
|
212
|
-
"48;5;#{arg}"
|
212
|
+
"48;5;#{arg - 256}"
|
213
213
|
when (512..767)
|
214
|
-
"58;5;#{arg}"
|
214
|
+
"58;5;#{arg - 512}"
|
215
215
|
else
|
216
216
|
invalid_argument(arg)
|
217
217
|
end
|
@@ -260,7 +260,7 @@ module NattyUI
|
|
260
260
|
return if (attributes = attributes.to_s.split).empty?
|
261
261
|
"\e[#{
|
262
262
|
attributes
|
263
|
-
.map! {
|
263
|
+
.map! { ATTR[_1] || CLR[_1] || color(_1) || return }
|
264
264
|
.join(';')
|
265
265
|
}m"
|
266
266
|
end
|
@@ -331,7 +331,13 @@ module NattyUI
|
|
331
331
|
end
|
332
332
|
end
|
333
333
|
|
334
|
-
|
334
|
+
# @!visibility private
|
335
|
+
CSI = /\e\[[\d;:]*[ABCDEFGHJKSTfminsuhl]/
|
336
|
+
|
337
|
+
# @!visibility private
|
338
|
+
OSC = /\e\]\d+(?:;[^;\a\e]+)*(?:\a|\e\\)/
|
339
|
+
|
340
|
+
ESC = /(#{CSI})|(#{OSC})/
|
335
341
|
|
336
342
|
CLR_PREFIX = {
|
337
343
|
'fg' => '38',
|
@@ -340,8 +346,8 @@ module NattyUI
|
|
340
346
|
'on' => '48'
|
341
347
|
}.freeze
|
342
348
|
|
343
|
-
PI2_THIRD = 2 * Math::PI / 3
|
344
|
-
PI4_THIRD = 4 * Math::PI / 3
|
349
|
+
PI2_THIRD = 2 * Math::PI / 3
|
350
|
+
PI4_THIRD = 4 * Math::PI / 3
|
345
351
|
|
346
352
|
SATTR =
|
347
353
|
Module
|
@@ -349,6 +355,7 @@ module NattyUI
|
|
349
355
|
def self.to_hash
|
350
356
|
map = {
|
351
357
|
# alternative names
|
358
|
+
reset: '',
|
352
359
|
slow_blink: 5,
|
353
360
|
conceal: 8,
|
354
361
|
default_font: 10,
|
@@ -370,9 +377,8 @@ module NattyUI
|
|
370
377
|
}
|
371
378
|
add = ->(s, n) { n.each_with_index { |a, idx| map[a] = s + idx } }
|
372
379
|
add[
|
373
|
-
|
380
|
+
1,
|
374
381
|
%i[
|
375
|
-
reset
|
376
382
|
bold
|
377
383
|
faint
|
378
384
|
italic
|
@@ -492,4 +498,4 @@ module NattyUI
|
|
492
498
|
end
|
493
499
|
end
|
494
500
|
|
495
|
-
require_relative '
|
501
|
+
require_relative 'ansi/constants'
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'ansi'
|
4
3
|
require_relative 'wrapper'
|
5
|
-
require_relative 'line_animation'
|
6
4
|
|
7
5
|
module NattyUI
|
8
6
|
class AnsiWrapper < Wrapper
|
@@ -13,8 +11,8 @@ module NattyUI
|
|
13
11
|
|
14
12
|
prefix = kwargs[:prefix]
|
15
13
|
if prefix && !prefix.empty?
|
16
|
-
prefix =
|
17
|
-
prefix_width = kwargs[:prefix_width] ||
|
14
|
+
prefix = Text.embellish(prefix)
|
15
|
+
prefix_width = kwargs[:prefix_width] || Text.width(prefix)
|
18
16
|
else
|
19
17
|
prefix = nil
|
20
18
|
prefix_width = 0
|
@@ -23,12 +21,12 @@ module NattyUI
|
|
23
21
|
kwargs[:prefix_width] = prefix_width
|
24
22
|
|
25
23
|
suffix = kwargs[:suffix]
|
26
|
-
suffix = suffix.empty? ? nil :
|
24
|
+
suffix = suffix.empty? ? nil : Texct.embellish(suffix) if suffix
|
27
25
|
|
28
26
|
mw = kwargs[:max_width]
|
29
27
|
unless mw
|
30
28
|
mw = screen_columns - prefix_width
|
31
|
-
mw -= kwargs[:suffix_width] ||
|
29
|
+
mw -= kwargs[:suffix_width] || Text.(suffix) if suffix
|
32
30
|
end
|
33
31
|
kwargs[:max_width] = mw
|
34
32
|
|
@@ -36,17 +34,16 @@ module NattyUI
|
|
36
34
|
animation = LineAnimation[animation].new(@stream, kwargs)
|
37
35
|
prefix = "#{Ansi::RESET}#{Ansi::CLL}#{prefix}"
|
38
36
|
|
39
|
-
|
40
|
-
.
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
.
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
37
|
+
Text.each_line(
|
38
|
+
args.map! { Text.embellish(Ansi.blemish(_1)) },
|
39
|
+
mw
|
40
|
+
) do |line|
|
41
|
+
@stream << prefix
|
42
|
+
animation.print(line)
|
43
|
+
(@stream << "#{prefix}#{line}#{suffix}\n").flush
|
44
|
+
@lines_written += 1
|
45
|
+
end
|
46
|
+
|
50
47
|
(@stream << Ansi::CURSOR_SHOW).flush
|
51
48
|
self
|
52
49
|
end
|
@@ -72,16 +69,18 @@ module NattyUI
|
|
72
69
|
protected
|
73
70
|
|
74
71
|
def prepare_print(args, kwargs)
|
75
|
-
|
72
|
+
Text.prepare_print(args, kwargs, -> { screen_columns }) do |str|
|
73
|
+
Text.embellish(str)
|
74
|
+
end
|
76
75
|
end
|
77
76
|
|
78
77
|
def temp_func
|
79
78
|
count = @lines_written
|
80
79
|
lambda do
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
@lines_written -=
|
80
|
+
if (c = @lines_written - count).nonzero?
|
81
|
+
@stream << Ansi.cursor_prev_line(c) << Ansi.screen_erase(:below) <<
|
82
|
+
Ansi::CURSOR_FIRST_COLUMN
|
83
|
+
@lines_written -= c
|
85
84
|
end
|
86
85
|
@stream.flush
|
87
86
|
self
|
@@ -107,9 +106,7 @@ module NattyUI
|
|
107
106
|
(wrapper.stream << @msg << (@max_value ? fullbar : @spinner.next)).flush
|
108
107
|
end
|
109
108
|
|
110
|
-
def end_draw
|
111
|
-
(wrapper.stream << Ansi::CLL << Ansi::CURSOR_SHOW).flush
|
112
|
-
end
|
109
|
+
def end_draw = (wrapper.stream << Ansi::CLL << Ansi::CURSOR_SHOW).flush
|
113
110
|
|
114
111
|
def fullbar
|
115
112
|
percent = @value / @max_value
|
@@ -124,7 +121,6 @@ module NattyUI
|
|
124
121
|
BAR_BACK = Ansi[236, 492].freeze
|
125
122
|
BAR_INK = Ansi[:bold, 255, :on_default].freeze
|
126
123
|
end
|
127
|
-
private_constant :Progress
|
128
124
|
|
129
125
|
module Temporary
|
130
126
|
def temporary
|
@@ -145,12 +141,10 @@ module NattyUI
|
|
145
141
|
end
|
146
142
|
end
|
147
143
|
end
|
148
|
-
private_constant :Temporary
|
149
144
|
|
150
145
|
class Section < Section
|
151
146
|
include Temporary
|
152
147
|
end
|
153
|
-
private_constant :Section
|
154
148
|
|
155
149
|
class Quote < Quote
|
156
150
|
include Temporary
|
@@ -160,7 +154,6 @@ module NattyUI
|
|
160
154
|
@prefix = "#{Ansi[39]}#{@prefix}#{Ansi::RESET}"
|
161
155
|
end
|
162
156
|
end
|
163
|
-
private_constant :Quote
|
164
157
|
|
165
158
|
class Framed < Framed
|
166
159
|
def color(str) = "#{Ansi[39]}#{str}#{Ansi::RESET}"
|
@@ -173,7 +166,6 @@ module NattyUI
|
|
173
166
|
@finish = color("#{deco[5]}#{deco[6] * aw}#{deco[7]}")
|
174
167
|
end
|
175
168
|
end
|
176
|
-
private_constant :Framed
|
177
169
|
|
178
170
|
class Message < Section
|
179
171
|
protected
|
@@ -182,7 +174,7 @@ module NattyUI
|
|
182
174
|
wrapper = parent.wrapper
|
183
175
|
color = COLORS[glyph] || COLORS[:default]
|
184
176
|
glyph = wrapper.glyph(glyph) || glyph
|
185
|
-
prefix_width =
|
177
|
+
prefix_width = Text.width(glyph) + 1
|
186
178
|
parent.puts(
|
187
179
|
title,
|
188
180
|
prefix: "#{glyph} #{color}",
|
@@ -204,13 +196,11 @@ module NattyUI
|
|
204
196
|
query: Ansi[255]
|
205
197
|
}.compare_by_identity.freeze
|
206
198
|
end
|
207
|
-
private_constant :Message
|
208
199
|
|
209
200
|
class Task < Message
|
210
201
|
include ProgressAttributes
|
211
202
|
include TaskMethods
|
212
203
|
end
|
213
|
-
private_constant :Task
|
214
204
|
end
|
215
205
|
|
216
206
|
private_constant :AnsiWrapper
|