natty-ui 0.6.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 +12 -0
- data/README.md +25 -48
- 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 -134
- 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 +22 -21
- data/examples/table.rb +18 -0
- data/lib/natty-ui/ansi.rb +111 -92
- data/lib/natty-ui/ansi_wrapper.rb +93 -161
- data/lib/natty-ui/features.rb +12 -19
- 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/{mixins.rb → wrapper/mixins.rb} +2 -2
- data/lib/natty-ui/wrapper/progress.rb +11 -9
- 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 +27 -5
- data/lib/natty-ui/wrapper/section.rb +42 -40
- data/lib/natty-ui/wrapper/table.rb +298 -0
- data/lib/natty-ui/wrapper/task.rb +9 -12
- data/lib/natty-ui/wrapper.rb +117 -44
- data/lib/natty-ui.rb +48 -50
- data/lib/natty_ui.rb +3 -0
- metadata +18 -9
- data/examples/basic.rb +0 -62
data/lib/natty-ui.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'readline'
|
4
3
|
unless defined?(Reline)
|
5
4
|
# load the Reline::Unicode part only
|
6
5
|
# @!visibility private
|
@@ -15,7 +14,7 @@ require_relative 'natty-ui/ansi_wrapper'
|
|
15
14
|
|
16
15
|
#
|
17
16
|
# Module to create beautiful, nice, nifty, fancy, neat, pretty, cool, lovely,
|
18
|
-
# natty user interfaces for your CLI.
|
17
|
+
# natty user interfaces for your CLI application.
|
19
18
|
#
|
20
19
|
# It creates {Wrapper} instances which can optionally support ANSI. The UI
|
21
20
|
# consists of {Wrapper::Element}s and {Wrapper::Section}s for different
|
@@ -25,9 +24,12 @@ module NattyUI
|
|
25
24
|
class << self
|
26
25
|
# @see .valid_in?
|
27
26
|
# @return [IO] IO stream used to read input
|
28
|
-
# @raise TypeError when a non-readable stream will be assigned
|
27
|
+
# @raise [TypeError] when a non-readable stream will be assigned
|
29
28
|
attr_reader :in_stream
|
30
29
|
|
30
|
+
# @return [Wrapper, Wrapper::Element] active UI element
|
31
|
+
attr_reader :element
|
32
|
+
|
31
33
|
# @param [IO] stream to read input
|
32
34
|
def in_stream=(stream)
|
33
35
|
unless valid_in?(stream)
|
@@ -44,7 +46,7 @@ module NattyUI
|
|
44
46
|
# @param [Boolean, :auto] ansi whether ANSI should be supported
|
45
47
|
# or automatically selected
|
46
48
|
# @return [Wrapper] wrapper for the given `stream`
|
47
|
-
# @raise TypeError when `stream` is not a writable stream
|
49
|
+
# @raise [TypeError] when `stream` is not a writable stream
|
48
50
|
def new(stream, ansi: :auto)
|
49
51
|
unless valid_out?(stream)
|
50
52
|
raise(TypeError, "writable IO required - #{stream.inspect}")
|
@@ -77,10 +79,9 @@ module NattyUI
|
|
77
79
|
# Translate embedded attribute descriptions into ANSI control codes.
|
78
80
|
#
|
79
81
|
# @param [#to_s] str string to edit
|
80
|
-
# @return
|
82
|
+
# @return [String] edited string
|
81
83
|
def embellish(str)
|
82
|
-
str = str.to_s
|
83
|
-
return +'' if str.empty?
|
84
|
+
return +'' if (str = str.to_s).empty?
|
84
85
|
reset = false
|
85
86
|
ret =
|
86
87
|
str.gsub(/(\[\[((?~\]\]))\]\])/) do
|
@@ -91,26 +92,28 @@ module NattyUI
|
|
91
92
|
end
|
92
93
|
match.empty? or next "[[#{match}]]"
|
93
94
|
reset = false
|
94
|
-
Ansi
|
95
|
+
Ansi::RESET
|
95
96
|
end
|
96
|
-
reset ? "#{ret}#{Ansi
|
97
|
+
reset ? "#{ret}#{Ansi::RESET}" : ret
|
97
98
|
end
|
98
99
|
|
99
100
|
# Remove embedded attribute descriptions from given string.
|
100
101
|
#
|
101
102
|
# @param [#to_s] str string to edit
|
102
|
-
# @
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
103
|
+
# @param [:keep,:remove] ansi keep or remove ANSI codes too
|
104
|
+
# @return [String] edited string
|
105
|
+
def plain(str, ansi: :keep)
|
106
|
+
str =
|
107
|
+
str
|
108
|
+
.to_s
|
109
|
+
.gsub(/(\[\[((?~\]\]))\]\])/) do
|
110
|
+
match = Regexp.last_match[2]
|
111
|
+
if match.delete_prefix!('/')
|
112
|
+
next match.empty? ? nil : "[[#{match}]]"
|
113
|
+
end
|
114
|
+
Ansi.try_convert(match) ? nil : "[[#{match}]]"
|
111
115
|
end
|
112
|
-
|
113
|
-
end
|
116
|
+
ansi == :keep ? str : Ansi.blemish(str)
|
114
117
|
end
|
115
118
|
|
116
119
|
# Calculate monospace (display) width of given String.
|
@@ -119,8 +122,8 @@ module NattyUI
|
|
119
122
|
# @param [#to_s] str string to calculate
|
120
123
|
# @return [Integer] the display size
|
121
124
|
def display_width(str)
|
122
|
-
str = str.to_s
|
123
|
-
|
125
|
+
return 0 if (str = str.to_s).empty?
|
126
|
+
Reline::Unicode.calculate_width(plain(str), true)
|
124
127
|
end
|
125
128
|
|
126
129
|
# Convert given arguments into strings and yield each line.
|
@@ -137,12 +140,11 @@ module NattyUI
|
|
137
140
|
# @return [Enumerator] line enumerator
|
138
141
|
def each_line(*strs, max_width: nil, &block)
|
139
142
|
return to_enum(__method__, *strs, max_width: max_width) unless block
|
140
|
-
|
141
|
-
strs.each {
|
143
|
+
if max_width.nil?
|
144
|
+
strs.each { _1.to_s.each_line(chomp: true, &block) }
|
142
145
|
return nil
|
143
146
|
end
|
144
|
-
max_width = max_width.to_i
|
145
|
-
return if max_width <= 0
|
147
|
+
return if (max_width = max_width.to_i) <= 0
|
146
148
|
strs.each do |str|
|
147
149
|
str
|
148
150
|
.to_s
|
@@ -155,37 +157,28 @@ module NattyUI
|
|
155
157
|
nil
|
156
158
|
end
|
157
159
|
|
158
|
-
# Read
|
160
|
+
# Read next raw key (keyboard input) from {in_stream}.
|
159
161
|
#
|
160
|
-
#
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
def readline(prompt = nil, completion: false, stream: StdOut.stream)
|
172
|
-
cp = Readline.completion_proc
|
173
|
-
Readline.completion_proc = completion == false ? ->(*_) {} : completion
|
174
|
-
Readline.output = stream
|
175
|
-
Readline.input = @in_stream
|
176
|
-
Readline.readline(prompt.to_s)
|
177
|
-
rescue Interrupt
|
178
|
-
stream.puts
|
179
|
-
nil
|
180
|
-
ensure
|
181
|
-
Readline.completion_proc = cp
|
162
|
+
# @return [String] read key
|
163
|
+
def read_key
|
164
|
+
return @in_stream.getch unless defined?(@in_stream.getc)
|
165
|
+
return @in_stream.getc unless defined?(@in_stream.raw)
|
166
|
+
@in_stream.raw do |raw|
|
167
|
+
key = raw.getc
|
168
|
+
while (nc = raw.read_nonblock(1, exception: false))
|
169
|
+
nc.is_a?(String) ? key += nc : break
|
170
|
+
end
|
171
|
+
key
|
172
|
+
end
|
182
173
|
end
|
183
174
|
|
184
175
|
private
|
185
176
|
|
186
177
|
def wrapper_class(stream, ansi)
|
187
178
|
return AnsiWrapper if ansi == true
|
188
|
-
|
179
|
+
if ansi == false || ENV.key?('NO_COLOR') || ENV['TERM'] == 'dumb'
|
180
|
+
return Wrapper
|
181
|
+
end
|
189
182
|
stream.tty? ? AnsiWrapper : Wrapper
|
190
183
|
end
|
191
184
|
|
@@ -202,5 +195,10 @@ module NattyUI
|
|
202
195
|
# Instance for standard error output.
|
203
196
|
StdErr = stderr_is_stdout? ? StdOut : new(STDERR)
|
204
197
|
|
198
|
+
@element = StdOut
|
205
199
|
self.in_stream = STDIN
|
206
200
|
end
|
201
|
+
|
202
|
+
# @see NattyUI.element
|
203
|
+
# @return [NattyUI::Wrapper, NattyUI::Wrapper::Element] active UI element
|
204
|
+
def ui = NattyUI.element unless defined?(ui)
|
data/lib/natty_ui.rb
ADDED
metadata
CHANGED
@@ -1,21 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: natty-ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Blumtritt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
This is the beautiful, nice, nifty, fancy, neat, pretty, cool, lovely,
|
15
|
-
natty user interface you like to have for your command line
|
16
|
-
|
17
|
-
|
18
|
-
command line application functionally and aesthetically.
|
15
|
+
natty user interface tool you like to have for your command line applications.
|
16
|
+
It contains elegant, simple and beautiful features that enhance your
|
17
|
+
command line interfaces functionally and aesthetically.
|
19
18
|
email:
|
20
19
|
executables: []
|
21
20
|
extensions: []
|
@@ -23,32 +22,42 @@ extra_rdoc_files:
|
|
23
22
|
- README.md
|
24
23
|
- LICENSE
|
25
24
|
files:
|
25
|
+
- ".yardopts"
|
26
26
|
- LICENSE
|
27
27
|
- README.md
|
28
|
+
- examples/24bit-colors.rb
|
29
|
+
- examples/3bit-colors.rb
|
30
|
+
- examples/8bit-colors.rb
|
28
31
|
- examples/attributes.rb
|
29
|
-
- examples/
|
32
|
+
- examples/demo.rb
|
30
33
|
- examples/illustration.png
|
34
|
+
- examples/illustration.rb
|
31
35
|
- examples/list_in_columns.rb
|
32
36
|
- examples/progress.rb
|
33
37
|
- examples/query.rb
|
38
|
+
- examples/table.rb
|
34
39
|
- lib/natty-ui.rb
|
35
40
|
- lib/natty-ui/ansi.rb
|
36
41
|
- lib/natty-ui/ansi_wrapper.rb
|
37
42
|
- lib/natty-ui/features.rb
|
38
|
-
- lib/natty-ui/mixins.rb
|
39
43
|
- lib/natty-ui/version.rb
|
40
44
|
- lib/natty-ui/wrapper.rb
|
41
45
|
- lib/natty-ui/wrapper/ask.rb
|
42
46
|
- lib/natty-ui/wrapper/element.rb
|
43
47
|
- lib/natty-ui/wrapper/framed.rb
|
44
48
|
- lib/natty-ui/wrapper/heading.rb
|
49
|
+
- lib/natty-ui/wrapper/horizontal_rule.rb
|
45
50
|
- lib/natty-ui/wrapper/list_in_columns.rb
|
46
51
|
- lib/natty-ui/wrapper/message.rb
|
52
|
+
- lib/natty-ui/wrapper/mixins.rb
|
47
53
|
- lib/natty-ui/wrapper/progress.rb
|
48
54
|
- lib/natty-ui/wrapper/query.rb
|
55
|
+
- lib/natty-ui/wrapper/quote.rb
|
49
56
|
- lib/natty-ui/wrapper/request.rb
|
50
57
|
- lib/natty-ui/wrapper/section.rb
|
58
|
+
- lib/natty-ui/wrapper/table.rb
|
51
59
|
- lib/natty-ui/wrapper/task.rb
|
60
|
+
- lib/natty_ui.rb
|
52
61
|
homepage: https://github.com/mblumtritt/natty-ui
|
53
62
|
licenses:
|
54
63
|
- BSD-3-Clause
|
@@ -72,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
81
|
- !ruby/object:Gem::Version
|
73
82
|
version: '0'
|
74
83
|
requirements: []
|
75
|
-
rubygems_version: 3.
|
84
|
+
rubygems_version: 3.5.13
|
76
85
|
signing_key:
|
77
86
|
specification_version: 4
|
78
87
|
summary: This is the beautiful, nice, nifty, fancy, neat, pretty, cool, lovely, natty
|
data/examples/basic.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'natty-ui'
|
4
|
-
|
5
|
-
UI = NattyUI::StdOut
|
6
|
-
|
7
|
-
UI.space
|
8
|
-
|
9
|
-
UI.h1 'NattyUI Basic Feature Demo', <<~TEXT
|
10
|
-
|
11
|
-
This is a short demo of the basic features of [[75 bold]]NattyUI[[/]].
|
12
|
-
|
13
|
-
TEXT
|
14
|
-
|
15
|
-
UI.h2 'Feature: ANSI Colors and Attributes', <<~TEXT
|
16
|
-
|
17
|
-
Like you might noticed you can [[57]]color [[d7]]text[[/]] for terminals supporting this
|
18
|
-
feature. You can enforece the non-ANSI version by setting the environment
|
19
|
-
variable [[75 italic]]NO_COLOR[[/]] to '[[75]]1[[/]]'. (see also [[underline]]https://no-color.org[[/]])
|
20
|
-
|
21
|
-
You can not only color your text but also [[italic]]modify[[/]], [[underline]]decorate[[/]] and [[strike]]manipulate[[/]]
|
22
|
-
it. The attributes are direct embedded into the text like '[[/bold red]]'
|
23
|
-
and can be resetted with '[[//]]' or at the line end.
|
24
|
-
|
25
|
-
TEXT
|
26
|
-
|
27
|
-
UI.h2 'Feature: Sections' do |sec|
|
28
|
-
sec.puts <<~TEXT
|
29
|
-
|
30
|
-
Sections group text lines together and/or define their style. There are
|
31
|
-
several section types which all can be stacked.
|
32
|
-
|
33
|
-
Have a look at the different types of sections:
|
34
|
-
|
35
|
-
TEXT
|
36
|
-
sec.message 'Generic Message'
|
37
|
-
sec.information 'Informational Message'
|
38
|
-
sec.warning 'Warning Message'
|
39
|
-
sec.error 'Error Message'
|
40
|
-
sec.completed 'Completion Message'
|
41
|
-
sec.failed 'Failure Message'
|
42
|
-
sec.msg '[[d5]]Customized Message', symbol: '◉'
|
43
|
-
sec.space
|
44
|
-
|
45
|
-
sec.puts 'You can stack all kinds of sections together:'
|
46
|
-
sec.space
|
47
|
-
sec.framed('Rouned Frame') do |f1|
|
48
|
-
f1.framed('Heavy Framed', type: :heavy) do |f2|
|
49
|
-
f2.framed('Simple Frame', type: :simple) do |f3|
|
50
|
-
f3.framed('Double Framed Section', type: :double) do |f4|
|
51
|
-
f4.message(
|
52
|
-
'[[fff400]]Frames are nice',
|
53
|
-
"Just to show you that all sections\ncan be stacked...",
|
54
|
-
symbol: '💛'
|
55
|
-
)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
UI.space
|