natty-ui 0.11.1 → 0.12.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c2fdc1d9e9799f56f2781822273de9239840e94ceadac332710fe70fc1082bd
4
- data.tar.gz: e33e6c658e86259f364f320f1e060d7d2f8a7444e07119d125cd0a335cb23313
3
+ metadata.gz: 0aa357f7937c367ecc77396e7241f33a774973d773b99c6923cc975199755a14
4
+ data.tar.gz: '060778aaca552a23c57e39e4efd8adf3eff07658e6a712708b6c8e46c5077bc1'
5
5
  SHA512:
6
- metadata.gz: b8fc4cfe81f56efafb0b605d9694e7b592bbd4daa4edab2b6b0d1e7a81ba87704f4fb4d0f8acc9572907cd4f3d815762d41002b64082bb04c9a085f5709e4be5
7
- data.tar.gz: 4cab9391a300aaf0c7f74f6861c7805f008df6c824de3813eeaaebda0cbc42ff661b14da4a71e2c0860687e971dd98f680d33573fdb9da8f4b38bf4d2ef21bf2
6
+ metadata.gz: c79a14e0f8b02181a19268958c8784e306f66853e0e09f40ae630043a3f89b699aaaaee72622d06fff43df0eab9814908b5d692f748df0c7ff5f67d4cac1b460
7
+ data.tar.gz: 7b27b83b5592b3ec556e640d7d583983ec42615ac036c40a0f5b2a305616e3df846f292aae191952e312aeaf6d9e4be99ab84ed123c1853acbf055c515b9335f
@@ -7,7 +7,7 @@ ui.h1 'NattyUI: 8-bit Color Support'
7
7
  ui.space
8
8
 
9
9
  color = ->(i) { "[bg#{i = i.to_s(16).rjust(2, '0')}] #{i} " }
10
- ui.msg 'System Colors', glyph: :point do
10
+ ui.msg 'System Colors' do
11
11
  ui.puts <<~COLORS
