natty-ui 0.9.4 → 0.11.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -11
  3. data/examples/24bit-colors.rb +8 -16
  4. data/examples/3bit-colors.rb +1 -1
  5. data/examples/8bit-colors.rb +15 -11
  6. data/examples/animate.rb +31 -11
  7. data/examples/attributes.rb +16 -14
  8. data/examples/attributes_list.rb +14 -0
  9. data/examples/demo.rb +4 -4
  10. data/examples/illustration.rb +52 -24
  11. data/examples/ls.rb +4 -4
  12. data/examples/message.rb +11 -9
  13. data/examples/progress.rb +2 -2
  14. data/examples/query.rb +1 -1
  15. data/examples/table.rb +23 -23
  16. data/lib/natty-ui/animation/binary.rb +37 -0
  17. data/lib/natty-ui/animation/default.rb +42 -0
  18. data/lib/natty-ui/animation/matrix.rb +55 -0
  19. data/lib/natty-ui/animation/rainbow.rb +28 -0
  20. data/lib/natty-ui/animation/type_writer.rb +44 -0
  21. data/lib/natty-ui/animation.rb +69 -0
  22. data/lib/natty-ui/ansi/constants.rb +1 -1
  23. data/lib/natty-ui/ansi.rb +46 -26
  24. data/lib/natty-ui/ansi_wrapper.rb +47 -51
  25. data/lib/natty-ui/key_map.rb +72 -49
  26. data/lib/natty-ui/preload.rb +1 -1
  27. data/lib/natty-ui/text.rb +75 -85
  28. data/lib/natty-ui/version.rb +1 -1
  29. data/lib/natty-ui/wrapper/animate.rb +1 -1
  30. data/lib/natty-ui/wrapper/ask.rb +1 -1
  31. data/lib/natty-ui/wrapper/element.rb +18 -10
  32. data/lib/natty-ui/wrapper/features.rb +0 -8
  33. data/lib/natty-ui/wrapper/framed.rb +7 -27
  34. data/lib/natty-ui/wrapper/message.rb +1 -1
  35. data/lib/natty-ui/wrapper/request.rb +1 -1
  36. data/lib/natty-ui/wrapper/section.rb +18 -18
  37. data/lib/natty-ui/wrapper/table.rb +432 -168
  38. data/lib/natty-ui/wrapper.rb +45 -48
  39. data/lib/natty-ui.rb +65 -2
  40. metadata +10 -8
  41. data/lib/natty-ui/line_animation/default.rb +0 -35
  42. data/lib/natty-ui/line_animation/matrix.rb +0 -28
  43. data/lib/natty-ui/line_animation/rainbow.rb +0 -30
  44. data/lib/natty-ui/line_animation/type_writer.rb +0 -44
  45. data/lib/natty-ui/line_animation.rb +0 -48
@@ -47,24 +47,29 @@ module NattyUI
47
47
 
48
48
  # Print given arguments line-wise to the output stream.
49
49
  #
50
- # @overload puts(...)
51
- # @param [#to_s] ... objects to print
52
- # @return [Wrapper] itself
53
- def puts(*args, **kwargs)
54
- @stream.puts(args = prepare_print(args, kwargs))
55
- @lines_written += args.size
50
+ # @param [#to_s] args objects to print
51
+ # @option options [:left, :right, :center] :align text alignment
52
+ # @return [Wrapper] itself
53
+ def puts(*args, **options)
54
+ pprint(args, options) do |line|
55
+ @stream.puts(line)
56
+ @lines_written += 1
57
+ end
56
58
  @stream.flush
57
59
  self
58
60
  end
59
61
 
60
62
  # Print given arguments to the output stream.
61
63
  #
62
- # @overload print(...)
63
- # @param [#to_s] ... objects to print
64
- # @return [Wrapper] itself
65
- def print(*args, **kwargs)
66
- @stream.print(*(args = prepare_print(args, kwargs)))
67
- @lines_written += args.size - 1
64
+ # @param [#to_s] args objects to print
65
+ # @option options [:left, :right, :center] :align text alignment
66
+ # @return [Wrapper] itself
67
+ def print(*args, **options)
68
+ pprint(args, options) do |line|
69
+ @stream.print(line)
70
+ @lines_written += 1
71
+ end
72
+ @lines_written -= 1
68
73
  @stream.flush
69
74
  self
70
75
  end
@@ -152,21 +157,36 @@ module NattyUI
152
157
  # @!visibility private
153
158
  def prefix = nil
154
159
 
155
- # @return [Array<Symbol>] available glyph names
156
- def glyph_names = GLYPHS.keys
157
-
158
- #
159
- # Get a pre-defined glyph
160
- #
161
- # @param [Symbol] name glyph name
162
- # @return [String] the named glyph
163
- # @return [nil] when glyph is not defined
164
- def glyph(name) = GLYPHS[name]
165
-
166
160
  protected
