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.
@@ -7,24 +7,12 @@ module NattyUI
7
7
  # Creates a default section and prints given arguments as lines
8
8
  # into the section.
9
9
  #
10
- # @param [Array<#to_s>] args objects to print
10
+ # @param [Array<#to_s>] args optional objects to print
11
11
  # @yieldparam [Wrapper::Section] section the created section
12
12
  # @return [Object] the result of the code block
13
13
  # @return [Wrapper::Section] itself, when no code block is given
14
- def section(*args, &block)
15
- _section(self, :Section, args, prefix: ' ', suffix: ' ', &block)
16
- end
14
+ def section(*args, &block) = _section(:Section, args, prefix: ' ', &block)
17
15
  alias sec section
18
-
19
- # Creates a quotation section and prints given arguments as lines
20
- # into the section.
21
- #
22
- # @param (see #section)
23
- # @yieldparam (see #section)
24
- # @return (see #section)
25
- def quote(*args, &block)
26
- _section(self, :Section, args, prefix: '▍ ', prefix_attr: 39, &block)
27
- end
28
16
  end
29
17
 
30
18
  class Wrapper
@@ -34,47 +22,53 @@ module NattyUI
34
22
  # A section can contain other elements and sections.
35
23
  #
36
24
  # @see Features#section
37
- # @see Features#quote
38
25
  class Section < Element
39
- # Close the section.
40
- #
41
- # @return [Section] itself
42
- def close = _close(:closed)
26
+ # @return [Integer] available columns count within the section
27
+ def available_width
28
+ @available_width ||=
29
+ @parent.available_width - @prefix_width - @suffix_width
30
+ end
43
31
 
44
- # Print given arguments as lines into the section.
45
- # Optionally limit the line width to given `max_width`.
32
+ # Print given arguments line-wise into the section.
46
33
  #
47
- # @overload puts(..., max_width: nil)
34
+ # @overload puts(...)
48
35
  # @param [#to_s] ... objects to print
49
- # @param [Integer, nil] max_width maximum line width
50
- # @comment @param [#to_s, nil] prefix line prefix
51
- # @comment @param [#to_s, nil] suffix line suffix
52
36
  # @return [Section] itself
53
- def puts(*args, max_width: nil, prefix: nil, suffix: nil)
37
+ def puts(*args, **kwargs)
54
38
  return self if @status
55
39
  @parent.puts(
56
40
  *args,
57
- max_width: max_width,
58
- prefix: prefix ? "#{@prefix}#{prefix}" : @prefix,
59
- suffix: suffix ? "#{suffix}#{@suffix}" : @suffix
41
+ prefix: "#{@prefix}#{kwargs[:prefix]}",
42
+ prefix_width: @prefix_width + kwargs[:prefix_width].to_i,
43
+ suffix: "#{kwargs[:suffix]}#{@suffix}",
44
+ suffix_width: @suffix_width + kwargs[:suffix_width].to_i
60
45
  )
61
46
  self
62
47
  end
63
- alias add puts
64
48
 
65
- # Add at least one empty line
49
+ # Print given arguments into the section.
66
50
  #
