natty-ui 0.7.0 → 0.8.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 +4 -1
- data/README.md +25 -47
- data/examples/24bit-colors.rb +23 -0
- data/examples/3bit-colors.rb +13 -0
- data/examples/8bit-colors.rb +31 -0
- data/examples/attributes.rb +41 -130
- data/examples/demo.rb +217 -0
- data/examples/illustration.png +0 -0
- data/examples/illustration.rb +26 -0
- data/examples/list_in_columns.rb +10 -17
- data/examples/progress.rb +24 -29
- data/examples/query.rb +21 -27
- data/examples/table.rb +18 -0
- data/lib/natty-ui/ansi.rb +81 -61
- data/lib/natty-ui/ansi_wrapper.rb +92 -163
- data/lib/natty-ui/features.rb +11 -18
- data/lib/natty-ui/version.rb +2 -2
- data/lib/natty-ui/wrapper/ask.rb +26 -20
- data/lib/natty-ui/wrapper/element.rb +19 -23
- data/lib/natty-ui/wrapper/framed.rb +23 -18
- data/lib/natty-ui/wrapper/heading.rb +26 -53
- data/lib/natty-ui/wrapper/horizontal_rule.rb +37 -0
- data/lib/natty-ui/wrapper/list_in_columns.rb +66 -10
- data/lib/natty-ui/wrapper/message.rb +20 -27
- data/lib/natty-ui/wrapper/progress.rb +10 -8
- data/lib/natty-ui/wrapper/query.rb +37 -30
- data/lib/natty-ui/wrapper/quote.rb +25 -0
- data/lib/natty-ui/wrapper/request.rb +21 -10
- data/lib/natty-ui/wrapper/section.rb +43 -41
- data/lib/natty-ui/wrapper/table.rb +298 -0
- data/lib/natty-ui/wrapper/task.rb +6 -7
- data/lib/natty-ui/wrapper.rb +118 -41
- data/lib/natty-ui.rb +43 -39
- metadata +15 -8
- data/examples/basic.rb +0 -62
data/examples/list_in_columns.rb
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'natty-ui'
|
4
4
|
|
5
|
-
UI = NattyUI::StdOut
|
6
|
-
|
7
5
|
LOREM = <<~LOREM
|
8
6
|
Lorem ipsum dolor sit
|
9
7
|
amet, consectetur adipisicing
|
@@ -14,7 +12,7 @@ LOREM = <<~LOREM
|
|
14
12
|
nostrud exercitation ullamco
|
15
13
|
laboris nisi ut aliquip ex
|
16
14
|
ea commodo [[bold]]consequat[[/]]. Duis
|
17
|
-
aute irure dolor in
|
15
|
+
aute irure [[bold green]]dolor[[/]] in
|
18
16
|
reprehenderit in voluptate
|
19
17
|
velit [[underline]]esse cillum[[/]] dolore eu
|
20
18
|
fugiat nulla pariatur.
|
@@ -24,20 +22,15 @@ LOREM = <<~LOREM
|
|
24
22
|
deserunt mollit anim id
|
25
23
|
est laborum.
|
26
24
|
LOREM
|
27
|
-
WORDS = LOREM.split(/\W+/).uniq.sort!.freeze
|
28
|
-
|
29
|
-
UI.space
|
30
|
-
UI.h2 'Print a list in columns'
|
31
|
-
UI.space
|
32
25
|
|
33
|
-
|
34
|
-
|
35
|
-
|
26
|
+
ui.space
|
27
|
+
ui.h1 'Print a list in columns'
|
28
|
+
ui.space
|
36
29
|
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
ui.h2 'Lorem ipsum lines (compact)'
|
31
|
+
ui.ls LOREM.lines(chomp: true), glyph: 1
|
32
|
+
ui.space
|
40
33
|
|
41
|
-
|
42
|
-
|
43
|
-
|
34
|
+
ui.h2 'Lorem ipsum lines (row-wise)'
|
35
|
+
ui.ls LOREM.lines(chomp: true), glyph: 1, compact: false
|
36
|
+
ui.space
|
data/examples/progress.rb
CHANGED
@@ -2,67 +2,62 @@
|
|
2
2
|
|
3
3
|
require 'natty-ui'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
UI.h1 'NattyUI Progress Indication Demo'
|
9
|
-
UI.space
|
5
|
+
ui.space
|
6
|
+
ui.h1 'NattyUI Progress Indication Demo'
|
7
|
+
ui.space
|
10
8
|
|
11
9
|
# just simulate some work
|
12
10
|
def something = sleep(0.5)
|
13
11
|
def some = sleep(0.15)
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
ui.info 'Tasks are sections to visualize step by step processing.' do
|
14
|
+
ui.task 'Assemble assets' do
|
15
|
+
ui.task('Initialize') { something }
|
18
16
|
|
19
|
-
progress =
|
17
|
+
progress = ui.progress 'Connect to server...'
|
20
18
|
20.times do
|
21
19
|
progress.step
|
22
20
|
some
|
23
21
|
end
|
24
22
|
progress.ok 'Connected'
|
25
23
|
|
26
|
-
|
24
|
+
ui.task('Collect files...') { something }
|
27
25
|
|
28
|
-
|
26
|
+
ui.task 'Compile files...' do
|
29
27
|
%w[readme.txt main.css main.html sub.html].each do |name|
|
30
|
-
|
28
|
+
ui.msg "Compile file [[bright_yellow]]./source/#{name}[[/]]..."
|
31
29
|
something
|
32
30
|
end
|
33
|
-
|
31
|
+
ui.done 'Files compiled.'
|
34
32
|
end
|
35
33
|
|
36
|
-
progress =
|
34
|
+
progress = ui.progress('Compress files', max_value: 11)
|
37
35
|
11.times do
|
38
36
|
progress.step
|
39
37
|
something
|
40
38
|
end
|
41
39
|
progress.done 'All compressed'
|
42
40
|
|
43
|
-
|
41
|
+
ui.task('Signing') { something }
|
44
42
|
|
45
|
-
|
43
|
+
ui.task('Store assembled results') { something }
|
46
44
|
end
|
47
|
-
|
45
|
+
|
46
|
+
ui.puts(
|
48
47
|
'The details are removed ([[italic]]in ANSI version[[/]]) when the task',
|
49
48
|
'ended sucessfully.'
|
50
49
|
)
|
51
50
|
end
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
progress.step
|
60
|
-
some
|
52
|
+
ui.info 'Details of failed tasks will not be cleaned.' do
|
53
|
+
ui.task 'Assemble assets' do
|
54
|
+
ui.task('Initialize') { something }
|
55
|
+
ui.task('Connect to Server') do
|
56
|
+
something
|
57
|
+
ui.failed 'Unable to connect to server'
|
61
58
|
end
|
62
|
-
|
63
|
-
|
64
|
-
task.error 'This code will not be reachd!'
|
59
|
+
ui.error 'This code will not be reachd!'
|
65
60
|
end
|
66
61
|
end
|
67
62
|
|
68
|
-
|
63
|
+
ui.space
|
data/examples/query.rb
CHANGED
@@ -2,42 +2,36 @@
|
|
2
2
|
|
3
3
|
require 'natty-ui'
|
4
4
|
|
5
|
-
|
5
|
+
ui.space
|
6
|
+
ui.h1 'NattyUI Query Demo'
|
7
|
+
ui.space
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
# little helper
|
10
|
+
def abort!
|
11
|
+
ui.failed 'aborted'
|
12
|
+
exit
|
13
|
+
end
|
10
14
|
|
11
|
-
unless
|
12
|
-
|
15
|
+
unless ui.ask('Do you like to continute? (Y|n): ')
|
16
|
+
ui.info 'ok, try later!'
|
13
17
|
exit
|
14
18
|
end
|
15
19
|
|
16
20
|
choice =
|
17
|
-
|
21
|
+
ui.query(
|
18
22
|
'Which fruits do you prefer?',
|
19
23
|
'Apples',
|
20
|
-
'Bananas',
|
24
|
+
'[[yellow]]Bananas[[/]]',
|
21
25
|
'Cherries',
|
22
|
-
x: 'No fruits'
|
23
|
-
result: :choice
|
26
|
+
x: 'No fruits'
|
24
27
|
)
|
25
|
-
unless choice
|
26
|
-
|
27
|
-
exit false
|
28
|
-
end
|
29
|
-
UI.info "Your choice: #{choice}"
|
28
|
+
abort! unless choice
|
29
|
+
ui.info "Your choice: #{choice}"
|
30
30
|
|
31
|
-
answer =
|
32
|
-
unless answer
|
33
|
-
|
34
|
-
exit false
|
35
|
-
end
|
36
|
-
UI.info "Your answer: #{answer.inspect}"
|
31
|
+
answer = ui.request 'What is your favorite verb?: '
|
32
|
+
abort! unless answer
|
33
|
+
ui.info "Your answer: #{answer.inspect}"
|
37
34
|
|
38
|
-
answer =
|
39
|
-
unless answer
|
40
|
-
|
41
|
-
exit false
|
42
|
-
end
|
43
|
-
UI.info "I'll keep your secret!"
|
35
|
+
answer = ui.request('What is your current password?:', password: true)
|
36
|
+
abort! unless answer
|
37
|
+
ui.info "I'll keep your secret!"
|
data/examples/table.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'natty-ui'
|
4
|
+
|
5
|
+
User = Struct.new(:id, :name, :address)
|
6
|
+
|
7
|
+
USERS = [
|
8
|
+
User.new(1, 'Henry', 'henry@some.test'),
|
9
|
+
User.new(2, 'Sam', 'sam-sam@some.test'),
|
10
|
+
User.new(3, 'Taylor', 'taylor@some.test'),
|
11
|
+
User.new(3, 'Max', 'maxxx@some.test')
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
ui.space
|
15
|
+
ui.h1 'The User List'
|
16
|
+
ui.space
|
17
|
+
|
18
|
+
ui.table(User.members, *USERS)
|
data/lib/natty-ui/ansi.rb
CHANGED
@@ -5,44 +5,85 @@ module NattyUI
|
|
5
5
|
# Helper module for ANSI escape codes.
|
6
6
|
#
|
7
7
|
module Ansi
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# ANSI code to move the cursor down.
|
9
|
+
CURSOR_DOWN = "\e[B"
|
10
|
+
|
11
|
+
# ANSI code to move the cursor up.
|
12
|
+
CURSOR_UP = "\e[A"
|
13
|
+
|
14
|
+
# ANSI code to move the cursor left.
|
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"
|
11
46
|
|
12
|
-
|
13
|
-
|
47
|
+
# ANSI code to erase to end of current line.
|
48
|
+
LINE_ERASE_TO_END = "\e[0K"
|
14
49
|
|
15
|
-
|
16
|
-
|
50
|
+
# ANSI code to erase to begin of current line.
|
51
|
+
LINE_ERASE_TO_BEGIN = "\e[1K"
|
17
52
|
|
18
|
-
|
19
|
-
|
53
|
+
# ANSI code to save current screen state.
|
54
|
+
SCREEN_SAVE = "\e[?47h"
|
20
55
|
|
21
|
-
|
22
|
-
|
56
|
+
# ANSI code to restore screen state.
|
57
|
+
SCREEN_RESTORE = "\e[?47l"
|
23
58
|
|
24
|
-
|
25
|
-
|
59
|
+
# ANSI code to erase screen.
|
60
|
+
SCREEN_ERASE = "\e[2J"
|
26
61
|
|
27
|
-
|
28
|
-
|
62
|
+
# ANSI code to erase screen below current cursor position.
|
63
|
+
SCREEN_ERASE_BELOW = "\e[0J"
|
29
64
|
|
30
|
-
|
31
|
-
|
65
|
+
# ANSI code to erase screen above current cursor position.
|
66
|
+
SCREEN_ERASE_ABOVE = "\e[1J"
|
32
67
|
|
33
|
-
|
34
|
-
|
68
|
+
# ANSI code to alternate screen
|
69
|
+
SCREEN_ALTERNATIVE = "\e[?1049h"
|
35
70
|
|
36
|
-
|
37
|
-
|
71
|
+
# ANSI code to set alternate screen off.
|
72
|
+
SCREEN_ALTERNATIVE_OFF = "\e[?1049l"
|
38
73
|
|
39
|
-
|
40
|
-
|
74
|
+
# ANSI code to reset all attributes.
|
75
|
+
RESET = "\e[0m"
|
41
76
|
|
42
|
-
|
43
|
-
|
44
|
-
def line_clear = "\e[1K\e[0G"
|
77
|
+
# @!visibility private
|
78
|
+
CURSOR_RIGHT_ALIGNED = "\e[9999G\e[D\e[C"
|
45
79
|
|
80
|
+
# @!visibility private
|
81
|
+
BLANK_SLATE = "\e[0m\e[s\e[?47h\e[H\e[2J"
|
82
|
+
|
83
|
+
# @!visibility private
|
84
|
+
UNBLANK_SLATE = "\e[?47l\e[u\e[0m"
|
85
|
+
|
86
|
+
class << self
|
46
87
|
# @param lines [Integer] number of lines
|
47
88
|
# @return [String] ANSI code to move the cursor up
|
48
89
|
def cursor_up(lines = nil) = "\e[#{lines}A"
|
@@ -60,37 +101,18 @@ module NattyUI
|
|
60
101
|
def cursor_left(columns = nil) = "\e[#{columns}D"
|
61
102
|
|
62
103
|
# @param lines [Integer] number of lines
|
63
|
-
# @return [String] ANSI code to move the cursor to beginning of
|
64
|
-
#
|
104
|
+
# @return [String] ANSI code to move the cursor to beginning of some lines
|
105
|
+
# below
|
65
106
|
def cursor_line_down(lines = nil) = "\e[#{lines}E"
|
66
107
|
|
67
108
|
# @param lines [Integer] number of lines
|
68
|
-
# @return [String] ANSI code to move the cursor to beginning of
|
69
|
-
#
|
109
|
+
# @return [String] ANSI code to move the cursor to beginning of some lines
|
110
|
+
# up
|
70
111
|
def cursor_line_up(lines = nil) = "\e[#{lines}F"
|
71
112
|
|
72
|
-
# @param
|
113
|
+
# @param column [Integer] column number
|
73
114
|
# @return [String] ANSI code to move the cursor to given column
|
74
|
-
def cursor_column(
|
75
|
-
|
76
|
-
# @return [String] ANSI code positioning the cursor on right hand side of
|
77
|
-
# the terminal
|
78
|
-
def cursor_right_aligned = "\e[9999G\e[D\e[C"
|
79
|
-
|
80
|
-
# @return [String] ANSI code to hide the cursor
|
81
|
-
def cursor_hide = "\e[?25l"
|
82
|
-
|
83
|
-
# @return [String] ANSI code to show the cursor (again)
|
84
|
-
def cursor_show = "\e[?25h"
|
85
|
-
|
86
|
-
# @return [String] ANSI code to save current cursor position
|
87
|
-
def cursor_save_pos = "\e[s"
|
88
|
-
|
89
|
-
# @return [String] ANSI code to restore saved cursor position
|
90
|
-
def cursor_restore_pos = "\e[u"
|
91
|
-
|
92
|
-
# @return [String] ANSI code to set cursor position on upper left corner
|
93
|
-
def cursor_home = "\e[H"
|
115
|
+
def cursor_column(column = nil) = "\e[#{column}G"
|
94
116
|
|
95
117
|
# @param row [Integer] row to set cursor
|
96
118
|
# @param column [Integer] column to set cursor
|
@@ -100,17 +122,17 @@ module NattyUI
|
|
100
122
|
column ? "\e[;#{column}H" : "\e[H"
|
101
123
|
end
|
102
124
|
|
103
|
-
# Decorate given `
|
125
|
+
# Decorate given `str` with ANSI `attributes`.
|
104
126
|
#
|
105
127
|
# @see []
|
106
128
|
#
|
107
|
-
# @param
|
129
|
+
# @param str [#to_s] object to be decorated
|
108
130
|
# @param attributes [Symbol, String] attribute names to be used
|
109
131
|
# @param reset [Boolean] whether to include reset code for ANSI attributes
|
110
|
-
# @return [String] `
|
111
|
-
def embellish(
|
132
|
+
# @return [String] `str` converted and decorated with the ANSI `attributes`
|
133
|
+
def embellish(str, *attributes, reset: true)
|
112
134
|
attributes = self[*attributes]
|
113
|
-
attributes.empty? ?
|
135
|
+
attributes.empty? ? str.to_s : "#{attributes}#{str}#{"\e[0m" if reset}"
|
114
136
|
end
|
115
137
|
|
116
138
|
# Remove ANSI attribtes from given string.
|
@@ -229,9 +251,7 @@ module NattyUI
|
|
229
251
|
def try_convert(attributes)
|
230
252
|
return if (attributes = attributes.to_s.split).empty?
|
231
253
|
"\e[#{
|
232
|
-
attributes
|
233
|
-
.map { |arg| ATTRIBUTES[arg] || color(arg) || return }
|
234
|
-
.join(';')
|
254
|
+
attributes.map { ATTRIBUTES[_1] || color(_1) || return }.join(';')
|
235
255
|
}m"
|
236
256
|
end
|
237
257
|
|
@@ -262,7 +282,7 @@ module NattyUI
|
|
262
282
|
end
|
263
283
|
val.delete_prefix!('#')
|
264
284
|
case val.size
|
265
|
-
when 2
|
285
|
+
when 1, 2
|
266
286
|
"#{base}5;#{val.hex}" if /\A[[:xdigit:]]+\z/.match?(val)
|
267
287
|
when 3
|
268
288
|
if /\A[[:xdigit:]]+\z/.match?(val)
|
@@ -433,7 +453,7 @@ module NattyUI
|
|
433
453
|
ul_bright_magenta: '58;2;255;0;255',
|
434
454
|
ul_bright_cyan: '58;2;0;255;255',
|
435
455
|
ul_bright_white: '58;2;255;255;255'
|
436
|
-
}.tap {
|
456
|
+
}.tap { _1.merge!(_1.transform_keys(&:to_s)).freeze }
|
437
457
|
private_constant :ATTRIBUTES
|
438
458
|
end
|
439
459
|
end
|