167
161
 
168
- def prepare_print(args, kwargs)
169
- Text.prepare_print(args, kwargs, -> { screen_columns }) { Text.plain(_1) }
162
+ def pprint(strs, opts)
163
+ prefix = opts[:prefix] and prefix = Text.plain(prefix)
164
+ suffix = opts[:suffix] and suffix = Text.plain(suffix)
165
+ return yield("#{prefix}#{suffix}") if strs.empty?
166
+ max_width =
167
+ opts.fetch(:max_width) do
168
+ screen_columns - (opts[:prefix_width] || Text.width(prefix)) -
169
+ (opts[:suffix_width] || Text.width(suffix))
170
+ end
171
+ case opts[:align]
172
+ when :right
173
+ Text.each_line_plain(strs, max_width) do |line, width|
174
+ width = max_width - width
175
+ yield("#{prefix}#{' ' * width}#{line}#{suffix}")
176
+ end
177
+ when :center
178
+ Text.each_line_plain(strs, max_width) do |line, width|
179
+ width = max_width - width
180
+ right = width / 2
181
+ yield(
182
+ "#{prefix}#{' ' * (width - right)}#{line}#{' ' * right}#{suffix}"
183
+ )
184
+ end
185
+ else
186
+ Text.each_line_plain(strs, max_width) do |line|
187
+ yield("#{prefix}#{line}#{suffix}")
188
+ end
189
+ end
170
190
  end
171
191
 
172
192
  def temp_func
@@ -206,28 +226,5 @@ module NattyUI
206
226
  rescue SystemCallError
207
227
  nil
208
228
  end
209
-
210
- GLYPHS = {
211
- default: "#{Ansi[:bold, 255]}•#{Ansi::RESET}",
212
- information: "#{Ansi[:bold, 119]}𝒊#{Ansi::RESET}",
213
- warning: "#{Ansi[:bold, 221]}!#{Ansi::RESET}",
214
- error: "#{Ansi[:bold, 208]}𝙓#{Ansi::RESET}",
215
- completed: "#{Ansi[:bold, 82]}✓#{Ansi::RESET}",
216
- failed: "#{Ansi[:bold, 196]}𝑭#{Ansi::RESET}",
217
- task: "#{Ansi[:bold, 39]}➔#{Ansi::RESET}",
218
- query: "#{Ansi[:bold, 39]}▸#{Ansi::RESET}"
219
- }.compare_by_identity.freeze
220
-
221
- # GLYPHS = {
222
- # default: '●',
223
- # information: '🅸 ',
224
- # warning: '🆆 ',
225
- # error: '🅴 ',
226
- # completed: '✓',
227
- # failed: '🅵 ',
228
- # task: '➔',
229
- # query: '🆀 '
230
- # }.compare_by_identity.freeze
231
- private_constant :GLYPHS
232
229
  end
233
230
  end
data/lib/natty-ui.rb CHANGED
@@ -135,6 +135,34 @@ module NattyUI
135
135
  nil
136
136
  end
137
137
 
138
+ # @return [Array<Symbol>] available glyph names
139
+ def glyph_names = GLYPH.keys
140
+
141
+ # Get a pre-defined glyph.
142
+ #
143
+ # @param [Symbol] name glyph name
144
+ # @return [String] the glyph
145
+ # @return [nil] when glyph is not defined
146
+ def glyph(name) = GLYPH[name]
147
+
148
+ # @return [Array<Symbol>] available frame names
149
+ def frame_names = FRAME.keys
150
+
151
+ # Get a frame definition.
152
+ #
153
+ # @param [Symbol] name frame type name
154
+ # @return [String] the frame definition
155
+ # @raise [ArgumentError] when an invalid name is specified
156
+ def frame(name)
157
+ if name.is_a?(Symbol)
158
+ ret = FRAME[name] and return ret
159
+ elsif name.is_a?(String)
160
+ return name if name.size == 11
161
+ return name * 11 if name.size == 1
162
+ end
163
+ raise(ArgumentError, "invalid frame type - #{name.inspect}")
164
+ end
165
+
138
166
  private
139
167
 
140
168
  def wrapper_class(stream, ansi)
@@ -159,10 +187,45 @@ module NattyUI
159
187
  StdErr = stderr_is_stdout? ? StdOut : new(STDERR)
160
188
 
161
189
  dir = __dir__
162
- autoload(:LineAnimation, File.join(dir, 'natty-ui', 'line_animation'))
190
+ autoload(:Animation, File.join(dir, 'natty-ui', 'animation'))
163
191
  autoload(:KEY_MAP, File.join(dir, 'natty-ui', 'key_map'))
164
192
 
