natty-ui 0.11.2 → 0.12.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -2
  3. data/examples/24bit-colors.rb +1 -3
  4. data/examples/3bit-colors.rb +1 -3
  5. data/examples/8bit-colors.rb +4 -6
  6. data/examples/animate.rb +7 -9
  7. data/examples/attributes.rb +7 -10
  8. data/examples/attributes_list.rb +2 -4
  9. data/examples/demo.rb +1 -3
  10. data/examples/ls.rb +1 -3
  11. data/examples/message.rb +1 -3
  12. data/examples/progress.rb +9 -6
  13. data/examples/query.rb +1 -3
  14. data/examples/read_key.rb +1 -1
  15. data/examples/table.rb +1 -3
  16. data/lib/natty-ui/animation/binary.rb +1 -2
  17. data/lib/natty-ui/animation/default.rb +9 -13
  18. data/lib/natty-ui/animation/matrix.rb +0 -4
  19. data/lib/natty-ui/animation/type_writer.rb +5 -5
  20. data/lib/natty-ui/animation.rb +6 -6
  21. data/lib/natty-ui/ansi/constants.rb +6 -6
  22. data/lib/natty-ui/ansi.rb +19 -10
  23. data/lib/natty-ui/ansi_wrapper.rb +58 -29
  24. data/lib/natty-ui/frame.rb +53 -0
  25. data/lib/natty-ui/glyph.rb +64 -0
  26. data/lib/natty-ui/preload.rb +5 -2
  27. data/lib/natty-ui/spinner.rb +120 -0
  28. data/lib/natty-ui/text/east_asian_width.rb +1 -1
  29. data/lib/natty-ui/version.rb +1 -1
  30. data/lib/natty-ui/wrapper/ask.rb +1 -1
  31. data/lib/natty-ui/wrapper/framed.rb +3 -3
  32. data/lib/natty-ui/wrapper/heading.rb +10 -6
  33. data/lib/natty-ui/wrapper/list_in_columns.rb +1 -1
  34. data/lib/natty-ui/wrapper/message.rb +2 -2
  35. data/lib/natty-ui/wrapper/mixins.rb +11 -3
  36. data/lib/natty-ui/wrapper/progress.rb +7 -36
  37. data/lib/natty-ui/wrapper/request.rb +1 -1
  38. data/lib/natty-ui/wrapper/table.rb +8 -12
  39. data/lib/natty-ui/wrapper.rb +14 -5
  40. data/lib/natty-ui.rb +6 -66
  41. metadata +8 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ad3de350d186095b5c1d0c55e94171367fc2efefbfbe78a17c31aa10a7a94e6
4
- data.tar.gz: e7bdd00a40c25dec0fe0526cf09e2bc7ad967f7772f4de9dc321218d96114448
3
+ metadata.gz: b7b5e669e50f25432d17c55b8cbcc0e9a1c2c181982c08771b03160180586673
4
+ data.tar.gz: da124f705a984042e805c83b33565bc5c43e1a97c891ad95abccc5d2e8c62e62
5
5
  SHA512:
6
- metadata.gz: e7fa944d6f43866e23745edd5859d0428c3372821056a4cfb43af243b1dc358516be76f221e529c8efb89dfc3e0100296b1b7b28cc379017f2744bd46ee66070
7
- data.tar.gz: '09dbb59441a7a07dc3d8550f33e7d64f11ec657d6ae8b708064ee597cb99b90a3738f87861141f23df64160c6a71a3b86d4b6aa7bf4d173997d4970df5923a7d'
6
+ metadata.gz: 4be6c711b6b5cc7d3b6b6800f35e9e5450c44f6b57d139325a4afeeec3b350f26f0719a8909ee9d5d335e26803761bf3d2b31bbd672f47656d70b86ee2dbc465
7
+ data.tar.gz: 5b889460d57e3d92bb6bed0ce83fd8c4c6e7fecd8001fcd70674c6f7210550b259fcb4299d61d6a1a1ea376e96704670984a27c8471e07cb427a7fb62059de44
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # NattyUI ![version](https://img.shields.io/gem/v/natty-ui?label=)
2
2
 