12
12
  [#ff]#{0.upto(7).map(&color).join}
13
13
  [#00]#{8.upto(15).map(&color).join}
@@ -15,7 +15,7 @@ ui.msg 'System Colors', glyph: :point do
15
15
  COLORS
16
16
  end
17
17
 
18
- ui.msg '6x6x6 Color Cube', glyph: :point do
18
+ ui.msg '6x6x6 Color Cube' do
19
19
  [16, 22, 28].each do |b|
20
20
  b.step(b + 185, by: 36) do |i|
21
21
  left = i.upto(i + 5).map(&color).join
@@ -26,7 +26,7 @@ ui.msg '6x6x6 Color Cube', glyph: :point do
26
26
  end
27
27
  end
28
28
 
29
- ui.msg 'Grayscale', glyph: :point do
29
+ ui.msg 'Grayscale' do
30
30
  ui.puts <<~GRAYSCALE
31
31
  [#ff]#{232.upto(243).map(&color).join}
32
32
  [#ff]#{244.upto(255).map(&color).join}
data/examples/animate.rb CHANGED
@@ -13,32 +13,32 @@ TEXT = <<~TEXT.tr("\n", ' ')
13
13
  aliquip ex ea commodo [bold]consequat[/].
14
14
  TEXT
15
15
 
16
- ui.message 'Default Animation', glyph: :point do
16
+ ui.message 'Default Animation' do
17
17
  ui.animate TEXT, animation: :default
18
18
  end
19
19
  ui.space
20
20
 
21
- ui.message 'Shiny Rainbow', glyph: :point do
21
+ ui.message 'Shiny Rainbow' do
22
22
  ui.animate TEXT, animation: :rainbow
23
23
  end
24
24
  ui.space
25
25
 
26
- ui.message 'Binary Encoded', glyph: :point do
26
+ ui.message 'Binary Encoded' do
27
27
  ui.animate TEXT, animation: :binary, style: 'green', alt_style: :bright_green
28
28
  end
29
29
  ui.space
30
30
 
31
- ui.message 'Matrix Style', glyph: :point do
31
+ ui.message 'Matrix Style' do
32
32
  ui.animate TEXT, animation: :matrix
33
33
  end
34
34
  ui.space
35
35
 
36
- ui.message 'Typewriter Like', glyph: :point do
36
+ ui.message 'Typewriter Like' do
37
37
  ui.animate TEXT, animation: :type_writer
38
38
  end
39
39
  ui.space
40
40
 
41
- ui.message 'Default Styled', glyph: :point do
41
+ ui.message 'Default Styled' do
42
42
  ui.animate TEXT, style: 'bold bright_white on_red'
43
43
  end
44
44
  ui.space
data/examples/progress.rb CHANGED
@@ -7,8 +7,13 @@ ui.h1 'NattyUI: Progress Indication'
7
7
  ui.space
8
8
 
9
9
  # just simulate some work
10
- def something = sleep(0.5)
11
- def some = sleep(0.15)
10
+ if ENV.key?('NO_WAIT')
11
+ def something = nil
12
+ def some = nil
13
+ else
14
+ def something = sleep(0.5)
15
+ def some = sleep(0.15)
16
+ end
12
17
 
13
18
  ui.info 'Tasks are sections to visualize step by step processing.' do
14
19
  ui.task 'Assemble assets' do
@@ -25,7 +30,7 @@ ui.info 'Tasks are sections to visualize step by step processing.' do
25
30
 
26
31
  ui.task 'Compile files...' do
27
32
  %w[readme.txt main.css main.html sub.html].each do |name|
28
- ui.msg "Compile file [bright_yellow]./source/#{name}[/]..."
33
+ ui.msg "Compile file [bright_yellow]./source/#{name}[/]...", glyph: :dot
29
34
  something
30
35
  end
31
36
  ui.done 'Files compiled.'
@@ -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
@@ -85,11 +85,7 @@ module NattyUI
85
85
  (wrapper.stream << @msg << Ansi::CURSOR_HIDE).flush
86
86
  @msg = "#{Ansi::CLL}#{@msg}"
87
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
88
+ @spinner = NattyUI::Spinner[spinner]
93
89
  end
94
90
 
95
91
  def redraw
@@ -162,7 +158,7 @@ module NattyUI
162
158
 
163
159
  def initialize(parent, title:, glyph:, **opts)
164
160
  color = COLORS[glyph] || COLORS[:default]
165
- glyph = NattyUI.glyph(glyph) || glyph
161
+ glyph = NattyUI::Glyph[glyph]
166
162
  prefix_width = Text.width(glyph) + 1
167
163
  parent.puts(
168
164
  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
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'text'
4
+
5
+ module NattyUI
6
+ # Helper class to select glyph types.
7
+ # @see Features#message
8
+ module Glyph
9
+ # Define glyph type used by default.
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 ? :point : value]
15
+ end
16
+
17
+ # Defined glyph 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, #to_s]
25
+ # defined type name (see {.names})
26
+ # or glyph
27
+ # @return [String] glyph definition
28
+ def self.[](name)
29
+ return @default if name == :default
30
+ Text.embellish(
31
+ if name.is_a?(Symbol)
32
+ @all[name] or raise(ArgumentError, "invalid glyph type - #{name}")
33
+ else
34
+ name.to_s
35
+ end
36
+ )
37
+ end
38
+
39
+ @all = {
40
+ completed: '[b 52]✓',
41
+ dot: '[27]•',
42
+ error: '[b d0]𝙓',
43
+ failed: '[b c4]𝑭',
44
+ information: '[b 77]𝒊',
45
+ point: '[27]◉',
46
+ query: '[b 27]▸',
47
+ task: '[b 27]➔',
48
+ warning: '[b dd]!'
49
+ }.compare_by_identity
50
+
51
+ # GLYPH = {
52
+ # default: '●',
53
+ # information: '🅸 ',
54
+ # warning: '🆆 ',
55
+ # error: '🅴 ',
56
+ # completed: '✓',
57
+ # failed: '🅵 ',
58
+ # task: '➔',
59
+ # query: '🆀 '
60
+ # }.compare_by_identity.freeze
61
+
62
+ self.default = nil
63
+ end
64
+ end
@@ -3,7 +3,10 @@
3
3
  require_relative '../natty-ui'
4
4
 
5
5
  module NattyUI
6
- Animation.defined?(:matrix)
7
- Text::EastAsianWidth[0]
6
+ Animation[nil]
7
+ Frame[:default]
8
+ Glyph[:default]
8
9
  KEY_MAP[0]
10
+ Spinner[:default]
11
+ Text.width("\u1100")
9
12
  end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ansi'
4
+
5
+ module NattyUI
6
+ # Helper class to select spinner types.
7
+ # @see Features#progress
8
+ module Spinner
9
+ class << self
10
+ # Define spinner type used by default.
11
+ # @attribute [w] self.default
12
+ # @param value [Symbol] type name
13
+ # @return [Symbol] type name
14
+ def default=(value)
15
+ @default = self[value.nil? || value == :default ? :pulse : value]
16
+ end
17
+
18
+ # Defined spinner type names.
19
+ # @see []
20
+ #
21
+ # @attribute [r] self.names
22
+ # @return [Array<Symbol>] supported attribute names
23
+ def names = @all.keys
24
+
25
+ # @param name [Symbol, #to_a, #to_s]
26
+ # defined type name (see {.names})
27
+ # or spinner elements
28
+ # @return [Enumerator] spinner definition
29
+ def [](name)
30
+ return @default if name == :default
31
+ parts =
32
+ if name.is_a?(Symbol)
33
+ @all[name] or raise(ArgumentError, "invalid spinner type - #{name}")
34
+ else
35
+ name
36
+ end
37
+ parts =
38
+ (parts.respond_to?(:map) ? parts : parts.to_s.chars).map do |part|
39
+ "#{@style}#{part}"
40
+ end
41
+ raise(ArgumentError, "invalid spinner type - #{name}") if parts.empty?
42
+ parts = parts.zip(parts).flatten(1) while parts.size < 6
43
+ Enumerator.new { |y| parts.each { y << _1 } while true }
44
+ end
45
+
46
+ private
47
+
48
+ def slide(a, b, size, prefix = nil, suffix = prefix)
49
+ Enumerator.new do |y|
50
+ fn =
51
+ lambda do |i|
52
+ y << "#{prefix}#{a * (i += 1)}#{b * (size - i)}#{suffix}"
53
+ end
54
+ size.times(&fn)
55
+ a, b = b, a
56
+ size.times(&fn)
57
+ end
58
+ end
59
+
60
+ def bounce(a, b, size, prefix = nil, suffix = prefix)
61
+ Enumerator.new do |y|
62
+ fn =
63
+ lambda do |i|
64
+ y << "#{prefix}#{a * (i += 1)}#{b * (size - i)}#{suffix}"
65
+ end
66
+ size.times(&fn)
67
+ a, b = b, a
68
+ (size - 1).times(&fn)
69
+ fn = ->(i) { y << "#{prefix}#{a * i}#{b * (size - i)}#{suffix}" }
70
+ (size - 2).downto(0, &fn)
71
+ a, b = b, a
72
+ (size - 1).downto(0, &fn)
73
+ end
74
+ end
75
+
76
+ def move(a, b, size, prefix = nil, suffix = prefix)
77
+ Enumerator.new do |y|
78
+ size.times do |i|
79
+ y << "#{prefix}#{b * i}#{a}#{b * (size - i - 1)}#{suffix}"
80
+ end
81
+ y << "#{prefix}#{b * size}#{suffix}"
82
+ end
83
+ end
84
+ end
85
+
86
+ @style = Ansi[:bold, 220]
87
+ @all = {
88
+ bar: '▁▂▃▄▅▆▇█▇▆▅▄▃▂',
89
+ blink: '■□▪▫',
90
+ blocks: '▖▘▝▗',
91
+ bounce: bounce('◼︎', '◻︎', 7),
92
+ bounce2: bounce('▰', '▱', 7),
93
+ bounce3: bounce('● ', '◌ ', 7),
94
+ bounce4: bounce('=', ' ', 5, '[', ']'),
95
+ circle: '◐◓◑◒',
96
+ colors: '🟨🟨🟧🟧🟥🟥🟦🟦🟪🟪🟩🟩',
97
+ dots: '⣷⣯⣟⡿⢿⣻⣽⣾',
98
+ dots2: '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏',
99
+ dots3: '⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓',
100
+ dots4: '⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆',
101
+ dots5: '⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋',
102
+ move: move('◼︎', '◻︎', 7),
103
+ move2: move('▰', '▱', 7),
104
+ move3: move('● ', '◌ ', 7),
105
+ move4: move('=', ' ', 5, '[', ']'),
106
+ pulse: '•✺◉●◉✺',
107
+ slide: slide('◼︎', '◻︎', 7),
108
+ slide2: slide('▰', '▱', 7),
109
+ slide3: slide('● ', '◌ ', 7),
110
+ slide4: slide('=', ' ', 5, '[', ']'),
111
+ slide5: slide('.', ' ', 3),
112
+ snake: '⠁⠉⠙⠸⢰⣠⣄⡆⠇⠃',
113
+ stod: '⡿⣟⣯⣷⣾⣽⣻⢿',
114
+ swap: '㊂㊀㊁',
115
+ vintage: '-\\|/'
116
+ }.compare_by_identity
117
+
118
+ self.default = nil
119
+ end
120
+ end