165
- private_constant :LineAnimation, :KEY_MAP
193
+ GLYPH = {
194
+ default: "#{Ansi[:bold, 255]}•#{Ansi::RESET}",
195
+ point: "#{Ansi[0x27]}◉#{Ansi::RESET}",
196
+ information: "#{Ansi[:bold, 119]}𝒊#{Ansi::RESET}",
197
+ warning: "#{Ansi[:bold, 221]}!#{Ansi::RESET}",
198
+ error: "#{Ansi[:bold, 208]}𝙓#{Ansi::RESET}",
199
+ completed: "#{Ansi[:bold, 82]}✓#{Ansi::RESET}",
200
+ failed: "#{Ansi[:bold, 196]}𝑭#{Ansi::RESET}",
201
+ task: "#{Ansi[:bold, 39]}➔#{Ansi::RESET}",
202
+ query: "#{Ansi[:bold, 39]}▸#{Ansi::RESET}"
203
+ }.compare_by_identity.freeze
204
+
205
+ # GLYPH = {
206
+ # default: '●',
207
+ # information: '🅸 ',
208
+ # warning: '🆆 ',
209
+ # error: '🅴 ',
210
+ # completed: '✓',
211
+ # failed: '🅵 ',
212
+ # task: '➔',
213
+ # query: '🆀 '
214
+ # }.compare_by_identity.freeze
215
+
216
+ FRAME = {
217
+ rounded: '╭╮╰╯│─┼┬┴├┤',
218
+ simple: '┌┐└┘│─┼┬┴├┤',
219
+ heavy: '┏┓┗┛┃━╋┳┻┣┫',
220
+ double: '╔╗╚╝║═╬╦╩╠╣',
221
+ semi: '╒╕╘╛│═╪╤╧╞╡',
222
+ semi2: '╓╖╙╜│─╫╥╨╟╢',
223
+ rows: ' ── ',
224
+ cols: ' │ │ ',
225
+ undecorated: ' '
226
+ }.compare_by_identity.freeze
227
+
228
+ private_constant :Animation, :KEY_MAP, :GLYPH, :FRAME
166
229
 
167
230
  @element = StdOut
168
231
  self.in_stream = STDIN
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: natty-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
4
+ version: 0.11.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: 2024-07-13 00:00:00.000000000 Z
11
+ date: 2024-07-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  This is the beautiful, nice, nifty, fancy, neat, pretty, cool, lovely,
@@ -30,6 +30,7 @@ files:
30
30
  - examples/8bit-colors.rb
31
31
  - examples/animate.rb
32
32
  - examples/attributes.rb
33
+ - examples/attributes_list.rb
33
34
  - examples/demo.rb
34
35
  - examples/illustration.rb
35
36
  - examples/ls.rb
@@ -39,15 +40,16 @@ files:
39
40
  - examples/read_key.rb
40
41
  - examples/table.rb
41
42
  - lib/natty-ui.rb
43
+ - lib/natty-ui/animation.rb
44
+ - lib/natty-ui/animation/binary.rb
45
+ - lib/natty-ui/animation/default.rb
46
+ - lib/natty-ui/animation/matrix.rb
47
+ - lib/natty-ui/animation/rainbow.rb
48
+ - lib/natty-ui/animation/type_writer.rb
42
49
  - lib/natty-ui/ansi.rb
43
50
  - lib/natty-ui/ansi/constants.rb
44
51
  - lib/natty-ui/ansi_wrapper.rb
45
52
  - lib/natty-ui/key_map.rb
46
- - lib/natty-ui/line_animation.rb
47
- - lib/natty-ui/line_animation/default.rb
48
- - lib/natty-ui/line_animation/matrix.rb
49
- - lib/natty-ui/line_animation/rainbow.rb
50
- - lib/natty-ui/line_animation/type_writer.rb
51
53
  - lib/natty-ui/preload.rb
52
54
  - lib/natty-ui/text.rb
53
55
  - lib/natty-ui/text/east_asian_width.rb
@@ -94,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
96
  - !ruby/object:Gem::Version
95
97
  version: '0'
96
98
  requirements: []
97
- rubygems_version: 3.5.15
99
+ rubygems_version: 3.5.16
98
100
  signing_key:
99
101
  specification_version: 4