3
- This is the beautiful, nice, nifty, fancy, neat, pretty, cool, lovely, natty user interface you like to have for your command line applications. It contains elegant, simple and beautiful tools that enhance your command line interfaces functionally and aesthetically.
3
+ This is the beautiful, nice, nifty, fancy, neat, pretty, cool, rich, lovely, natty user interface you like to have for your command line applications. It contains elegant, simple and beautiful tools that enhance your command line interfaces functionally and aesthetically.
4
4
 
5
5
  - Gem: [rubygems.org](https://rubygems.org/gems/natty-ui)
6
6
  - Source: [github.com](https://github.com/mblumtritt/natty-ui)
@@ -13,7 +13,10 @@ Here you find elegant, simple and beautiful tools that enhance your command line
13
13
  You can style your text using a [BBCode](https://en.wikipedia.org/wiki/BBCode)-like syntax
14
14
 
15
15
  ```ruby
16
- ui.puts '[bold underline bright_white]Hello [ff7bfd]World!'
16
+ ui.puts '[b]Hello World![/b]' # bold
17
+ ui.puts '[i]Hello World![/i]' # italic
18
+ ui.puts '[u]Hello World![/u]' # underline
19
+ ui.puts '[yellow on_blue]Hello World![/]'
17
20
  ```
18
21
 
19
22
  which supports all ANSI attributes, colors in 3/4-bit, 8-bit and Truecolor. There are headers, rulers, diverse message types, framed blocks and tables to layout your text. You can organize the output of tasks, use progress bars and request and handle user input. And there are text animations for fame and fun!
@@ -2,9 +2,7 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: 24-bit Color Support'
7
- ui.space
5
+ ui.h1 'NattyUI: 24-bit Color Support', space: 2
8
6
 
9
7
  ui.section do
10
8
  bar = '█' * ui.available_width
@@ -2,9 +2,7 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: 3/4-bit Color Support'
7
- ui.space
5
+ ui.h1 'NattyUI: 3/4-bit Color Support', space: 2
8
6
 
9
7
  color = ->(n, j) { "[#{n}]#{n.ljust(j)}[/] [on_#{n}] sample text [/]" }
10
8
  %w[black red green yellow blue magenta cyan white].each do |name|
@@ -2,12 +2,10 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: 8-bit Color Support'
7
- ui.space
5
+ ui.h1 'NattyUI: 8-bit Color Support', space: 2
8
6
 
9
7
  color = ->(i) { "[bg#{i = i.to_s(16).rjust(2, '0')}] #{i} " }
10
- ui.msg 'System Colors', glyph: :point do
8
+ ui.msg 'System Colors' do
11
9
  ui.puts <<~COLORS
12
10
  [#ff]#{0.upto(7).map(&color).join}
13
11
  [#00]#{8.upto(15).map(&color).join}
@@ -15,7 +13,7 @@ ui.msg 'System Colors', glyph: :point do
15
13
  COLORS
16
14
  end
17
15
 
18
- ui.msg '6x6x6 Color Cube', glyph: :point do
16
+ ui.msg '6x6x6 Color Cube' do
19
17
  [16, 22, 28].each do |b|
20
18
  b.step(b + 185, by: 36) do |i|
21
19
  left = i.upto(i + 5).map(&color).join
@@ -26,7 +24,7 @@ ui.msg '6x6x6 Color Cube', glyph: :point do
26
24
  end
27
25
  end
28
26
 
29
- ui.msg 'Grayscale', glyph: :point do
27
+ ui.msg 'Grayscale' do
30
28
  ui.puts <<~GRAYSCALE
31
29
  [#ff]#{232.upto(243).map(&color).join}
32
30
  [#ff]#{244.upto(255).map(&color).join}
data/examples/animate.rb CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: Text Line Animation'
7
- ui.space
5
+ ui.h1 'NattyUI: Text Line Animation', space: 2
8
6
 
9
7
  TEXT = <<~TEXT.tr("\n", ' ')
10
8
  Lorem [yellow]ipsum[/] dolor sit amet, consectetur adipisicing elit, sed
@@ -13,32 +11,32 @@ TEXT = <<~TEXT.tr("\n", ' ')
13
11
  aliquip ex ea commodo [bold]consequat[/].
14
12
  TEXT
15
13
 
16
- ui.message 'Default Animation', glyph: :point do
14
+ ui.message 'Default Animation' do
17
15
  ui.animate TEXT, animation: :default
18
16
  end
19
17
  ui.space
20
18
 
21
- ui.message 'Shiny Rainbow', glyph: :point do
19
+ ui.message 'Shiny Rainbow' do
22
20
  ui.animate TEXT, animation: :rainbow
23
21
  end
24
22
  ui.space
25
23
 
26
- ui.message 'Binary Encoded', glyph: :point do
24
+ ui.message 'Binary Encoded' do
27
25
  ui.animate TEXT, animation: :binary, style: 'green', alt_style: :bright_green
28
26
  end
29
27
  ui.space
30
28
 
31
- ui.message 'Matrix Style', glyph: :point do
29
+ ui.message 'Matrix Style' do
32
30
  ui.animate TEXT, animation: :matrix
33
31
  end
34
32
  ui.space
35
33
 
36
- ui.message 'Typewriter Like', glyph: :point do
34
+ ui.message 'Typewriter Like' do
37
35
  ui.animate TEXT, animation: :type_writer
38
36
  end
39
37
  ui.space
40
38
 
41
- ui.message 'Default Styled', glyph: :point do
39
+ ui.message 'Default Styled' do
42
40
  ui.animate TEXT, style: 'bold bright_white on_red'
43
41
  end
44
42
  ui.space
@@ -2,20 +2,17 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h2 'NattyUI: ANSI Attributes'
7
- ui.space
5
+ ui.h2 'NattyUI: ANSI Attributes', space: 2
8
6
 
9
7
  ui.puts <<~PARA1.tr("\n", ' ')
10
8
  Some attributes are widely supported, such as [b]bold[/b],
11
- [i]italic[/i], [u]underline[/u], [blink]blink[/blink],
12
- [invert]invert[/invert] and [strike]strike[/strike], while others are rarely
13
- complete or correctly implemented, like [faint]faint[/faint],
14
- [double_underline]double underline[/], [curly_underline]curly
15
- underline[/], [dotted_underline]dotted underline[/],
9
+ [i]italic[/i], [u]underline[/u], [bl]blink[/bl], [inv]invert[/inv] and
10
+ [s]strike[/s], while others are rarely complete or correctly implemented, like
11
+ [faint]faint[/faint], [double_underline]double underline[/],
12
+ [curly_underline]curly underline[/], [dotted_underline]dotted underline[/],
16
13
  [dashed_underline]dashed underline[/], [rapid_blink]rapid_blink[/],
17
- [framed]framed[/], [encircled]encircled[/],
18
- [overlined]overlined[/] and [proportional]proportional[/].
14
+ [framed]framed[/], [encircled]encircled[/], [overlined]overlined[/] and
15
+ [proportional]proportional[/].
19
16
  PARA1
20
17
 
21
18
  ui.puts <<~PARA2.tr("\n", ' ')
@@ -2,13 +2,11 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h2 'NattyUI: All Attribute and Defined Color Names'
7
- ui.space
5
+ ui.h2 'NattyUI: All Attribute and Defined Color Names', space: 2
8
6
 
9
7
  ui.ls(
10
8
  (NattyUI::Ansi.attribute_names + NattyUI::Ansi.color_names)
11
9
  .sort!
12
- .map! { |name| "[#{name}]#{name}[/]" }
10
+ .map! { |name| "[#{name}]#{name}" }
13
11
  )
14
12
  ui.space
data/examples/demo.rb CHANGED
@@ -3,9 +3,7 @@
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
5
  ui.page do
6
- ui.space
7
- ui.h1 'NattyUI: Examples'
8
- ui.space
6
+ ui.h1 'NattyUI: Examples', space: 2
9
7
 
10
8
  ruby =
11
9
  ENV.fetch('RUBY') do
data/examples/ls.rb CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: Print In Columns'
7
- ui.space
5
+ ui.h1 'NattyUI: Print In Columns', space: 2
8
6
 
9
7
  LOREM = <<~IPSUM.lines(chomp: true)
10
8
  Lorem ipsum dolor sit
data/examples/message.rb CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: Message Types'
7
- ui.space
5
+ ui.h1 'NattyUI: Message Types', space: 2
8
6
 
9
7
  TEXT = <<~TEXT.tr("\n", ' ')
10
8
  Lorem [yellow]ipsum[/fg] dolor sit amet, consectetur adipisicing elit, sed
data/examples/progress.rb CHANGED
@@ -2,13 +2,16 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: Progress Indication'
7
- ui.space
5
+ ui.h1 'NattyUI: Progress Indication', space: 2
8
6
 
9
7
  # just simulate some work
10
- def something = sleep(0.5)
11
- def some = sleep(0.15)
8
+ if ENV.key?('NO_WAIT')
9
+ def something = nil
10
+ def some = nil
11
+ else
12
+ def something = sleep(0.5)
13
+ def some = sleep(0.15)
14
+ end
12
15
 
13
16
  ui.info 'Tasks are sections to visualize step by step processing.' do
14
17
  ui.task 'Assemble assets' do
@@ -25,7 +28,7 @@ ui.info 'Tasks are sections to visualize step by step processing.' do
25
28
 
26
29
  ui.task 'Compile files...' do
27
30
  %w[readme.txt main.css main.html sub.html].each do |name|
28
- ui.msg "Compile file [bright_yellow]./source/#{name}[/]..."
31
+ ui.msg "Compile file [bright_yellow]./source/#{name}[/]...", glyph: :dot
29
32
  something
30
33
  end
31
34
  ui.done 'Files compiled.'
data/examples/query.rb CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: User Queries'
7
- ui.space
5
+ ui.h1 'NattyUI: User Queries', space: 2
8
6
 
9
7
  # little helper
10
8
  def abort!
data/examples/read_key.rb CHANGED
@@ -4,7 +4,7 @@ require_relative '../lib/natty-ui'
4
4
 
5
5
  ui.puts '⌨️ Display Keyboard Input [bright_black](Exit with Ctrl+C)'
6
6
 
7
- ui.section prefix: '[blue]:[/] ' do
7
+ ui.section prefix: '[blue]:[/fg] ' do
8
8
  while true
9
9
  raw, name = NattyUI.read_key(mode: :both)
10
10
  ui.puts "[yellow]#{raw.inspect}[/] [bold bright_green]#{name}[/]"
data/examples/table.rb CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- ui.space
6
- ui.h1 'NattyUI: Tables'
7
- ui.space
5
+ ui.h1 'NattyUI: Tables', space: 2
8
6
 
9
7
  User = Struct.new(:id, :name, :mail, :notes)
10
8
  users = [
@@ -12,9 +12,8 @@ module NattyUI
12
12
  35.times do |i|
13
13
  binary.each do |chars|
14
14
  rc = rand_char
15
- rc = @style + rc if rc.size == 1
16
15
  chars.pop
17
- chars.unshift(rc)
16
+ chars.unshift(rc.size == 1 ? @style + rc : rc)
18
17
  puts(stream, chars.join)
19
18
  end
20
19
  (stream << @top).flush
@@ -11,23 +11,19 @@ module NattyUI
11
11
  @lines.each do |line, size|
12
12
  time = 0.25 / size
13
13
  stream << style
14
+ line = Text.plain(line)
14
15
  if (num += 1).odd?
15
16
  stream << @pos1
16
- Text
17
- .plain(line)
18
- .each_char do |char|
19
- (stream << char).flush
20
- sleep(time)
21
- end
17
+ line.each_char do |char|
18
+ (stream << char).flush
19
+ sleep(time)
20
+ end
22
21
  else
23
22
  stream << Ansi.cursor_column(@prefix_width + size - 1)
24
- Text
25
- .plain(line)
26
- .reverse
27
- .each_char do |char|
28
- (stream << char << CURSOR_LEFT).flush
29
- sleep(time)
30
- end
23
+ line.reverse.each_char do |char|
24
+ (stream << char << CURSOR_LEFT).flush
25
+ sleep(time)
26
+ end
31
27
  end
32
28
  stream << Ansi::RESET << @pos1 << line << Ansi::LINE_NEXT
33
29
  end
@@ -22,10 +22,6 @@ module NattyUI
22
22
  pos.pop(count).each { enc[_1] = line[_1] }
23
23
  pos.sample(pos.size / 3).each { enc[_1] = CHARS.sample }
24
24
  end
25
-
26
- # next stream << Ansi::LINE_NEXT if pos.size < 4
27
- # pos.shift(pos.size / 8).each { enc[_1] = line[_1] }
28
- # pos.sample(pos.size / 2).each { enc[_1] = CHARS.sample }
29
25
  puts(stream, enc)
30
26
  end
31
27
  (stream << @top).flush
@@ -10,15 +10,15 @@ module NattyUI
10
10
  @style = attribute(:style, :default)
11
11
  @cursor_style = attribute(:cursor_style, 0x2e)
12
12
  @lines.each do |line, size|
13
+ line = Text.plain(line)
13
14
  if (num += 1).odd?
14
15
  stream << @pos1
15
- Text.plain(line).each_char { cursor(stream, _1).flush }
16
+ line.each_char { cursor(stream, _1).flush }
16
17
  else
17
18
  stream << Ansi.cursor_column(@prefix_width + size - 1)
18
- Text
19
- .plain(line)
20
- .reverse
21
- .each_char { (cursor(stream, _1) << CURSOR_2LEFT).flush }
19
+ line.reverse.each_char do |char|
20
+ (cursor(stream, char) << CURSOR_2LEFT).flush
21
+ end
22
22
  end
23
23
  stream << Ansi::RESET << @pos1 << line << Ansi::LINE_NEXT
24
24
  end
@@ -2,19 +2,19 @@
2
2
 
3
3
  module NattyUI
4
4
  module Animation
5
- def self.defined = @defined.keys
6
- def self.defined?(name) = @defined.key?(name)
7
- def self.define(**kwargs) = @defined.merge!(kwargs)
5
+ def self.names = @all.keys
8
6
 
9
7
  def self.[](name)
10
8
  return if name.nil?
11
- klass = @defined[name] || @defined[:default]
9
+ klass = @all[name] || @all[:default]
12
10
  return klass unless klass.is_a?(String)
13
11
  require(klass)
14
- klass = @defined[name] and return klass
12
+ klass = @all[name] and return klass
15
13
  raise(LoadError, "unknown animation - #{name}")
16
14
  end
17
15
 
16
+ def self.define(**kwargs) = @all.merge!(kwargs)
17
+
18
18
  class Base
19
19
  attr_reader :lines_written
20
20
 
@@ -58,7 +58,7 @@ module NattyUI
58
58
  private_constant :Base
59
59
 
60
60
  dir = __dir__
61
- @defined = {
61
+ @all = {
62
62
  binary: "#{dir}/animation/binary",
63
63
  default: "#{dir}/animation/default",
64
64
  matrix: "#{dir}/animation/matrix",
@@ -59,17 +59,17 @@ module NattyUI::Ansi
59
59
  REVEAL = self[:reveal].freeze
60
60
 
61
61
  # @!visibility private
62
- CLS = (CURSOR_HOME + SCREEN_ERASE).freeze
62
+ CLS = "#{CURSOR_HOME}#{SCREEN_ERASE}".freeze
63
63
 
64
64
  # @!visibility private
65
- CLL = (CURSOR_FIRST_COLUMN + LINE_ERASE).freeze
65
+ CLL = "#{CURSOR_FIRST_COLUMN}#{LINE_ERASE}".freeze
66
66
 
67
67
  # @!visibility private
68
68
  SCREEN_BLANK =
69
- (
70
- CURSOR_SAFE_POS + SCREEN_ALTERNATE + CURSOR_HOME + SCREEN_ERASE + RESET
71
- ).freeze
69
+ "#{CURSOR_SAFE_POS}#{
70
+ SCREEN_ALTERNATE
71
+ }#{CURSOR_HOME}#{SCREEN_ERASE}#{RESET}".freeze
72
72
 
73
73
  # @!visibility private
74
- SCREEN_UNBLANK = (RESET + SCREEN_ALTERNATE_OFF + CURSOR_RESTORE_POS).freeze
74
+ SCREEN_UNBLANK = "#{RESET}#{SCREEN_ALTERNATE_OFF}#{CURSOR_RESTORE_POS}".freeze
75
75
  end
data/lib/natty-ui/ansi.rb CHANGED
@@ -373,16 +373,7 @@ module NattyUI
373
373
  'dashed_underline_off' => '4:0',
374
374
  'curly_underline' => '4:3',
375
375
  'dotted_underline' => '4:4',
376
- 'dashed_underline' => '4:5',
377
- # aliases
378
- 'b' => 1, # bold
379
- '/b' => 22, # bold_off
380
- 'i' => 3, # italic
381
- '/i' => 23, # italic_off
382
- 'u' => 4, # underline
383
- '/u' => 24, # underline_off
384
- 'h' => 8, # hide
385
- '/h' => 28 # reveal
376
+ 'dashed_underline' => '4:5'
386
377
  }
387
378
  add = ->(s, n) { n.each_with_index { |a, idx| map[a] = s + idx } }
388
379
  add[
@@ -432,6 +423,24 @@ module NattyUI
432
423
  ]
433
424
  add[73, %w[superscript subscript superscript_off]]
434
425
 
426
+ add_alias =
427
+ proc do |name, org_name|
428
+ map[name] = map[org_name] or
429
+ raise("undefined value - #{org_name}")
430
+ map["/#{name}"] = map["#{org_name}_off"] or
431
+ raise("undefined value - #{org_name}_off")
432
+ end
433
+ add_alias['b', 'bold']
434
+ add_alias['i', 'italic']
435
+ add_alias['u', 'underline']
436
+ add_alias['bl', 'blink']
437
+ add_alias['inv', 'invert']
438
+ add_alias['s', 'strike']
439
+ add_alias['sup', 'superscript']
440
+ add_alias['sub', 'subscript']
441
+ add_alias['prop', 'proportional']
442
+ add_alias['sp', 'spacing']
443
+
435
444
  map.merge!(
436
445
  map
437
446
  .filter_map do |name, att|
@@ -6,13 +6,23 @@ module NattyUI
6
6
  class AnsiWrapper < Wrapper
7
7
  def ansi? = true
8
8
 
9
+ def cursor=(value)
10
+ if value
11
+ (@stream << Ansi::CURSOR_SHOW).flush if @cursor == 1
12
+ @cursor -= 1 if @cursor.positive?
13
+ return
14
+ end
15
+ (@stream << Ansi::CURSOR_HIDE).flush if @cursor.zero?
16
+ @cursor += 1
17
+ end
18
+
9
19
  def puts(*args, **kwargs)
10
20
  return super if args.empty? || (animation = kwargs[:animation]).nil?
11
21
  animation = Animation[animation].new(wrapper, args, kwargs)
12
- @stream << Ansi::CURSOR_HIDE
22
+ self.cursor = false
13
23
  animation.perform(@stream)
14
24
  @lines_written += animation.lines_written
15
- (@stream << Ansi::CURSOR_SHOW).flush
25
+ self.cursor = true
16
26
  self
17
27
  end
18
28
 
@@ -77,39 +87,58 @@ module NattyUI
77
87
  end
78
88
  end
79
89
 
80
- class Progress < Progress
81
- def draw(title, spinner)
82
- @msg =
83
- "#{@parent.prefix}#{Ansi[:bold, 39]}➔#{Ansi[:reset, 39]} " \
84
- "#{title}#{Ansi::RESET} "
85
- (wrapper.stream << @msg << Ansi::CURSOR_HIDE).flush
86
- @msg = "#{Ansi::CLL}#{@msg}"
87
- return @msg << BAR_COLOR if @max_value
88
- spinner_color = Ansi[:bold, 220]
89
- @spinner =
90
- Enumerator.new do |y|
91
- spinner.each_char { y << "#{spinner_color}#{_1}" } while true
92
- end
90
+ class Progress < Element
91
+ include ProgressAttributes
92
+ include ValueAttributes
93
+
94
+ protected
95
+
96
+ def call(title, max_value, spinner)
97
+ @title = "[b 27]➔[/b] #{title}"
98
+ @info = nil
99
+ @final_text = [title]
100
+ if max_value
101
+ @max_value = [0, max_value.to_f].max
102
+ else
103
+ @spinner = NattyUI::Spinner[spinner]
104
+ end
105
+ @value = 0
106
+ @pos = wrapper.lines_written
107
+ wrapper.cursor = false
108
+ @parent.puts(@last_render = render)
109
+ @height = wrapper.lines_written - @pos
110
+ self
93
111
  end
94
112
 
95
113
  def redraw
96
- (wrapper.stream << @msg << (@max_value ? fullbar : @spinner.next)).flush
114
+ return if @status
115
+ current = render
116
+ return if @last_render == current
117
+ wrapper.stream << Ansi.cursor_previous_line(@height) << Ansi::LINE_ERASE
118
+ cl = wrapper.lines_written
119
+ @parent.puts(@last_render = current)
120
+ @height = wrapper.lines_written - cl
97
121
  end
98
122
 
99
- def end_draw = (wrapper.stream << Ansi::CLL << Ansi::CURSOR_SHOW).flush
100
-
101
- def fullbar
102
- percent = @value / @max_value
103
- count = (30 * percent).to_i
104
- mv = max_value.to_i.to_s
105
- "#{'█' * count}#{BAR_BACK}#{'▁' * (30 - count)}" \
106
- "#{BAR_INK} #{value.to_i.to_s.rjust(mv.size)}/#{mv} " \
107
- "(#{(percent * 100).round(2).to_s.rjust(6)})"
123
+ def render
124
+ return "#{@title} #{@spinner.next}#{" #{@info}" if @info}" if @spinner
125
+ percent = @max_value.zero? ? 100.0 : @value / @max_value
126
+ count = [(30 * percent).round, 30].min
127
+ mv = @max_value.round.to_s
128
+ "#{@title} [27 on27]#{'█' * count}[ec onec]#{
129
+ '▁' * (30 - count)
130
+ }[/bg] [e2 b]#{(percent * 100).round.to_s.rjust(3)}%[/b] [f6](#{
131
+ @value.round.to_s.rjust(mv.size)
132
+ }/#{mv})[/]#{" #{@info}" if @info}"
108
133
  end
109
134
 
110
- BAR_COLOR = Ansi[39, 295].freeze
111
- BAR_BACK = Ansi[236, 492].freeze
112
- BAR_INK = Ansi[:bold, 255, :on_default].freeze
135
+ def finish
136
+ wrapper.stream << Ansi.cursor_previous_line(@height) << Ansi::LINE_ERASE
137
+ wrapper.instance_variable_set(:@lines_written, @pos)
138
+ wrapper.cursor = true
139
+ return @parent.failed(*@final_text) if failed?
140
+ @parent.message(*@final_text, glyph: @status = :completed)
141
+ end
113
142
  end
114
143
 
115
144
  module Temporary
@@ -162,7 +191,7 @@ module NattyUI
162
191
 
163
192
  def initialize(parent, title:, glyph:, **opts)
164
193
  color = COLORS[glyph] || COLORS[:default]
165
- glyph = NattyUI.glyph(glyph) || glyph
194
+ glyph = NattyUI::Glyph[glyph]
166
195
  prefix_width = Text.width(glyph) + 1
167
196
  parent.puts(
168
197
  title,
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NattyUI
4
+ # Helper class to select frame types.
5
+ # @see Features#framed
6
+ # @see Features#table
7
+ module Frame
8
+ # Define frame type used by default.
9
+ #
10
+ # @attribute [w] self.default
11
+ # @param value [Symbol] type name
12
+ # @return [Symbol] type name
13
+ def self.default=(value)
14
+ @default = self[value.nil? || value == :default ? :rounded : value]
15
+ end
16
+
17
+ # Defined frame type names.
18
+ # @see []
19
+ #
20
+ # @attribute [r] self.names
21
+ # @return [Array<Symbol>] supported attribute names
22
+ def self.names = @all.keys
23
+
24
+ # @param name [Symbol, String]
25
+ # defined type name (see {.names})
26
+ # or frame elements
27
+ # @return [String] frame definition
28
+ def self.[](name)
29
+ return @default if name == :default
30
+ if name.is_a?(Symbol)
31
+ ret = @all[name] and return ret
32
+ elsif name.is_a?(String)
33
+ return name if name.size == 11
34
+ return name * 11 if name.size == 1
35
+ end
36
+ raise(ArgumentError, "invalid frame type - #{name}")
37
+ end
38
+
39
+ @all = {
40
+ cols: ' │ │ ',
41
+ double: '╔╗╚╝║═╬╦╩╠╣',
42
+ heavy: '┏┓┗┛┃━╋┳┻┣┫',
43
+ rounded: '╭╮╰╯│─┼┬┴├┤',
44
+ rows: ' ── ',
45
+ semi: '╒╕╘╛│═╪╤╧╞╡',
46
+ semi2: '╓╖╙╜│─╫╥╨╟╢',
47
+ simple: '┌┐└┘│─┼┬┴├┤',
48
+ undecorated: ' '
49
+ }.compare_by_identity
50
+
51
+ self.default = nil
52
+ end
53
+ end