67
- # @param [#to_i] lines count of lines
68
- # @return [Section] itself
69
- def space(lines = 1)
70
- @parent.puts(
71
- "\n" * [lines.to_i, 1].max,
72
- prefix: @prefix,
73
- suffix: @suffix
51
+ # @overload print(...)
52
+ # @param [#to_s] ... objects to print
53
+ # @return [Section] itself
54
+ def print(*args, **kwargs)
55
+ return self if @status
56
+ @parent.print(
57
+ *args,
58
+ prefix: "#{@prefix}#{kwargs[:prefix]}",
59
+ prefix_width: @prefix_width + kwargs[:prefix_width].to_i,
60
+ suffix: "#{kwargs[:suffix]}#{@suffix}",
61
+ suffix_width: @suffix_width + kwargs[:suffix_width].to_i
74
62
  )
75
63
  self
76
64
  end
77
65
 
66
+ # Add at least one empty line
67
+ #
68
+ # @param [#to_i] lines count of lines
69
+ # @return [Section] itself
70
+ def space(lines = 1) = puts("\n" * [1, lines.to_i].max)
71
+
78
72
  # @note The screen manipulation is only available in ANSI mode see {#ansi?}
79
73
  #
80
74
  # Resets the part of the screen written below the current output line when
@@ -90,12 +84,20 @@ module NattyUI
90
84
  # @return [Object] block result
91
85
  def temporary = block_given? ? yield(self) : self
92
86
 
87
+ # @!visibility private
88
+ def inspect = @status ? "#{_to_s[..-2]} status=#{@status}>" : _to_s
89
+
93
90
  protected
94
91
 
95
- def initialize(parent, prefix: nil, suffix: nil, **_)
92
+ def initialize(
93
+ parent,
94
+ prefix:,
95
+ prefix_width: NattyUI.display_width(prefix)
96
+ )
96
97
  super(parent)
97
98
  @prefix = prefix
98
- @suffix = suffix
99
+ @prefix_width = prefix_width
100
+ @suffix_width = 0
99
101
  end
100
102
  end
101
103
  end
@@ -0,0 +1,298 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'element'
3
+
4
+ module NattyUI
5
+ module Features
6
+ #
7
+ # Table view of data.
8
+ #
9
+ # @note Tables do not support text attributes yet and are still under
10
+ # construction. This means table features are not complete defined and
11
+ # may change in near future.
12
+ #
13
+ # @overload table(type: simple)
14
+ # Construct and display a table.
15
+ #
16
+ # @param [Symbol] type frame type;
17
+ # valid types are `:simple`, `:heavy`, `:semi`, `:double`
18
+ # @yieldparam [Table] table construction helper
19
+ # @return [Wrapper::Section, Wrapper] it's parent object
20
+ #
21
+ # @example
22
+ # ui.table do |table|
23
+ # table.add('name', 'price', 'origin')
24
+ # table.add('apple', '1$', 'California')
25
+ # table.add('banana', '2$', 'Brasil')
26
+ # table.add('kiwi', '1.5$', 'Newzeeland')
27
+ # end
28
+ #
29
+ # # output:
30
+ # # name │ price │ origin
31
+ # # ───────┼───────┼───────────
32
+ # # apple │ 1$ │ California
33
+ # # ───────┼───────┼───────────
34
+ # # banana │ 2$ │ Brasil
35
+ # # ───────┼───────┼───────────
36
+ # # kiwi │ 1.5$ │ Newzeeland
37
+ #
38
+ # @overload table(*args, type: simple)
39
+ # Display the given arrays as rows of a table.
40
+ #
41
+ # @param [Array<#to_s>] args one or more arrays representing rows of the table
42
+ # @param [Symbol] type frame type;
43
+ # valid types are `:simple`, `:heavy`, `:semi`, `:double`
44
+ # @return [Wrapper::Section, Wrapper] it's parent object
45
+ #
46
+ # @example
47
+ # ui.table(
48
+ # %w[name price origin],
49
+ # %w[apple 1$ California],
50
+ # %w[banana 2$ Brasil],
51
+ # %w[kiwi 1.5$ Newzeeland]
52
+ # )
53
+ def table(*table, type: :simple)
54
+ table = Table.new(*table)
55
+ yield(table) if block_given?
56
+ _element(:Table, table.rows, type)
57
+ end
58
+
59
+ #
60
+ # Table-like display of key/value pairs.
61
+ #
62
+ # @param [#to_s] seperator
63
+ # @param [Hash<#to_s,#to_s>] kwargs
64
+ # @return [Wrapper::Section, Wrapper] it's parent object
65
+ #
66
+ # @example
67
+ # ui.pairs(apple: '1$', banana: '2$', kiwi: '1.5$')
68
+ #
69
+ # # output:
70
+ # # apple: 1$
71
+ # # banana: 2$
72
+ # # kiwi: 1.5$
73
+ #
74
+ def pairs(seperator = ': ', **kwargs)
75
+ _element(:Pairs, Table.new(**kwargs).rows, seperator)
76
+ end
77
+
78
+ class Table
79
+ attr_reader :rows
80
+
81
+ def add_row(*columns)
82
+ @rows << columns
83
+ self
84
+ end
85
+ alias add add_row
86
+
87
+ def add_col(*columns)
88
+ columns.each_with_index do |col, row_idx|
89
+ (@rows[row_idx] ||= []) << col
90
+ end
91
+ self
92
+ end
93
+
94
+ def initialize(*args, **kwargs)
95
+ @rows = []
96
+ args.each { add_row(*_1) }
97
+ kwargs.each_pair { add_row(*_1) }
98
+ end
99
+ end
100
+ private_constant :Table
101
+ end
102
+
103
+ class Wrapper
104
+ # An {Element} to print a table.
105
+ #
106
+ # @see Features#table
107
+ class Table < Element
108
+ protected
109
+
110
+ def call(rows, type)
111
+ TableGenerator.each_line(
112
+ rows,
113
+ @parent.available_width - 1,
114
+ ORNAMENTS[type] ||
115
+ raise(ArgumentError, "invalid table type - #{type.inspect}"),
116
+ Ansi[39],
117
+ Ansi::RESET
118
+ ) { |line| @parent.puts(line) }
119
+ @parent
120
+ end
121
+
122
+ def coloring = [nil, nil]
123
+
124
+ ORNAMENTS = {
125
+ rounded: '│─┼',
126
+ simple: '│─┼',
127
+ heavy: '┃━╋',
128
+ double: '║═╬',
129
+ semi: '║╴╫'
130
+ }.compare_by_identity.freeze
131
+ end
132
+
133
+ # An {Element} to print key/value pairs.
134
+ #
135
+ # @see Features#pairs
136
+ class Pairs < Element
137
+ protected
138
+
139
+ def call(rows, seperator)
140
+ TableGenerator.each_simple_line(
141
+ rows,
142
+ @parent.available_width - 1,
143
+ seperator,
144
+ NattyUI.plain(seperator, ansi: false)[-1] == ' '
145
+ ) { |line| @parent.puts(line) }
146
+ @parent
147
+ end
148
+ end
149
+
150
+ class TableGenerator
151
+ def self.each_line(rows, max_width, ornament, opref, osuff)
152
+ return if rows.empty?
153
+ gen = new(rows, max_width, 3)
154
+ return unless gen.ok?
155
+ last_row = 0
156
+ col_div = " #{opref}#{ornament[0]}#{osuff} "
157
+ row_div = "#{ornament[1]}#{ornament[2]}#{ornament[1]}"
158
+ row_div =
159
+ "#{opref}#{gen.widths.map { ornament[1] * _1 }.join(row_div)}#{osuff}"
160
+ gen.each do |line, number|
161
+ if last_row != number
162
+ last_row = number
163
+ yield(row_div)
164
+ end
165
+ yield(line.join(col_div))
166
+ end
167
+ end
168
+
169
+ def self.each_simple_line(rows, max_width, col_div, first_right)
170
+ return if rows.empty?
171
+ gen = new(rows, max_width, NattyUI.display_width(col_div))
172
+ return unless gen.ok?
173
+ gen.aligns[0] = :right if first_right
174
+ gen.each { yield(_1.join(col_div)) }
175
+ end
176
+
177
+ attr_reader :widths, :aligns
178
+
179
+ def initialize(rows, max_width, col_div_size)
180
+ @rows =
181
+ rows.map do |row|
182
+ row.map do |col|
183
+ col = NattyUI.embellish(col).each_line(chomp: true).to_a
184
+ col.empty? ? col << '' : col
185
+ end
186
+ end
187
+ @max_width = max_width
188
+ @col_div_size = col_div_size
189
+ @widths = create_widths.freeze
190
+ @aligns = Array.new(@widths.size, :left)
191
+ end
192
+
193
+ def ok? = (@widths != nil)
194
+
195
+ def each
196
+ return unless @widths
197
+ col_empty = @widths.map { ' ' * _1 }
198
+ @rows.each_with_index do |row, row_idx|
199
+ row
200
+ .max_by(&:size)
201
+ .size
202
+ .times do |line_nr|
203
+ col_idx = -1
204
+ yield(
205
+ @widths.map do |col_width|
206
+ cell = row[col_idx += 1] or next col_empty[col_idx]
207
+ next col_empty[col_idx] if (line = cell[line_nr]).nil?
208
+ align(line.to_s, col_width, @aligns[col_idx])
209
+ end,
210
+ row_idx
211
+ )
212
+ end
213
+ end
214
+ end
215
+
216
+ private
217
+
218
+ def align(str, width, alignment)
219
+ return str unless (width -= NattyUI.display_width(str)).positive?
220
+ return str << (' ' * width) if alignment == :left
221
+ (' ' * width) << str
222
+ end
223
+
224
+ def create_widths
225
+ matrix = create_matrix
226
+ col_widths = find_col_widths(matrix)
227
+ adjusted = adjusted_widths(col_widths)
228
+ return if adjusted.empty? # nothing to draw
229
+ return adjusted if col_widths == adjusted # all fine
230
+ if (size = adjusted.size) != col_widths.size
231
+ @rows.map! { _1.take(size) }
232
+ matrix.map! { _1.take(size) }
233
+ col_widths = col_widths.take(size)
234
+ end
235
+ diff = diff(col_widths, adjusted)
236
+ @rows.each_with_index do |row, row_idx|
237
+ diff.each do |col_idx|
238
+ adjust_to = adjusted[col_idx]
239
+ next if matrix[row_idx][col_idx] <= adjust_to
240
+ ary = NattyUI.each_line(*row[col_idx], max_width: adjust_to).to_a
241
+ ary.pop if ary.last.empty?
242
+ row[col_idx] = ary
243
+ end
244
+ end
245
+ adjusted
246
+ end
247
+
248
+ def create_matrix
249
+ ret =
250
+ @rows.map do |row|
251
+ row.map { |col| col.map { NattyUI.display_width(_1) }.max }
252
+ end
253
+ cc = ret.max_by(&:size).size
254
+ ret.each { (add = cc - _1.size).nonzero? and _1.fill(0, _1.size, add) }
255
+ end
256
+
257
+ def find_col_widths(matrix)
258
+ ret = nil
259
+ matrix.each do |row|
260
+ next ret = row.dup unless ret
261
+ row.each_with_index do |size, idx|
262
+ hs = ret[idx]
263
+ ret[idx] = size if hs < size
264
+ end
265
+ end
266
+ ret
267
+ end
268
+
269
+ def adjusted_widths(col_widths)
270
+ ret = col_widths.dup
271
+ if ret.sum <=
272
+ (left = @max_width - (@col_div_size * (col_widths.size - 1)))
273
+ return ret
274
+ end
275
+ indexed = ret.each_with_index.to_a
276
+ # TODO: optimize this!
277
+ until ret.sum <= left
278
+ indexed.sort! { |b, a| (a[0] <=> b[0]).nonzero? || (a[1] <=> b[1]) }
279
+ pair = indexed[0]
280
+ next ret[pair[1]] = pair[0] if (pair[0] -= 1).nonzero?
281
+ indexed.shift
282
+ return [] if indexed.empty?
283
+ ret.pop
284
+ end
285
+ ret
286
+ end
287
+
288
+ def diff(col_widths, adjusted)
289
+ ret = []
290
+ col_widths.each_with_index do |val, idx|
291
+ ret << idx if val != adjusted[idx]
292
+ end
293
+ ret
294
+ end
295
+ end
296
+ private_constant :TableGenerator
297
+ end
298
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'section'
4
- require_relative '../mixins'
4
+ require_relative 'mixins'
5
5
 
6
6
  module NattyUI
7
7
  module Features
@@ -15,31 +15,28 @@ module NattyUI
15
15
  # @return [Object] the result of the code block
16
16
  # @return [Wrapper::Task] itself, when no code block is given
17
17
  def task(title, *args, &block)
18
- _section(self, :Task, args, title: title, &block)
18
+ _section(:Task, args, title: title, &block)
19
19
  end
20
20
  end
21
21
 
22
22
  module TaskMethods
23
23
  protected
24
24
 
25
- def initialize(parent, title:, **opts)
26
- @parent = parent
27
- @temp = wrapper.temporary
25
+ def initialize(parent, title:)
26
+ @temp = parent.wrapper.temporary
28
27
  @final_text = [title]
29
- super(parent, title: title, symbol: :task, **opts)
28
+ super(parent, title: title, glyph: :task)
30
29
  end
31
30
 
32
31
  def finish
33
- unless failed?
34
- @status = :completed if @status == :closed
35
- @temp.call
36
- end
32
+ return @parent.failed(*@final_text) if failed?
33
+ @temp.call
37
34
  _section(
38
- @parent,
39
35
  :Message,
40
36
  @final_text,
37
+ owner: @parent,
41
38
  title: @final_text.shift,
42
- symbol: @status
39
+ glyph: @status = :completed
43
40
  )
44
41
  end
45
42
  end
@@ -1,15 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'io/console'
4
+ require_relative 'ansi'
4
5
  require_relative 'wrapper/ask'
5
6
  require_relative 'wrapper/framed'
6
7
  require_relative 'wrapper/heading'
8
+ require_relative 'wrapper/horizontal_rule'
7
9
  require_relative 'wrapper/list_in_columns'
8
10
  require_relative 'wrapper/message'
9
11
  require_relative 'wrapper/progress'
10
12
  require_relative 'wrapper/query'
13
+ require_relative 'wrapper/quote'
11
14
  require_relative 'wrapper/request'
12
15
  require_relative 'wrapper/section'
16
+ require_relative 'wrapper/table'
13
17
  require_relative 'wrapper/task'
14
18
 
15
19
  module NattyUI
@@ -28,61 +32,60 @@ module NattyUI
28
32
 
29
33
  # @attribute [r] screen_size
30
34
  # @return [[Integer, Integer]] screen size as rows and columns
31
- def screen_size
32
- return @stream.winsize if @ws
33
- [ENV['LINES'].to_i.nonzero? || 24, ENV['COLUMNS'].to_i.nonzero? || 80]
34
- end
35
+ def screen_size = (@screen_size ||= determine_screen_size)
35
36
 
36
37
  # @attribute [r] screen_rows
37
38
  # @return [Integer] number of screen rows
38
- def screen_rows
39
- @ws ? @stream.winsize[0] : (ENV['LINES'].to_i.nonzero? || 24)
40
- end
39
+ def screen_rows = screen_size[0]
41
40
 
42
41
  # @attribute [r] screen_columns
43
42
  # @return [Integer] number of screen columns
44
- def screen_columns
45
- @ws ? @stream.winsize[-1] : (ENV['COLUMNS'].to_i.nonzero? || 80)
46
- end
43
+ def screen_columns = screen_size[1]
47
44
 
48
45
  # @!group Tool functions
49
46
 
50
- # Print given arguments as lines to the output stream.
51
- # Optionally limit the line width to given `max_width`.
47
+ # Print given arguments line-wise to the output stream.
52
48
  #
53
- # @overload puts(..., max_width: nil)
49
+ # @overload puts(...)
54
50
  # @param [#to_s] ... objects to print
55
- # @param [Integer, nil] max_width maximum line width
56
- # @comment @param [#to_s, nil] prefix line prefix
57
- # @comment @param [#to_s, nil] suffix line suffix
58
51
  # @return [Wrapper] itself
59
- def puts(*args, max_width: nil, prefix: nil, suffix: nil)
60
- if args.empty?
61
- @stream.puts(embellish("#{prefix}#{suffix}"))
62
- @lines_written += 1
63
- else
64
- NattyUI.each_line(*args, max_width: max_width) do |line|
65
- @stream.puts(embellish("#{prefix}#{line}#{suffix}"))
66
- @lines_written += 1
67
- end
68
- end
52
+ def puts(*args, **kwargs)
53
+ args = prepare_print(args, kwargs)
54
+ @lines_written += args.size
55
+ @stream.puts(args)
56
+ @stream.flush
57
+ self
58
+ end
59
+
60
+ # Print given arguments to the output stream.
61
+ #
62
+ # @overload print(...)
63
+ # @param [#to_s] ... objects to print
64
+ # @return [Wrapper] itself
65
+ def print(*args, **kwargs)
66
+ args = prepare_print(args, kwargs).to_a
67
+ @lines_written += args.size - 1
68
+ @stream.print(args.join("\n"))
69
69
  @stream.flush
70
70
  self
71
71
  end
72
- alias add puts
73
72
 
74
73
  # Add at least one empty line
75
74
  #
76
75
  # @param [#to_i] lines count of lines
77
76
  # @return [Wrapper] itself
78
77
  def space(lines = 1)
79
- lines = [lines.to_i, 1].max
80
- @stream << ("\n" * lines)
78
+ lines = [1, lines.to_i].max
79
+ (@stream << ("\n" * lines)).flush
81
80
  @lines_written += lines
82
- @stream.flush
83
81
  self
84
82
  end
85
83
 
84
+ # Clear Screen
85
+ #
86
+ # @return [Wrapper] itself
87
+ def cls = self
88
+
86
89
  # @note The screen manipulation is only available in ANSI mode see {#ansi?}
87
90
  #
88
91
  # Saves current screen, deletes all screen content and moves the cursor
@@ -137,11 +140,47 @@ module NattyUI
137
140
  # @!visibility private
138
141
  alias inspect to_s
139
142
 
143
+ # @attribute [r] wrapper
144
+ # @return [Wrapper] self
145
+ alias wrapper itself
146
+
147
+ # @!visibility private
148
+ alias available_width screen_columns
149
+
150
+ # @!visibility private
151
+ def prefix = ''
152
+
153
+ # @return [Array<Symbol>] available glyph names
154
+ def glyph_names = GLYPHS.keys
155
+
156
+ #
157
+ # Get a pre-defined glyph
158
+ #
159
+ # @param [Symbol] name glyph name
160
+ # @return [String] the named glyph
161
+ # @return [nil] when glyph is not defined
162
+ def glyph(name) = GLYPHS[name]
163
+
140
164
  protected
141
165
 
142
- def embellish(obj)
143
- obj = NattyUI.plain(obj)
144
- obj.empty? ? nil : obj
166
+ def prepare_print(args, kwargs)
167
+ prefix = kwargs[:prefix] and prefix = NattyUI.plain(prefix, ansi: false)
168
+ suffix = kwargs[:suffix] and suffix = NattyUI.plain(suffix, ansi: false)
169
+ return ["#{prefix}#{suffix}"] if args.empty?
170
+ NattyUI
171
+ .each_line(
172
+ *args.map! { NattyUI.plain(_1, ansi: false) },
173
+ max_width: max_with(prefix, suffix, kwargs)
174
+ )
175
+ .map { "#{prefix}#{_1}#{suffix}" }
176
+ end
177
+
178
+ def max_with(prefix, suffix, kwargs)
179
+ mw = kwargs[:max_width] and return mw
180
+ mw = screen_columns
181
+ mw -= kwargs[:prefix_width] || NattyUI.display_width(prefix) if prefix
182
+ mw -= kwargs[:suffix_width] || NattyUI.display_width(suffix) if suffix
183
+ mw
145
184
  end
146
185
 
147
186
  def temp_func
@@ -154,21 +193,55 @@ module NattyUI
154
193
  def initialize(stream)
155
194
  @stream = stream
156
195
  @lines_written = 0
157
- @ws = stream.respond_to?(:winsize) && stream.winsize&.all?(&:positive?)
158
- rescue Errno::ENOTTY
159
- @ws = false
160
196
  end
161
197
 
162
- def wrapper = self
163
- def prefix = nil
164
- alias suffix prefix
198
+ private_class_method :new
165
199
 
166
- def prefix_width = 0
167
- alias suffix_width prefix_width
168
- alias width prefix_width
200
+ private
169
201
 
170
- alias available_width screen_columns
202
+ def determine_screen_size
203
+ return @stream.winsize if @ws
204
+ if @ws.nil?
205
+ ret = try_fetch_winsize
206
+ if ret
207
+ @ws = true
208
+ Signal.trap('WINCH') { @screen_size = nil }
209
+ return ret
210
+ end
211
+ @ws = false
212
+ end
213
+ [ENV['LINES'].to_i.nonzero? || 24, ENV['COLUMNS'].to_i.nonzero? || 80]
214
+ end
171
215
 
172
- private_class_method :new
216
+ def try_fetch_winsize
217
+ return unless @stream.respond_to?(:winsize)
218
+ ret = @stream.winsize
219
+ ret&.all?(&:positive?) ? ret : nil
220
+ rescue SystemCallError
221
+ nil
222
+ end
223
+
224
+ GLYPHS = {
225
+ default: "#{Ansi[:bold, 255]}•#{Ansi::RESET}",
226
+ information: "#{Ansi[:bold, 119]}𝒊#{Ansi::RESET}",
227
+ warning: "#{Ansi[:bold, 221]}!#{Ansi::RESET}",
228
+ error: "#{Ansi[:bold, 208]}𝙓#{Ansi::RESET}",
229
+ completed: "#{Ansi[:bold, 82]}✓#{Ansi::RESET}",
230
+ failed: "#{Ansi[:bold, 196]}𝑭#{Ansi::RESET}",
231
+ task: "#{Ansi[:bold, 39]}➔#{Ansi::RESET}",
232
+ query: "#{Ansi[:bold, 39]}▸#{Ansi::RESET}"
233
+ }.compare_by_identity.freeze
234
+
235
+ # GLYPHS = {
236
+ # default: '●',
237
+ # information: '🅸 ',
238
+ # warning: '🆆 ',
239
+ # error: '🅴 ',
240
+ # completed: '✓',
241
+ # failed: '🅵 ',
242
+ # task: '➔',
243
+ # query: '🆀 '
244
+ # }.compare_by_identity.freeze
245
+ private_constant :GLYPHS
173
246
  end
174
247
  end