100
102
  summary: This is the beautiful, nice, nifty, fancy, neat, pretty, cool, lovely, natty
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NattyUI
4
- module LineAnimation
5
- class Default < None
6
- def initialize(*_)
7
- super
8
- @column = @options[:prefix_width] + 1
9
- @color = color
10
- @num = 0
11
- end
12
-
13
- def print(line)
14
- line = Text.plain(line)
15
- time = 0.5 / line.size
16
- @stream << @color
17
- if (@num += 1).odd?
18
- line.each_char do |char|
19
- (@stream << char).flush
20
- sleep(time)
21
- end
22
- else
23
- pos = @column + line.size
24
- line.reverse!
25
- line.each_char do |char|
26
- (@stream << Ansi.cursor_column(pos -= 1) << char).flush
27
- sleep(time)
28
- end
29
- end
30
- end
31
- end
32
-
33
- define default: Default
34
- end
35
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NattyUI
4
- module LineAnimation
5
- class Matrix < None
6
- def initialize(*_)
7
- super
8
- @prefix = "#{to_column}#{color}"
9
- end
10
-
11
- def print(line)
12
- line = Text.plain(line)
13
- str = Array.new(line.size) { CHARS.sample }.join
14
- pos = Array.new(line.size, &:itself).shuffle
15
- until pos.size < 4
16
- pos.shift(pos.size / 4).each { str[_1] = line[_1] }
17
- pos.sample(pos.size / 2).each { str[_1] = CHARS.sample }
18
- (@stream << "#{@prefix}#{str}").flush
19
- sleep(0.08)
20
- end
21
- end
22
-
23
- CHARS = '2598Z*):.\=+-¦|_ヲアウエオカキケコサシスセソタツテナニヌネハヒホマミムメモヤユラリワ'.chars
24
- end
25
-
26
- define matrix: Matrix
27
- end
28
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NattyUI
4
- module LineAnimation
5
- class Rainbow < None
6
- def initialize(*_)
7
- super
8
- @prefix = to_column
9
- end
10
-
11
- def print(line)
12
- line = Text.plain(line)
13
- 11.upto(200) do |spread|
14
- (
15
- @stream << @prefix <<
16
- Ansi.rainbow(
17
- line,
18
- frequence: 0.1,
19
- spread: spread / 100.0,
20
- seed: 0
21
- )
22
- ).flush
23
- sleep(0.01)
24
- end
25
- end
26
- end
27
-
28
- define rainbow: Rainbow
29
- end
30
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NattyUI
4
- module LineAnimation
5
- class TypeWriter < None
6
- def initialize(*_)
7
- super
8
- @color = color
9
- @cursor_color = attribute(:cursor_color, 0x2e)
10
- @column = @options[:prefix_width] + 1
11
- @num = 0
12
- end
13
-
14
- def print(line)
15
- line = Text.plain(line)
16
- if (@num += 1).odd?
17
- line.each_char { (@stream << cursor(_1)).flush }
18
- else
19
- pos = @column + line.size
20
- line.reverse!
21
- line.each_char do |char|
22
- @stream << Ansi.cursor_column(pos -= 1)
23
- (@stream << cursor(char)).flush
24
- end
25
- end
26
- end
27
-
28
- def cursor(char)
29
- @stream << @cursor_color
30
- (SPACE.match?(char) ? '▁' : '▁▂▃▄▅▆▇█').each_char do |cursor|
31
- (@stream << cursor).flush
32
- sleep(0.002)
33
- @stream << CURSOR_BACK
34
- end
35
- @stream << @color
36
- char
37
- end
38
-
39
- CURSOR_BACK = Ansi.cursor_back(1)
40
- end
41
-
42
- define type_writer: TypeWriter
43
- end
44
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NattyUI
4
- module LineAnimation
5
- def self.defined = @defined.keys
6
- def self.defined?(name) = @defined.key?(name)
7
- def self.define(**kwargs) = @defined.merge!(kwargs)
8
-
9
- def self.[](name)
10
- return if name.nil?
11
- klass = @defined[name] || @defined[:default]
12
- return klass unless klass.is_a?(String)
13
- require(klass)
14
- klass = @defined[name] and return klass
15
- raise(LoadError, "unknown animation - #{name}")
16
- end
17
-
18
- class None
19
- def initialize(stream, options)
20
- @stream = stream
21
- @options = options
22
- end
23
-
24
- def print(_line) = raise(NotImplementedError)
25
-
26
- protected
27
-
28
- def to_column = Ansi.cursor_column(@options[:prefix_width] + 1)
29
- def color = attribute(:color, :default)
30
-
31
- def attribute(name, *default)
32
- att = @options[name] or return Ansi[*default]
33
- return Ansi[*att] if att.is_a?(Enumerable)
34
- Ansi.try_convert(att.to_s) || Ansi[*default]
35
- end
36
-
37
- SPACE = /[[:space:]]/
38
- end
39
-
40
- dir = __dir__
41
- @defined = {
42
- default: "#{dir}/line_animation/default",
43
- matrix: "#{dir}/line_animation/matrix",
44
- rainbow: "#{dir}/line_animation/rainbow",
45
- type_writer: "#{dir}/line_animation/type_writer"
46
- }.compare_by_identity
47
- end
48
- end