natty-ui 0.27.0 → 0.29.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: 43f1afe6be5864d4895c974783fbfcff1f4b5a23f963eb24f6a964fe09b1174c
4
- data.tar.gz: e3a4c8e1981f0299f9927c4a3f53fa0c4eca95f792f9590c9ea191e7018adcb5
3
+ metadata.gz: 3d1b81e5e7afebe8166a6532c00df911d53b189f6eb4b282e828492b0d4a123f
4
+ data.tar.gz: ef24f92d9c696f966e6dbe3fdcb7eba55c649099551b50dcb83922f1702a1d2a
5
5
  SHA512:
6
- metadata.gz: d9c75d24c0363076c3e0d41ac458d4f13a6552811d166028d5d758ba408d20aa63907a471ee56c4fe4b0638db1cb03e915d0b6c606e8770a9753d59eafb7c951
7
- data.tar.gz: 77a95400ba528d57f3e1b559ac1ffa584c68a60bcc45d212341bc803031f204abac44e269db1d81903a4629b7c9c466c27acae66d84c2f802a3486bab37a929b
6
+ metadata.gz: 610d16c334a76042430e2cf9ff0ae876347ecb24417134adbda55dae569871b7e1e91408bab79770ba3da8ed9379dcf3834bc54aa6673d5081c376cc3c58778d
7
+ data.tar.gz: 024bc0a945ca27ec2379b7170343e40e23d555c65780b766c30751bc8c4e093766e79081bb6a5aae93cc3be8c9f8c474ca03b84fe1b5e4fa6307858d816a13bd
@@ -6,13 +6,13 @@ ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]8bit Color Support[/]' do
6
6
  color = ->(i) { "[bg#{i = i.to_s(16).rjust(2, '0')}] #{i} " }
7
7
 
8
8
  ui.space
9
- ui.message('System Colors', <<~COLORS.chomp)
9
+ ui.message 'System Colors', <<~COLORS.chomp
10
10
  [#ff]#{0.upto(7).map(&color).join}
11
11
  [#00]#{8.upto(15).map(&color).join}
12
12
  COLORS
13
13
 
14
14
  ui.space
15
- ui.message('Grayscale', <<~GRAYSCALE.chomp)
15
+ ui.message 'Grayscale', <<~GRAYSCALE.chomp
16
16
  [#ff]#{0xe8.upto(0xf3).map(&color).join}
17
17
  [#ff]#{0xf4.upto(0xff).map(&color).join}
18
18
  GRAYSCALE
data/examples/elements.rb CHANGED
@@ -4,16 +4,16 @@ require_relative '../lib/natty-ui'
4
4
 
5
5
  ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Simple Elements[/]' do
6
6
  ui.space
7
- ui.h1('This is a [b]H1[/b] heading element')
7
+ ui.h1 'This is a [b]H1[/b] heading element'
8
8
 
9
9
  ui.space
10
- ui.h2('This is a [b]H2[/b] heading element')
10
+ ui.h2 'This is a [b]H2[/b] heading element'
11
11
 
12
12
  ui.space
13
13
  ui.quote "This is a\nmulti-line quotation"
14
14
 
15
15
  ui.space
16
- ui.h3('This is a [b]H3[/b] heading element')
16
+ ui.h3 'This is a [b]H3[/b] heading element'
17
17
  ui.mark(
18
18
  'This is a multi-line message',
19
19
  'with a leading checkmark.',
@@ -21,11 +21,11 @@ ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Simple Elements[/]' do
21
21
  )
22
22
 
23
23
  ui.space
24
- ui.h4('This is a [b]H4[/b] heading element')
24
+ ui.h4 'This is a [b]H4[/b] heading element'
25
25
 
26
26
  ui.space
27
- ui.h5('This is a [b]H5[/b] heading element')
27
+ ui.h5 'This is a [b]H5[/b] heading element'
28
28
 
29
29
  ui.space
30
- ui.h6('This is a [b]H6[/b] heading element')
30
+ ui.h6 'This is a [b]H6[/b] heading element'
31
31
  end
data/examples/examples.rb CHANGED
@@ -13,17 +13,18 @@ EXAMPLES = {
13
13
  'ls' => 'Print Lists',
14
14
  'tables' => 'Print Tables',
15
15
  'cols' => 'Print Columns',
16
+ 'vbars' => 'Print Vertical Bars',
17
+ 'hbars' => 'Print Horizontal Bars',
16
18
  'sections' => 'Sections',
17
- 'tasks' => 'Tasks'
19
+ 'tasks' => 'Tasks',
20
+ 'options' => 'Options and Selections'
18
21
  }.freeze
19
22
 
20
- DEFAULT_MODE = NattyUI.input_mode == :default
21
-
22
23
  ui.space
23
24
 
24
25
  while true
25
26
  selected =
26
- ui.choice(**EXAMPLES, abortable: true) do
27
+ ui.choice(**EXAMPLES, abortable: true, selected: selected) do
27
28
  ui.cols(
28
29
  "[red] /\\_/\\\n( o.o )\n > ^ <",
29
30
  '[bright_green b]Select a natty example:',
@@ -32,12 +33,12 @@ while true
32
33
  ui.div('[faint](Abort with [\\ESC])', padding: [1, 0, 1])
33
34
  end
34
35
 
35
- ui.space unless DEFAULT_MODE
36
+ ui.space unless Terminal.ansi?
36
37
  break unless selected
37
38
 
38
39
  ui.temporary do
39
40
  load("#{__dir__}/#{selected}.rb")
40
- if DEFAULT_MODE
41
+ if Terminal.ansi?
41
42
  ui.await { ui.puts '[faint][\\Press ENTER to continue...]' }
42
43
  else
43
44
  ui.space
data/examples/hbars.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/natty-ui'
4
+
5
+ ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Print Horizontal Bars[/]' do
6
+ values = [11.97, 14.35, 15.51, 12.39, 14.3, 10.6, 17.7].freeze
7
+
8
+ ui.space
9
+ ui.hbars values, style: :blue
10
+ ui.puts 'NattyUI can quick dump values as horizontal bars.'
11
+
12
+ ui.space
13
+ ui.hbars values, style: :green, normalize: true, width: 0.5
14
+ ui.puts(
15
+ 'These are the same values but [i]normalized[/i] ' \
16
+ 'and printed in half width.'
17
+ )
18
+ end
@@ -39,7 +39,7 @@ ui.message '[b]​ᓚᕠᗢ NattyUI[/b]' do
39
39
  table.add do |row|
40
40
  row.add 'Layout'
41
41
  row.add <<~TEXT.chomp
42
- 🎩 heading elements     📝 messages
42
+ 🎩 heading elements     📝 messages    📊 bar graphs
43
43
  📏 horizontal rulers    [blue]┼┼[/] tables
44
44
  📋 lists                [b green]✓✓[/] tasks
45
45
  TEXT
data/examples/info.rb CHANGED
@@ -2,29 +2,30 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
+ def colors
6
+ return Terminal.colors.to_s if Terminal.colors < 8
7
+ colors = [
8
+ Terminal.true_color? ? 'true color' : Terminal.colors,
9
+ "#{(0..15).map { "[#{_1.to_s(16).rjust(2, '0')}]██" }.join}[/]"
10
+ ]
11
+ if Terminal.true_color?
12
+ colors << Terminal::Ansi.rainbow('████████████████████████████████')
13
+ end
14
+ colors.join("\n")
15
+ end
16
+
5
17
  ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Terminal Information[/]' do
6
18
  ui.space
7
19
  ui.table do |table|
8
- table.add('Identifier', Terminal.application || 'unidentified')
9
- table.add('ANSI support', Terminal.ansi? ? 'yes' : 'no')
10
- table.add('Input mode', Terminal.input_mode)
11
- table.add(
12
- 'Colors',
13
- "#{Terminal.true_color? ? 'true color' : Terminal.colors}
14
- [black]██[red]██[green]██[yellow]██[blue]██[magenta]██[cyan]██[white]██" \
15
- '[bright_black]██[bright_red]██[bright_green]██[bright_yellow]██' \
16
- '[bright_blue]██[bright_magenta]██[bright_cyan]██[bright_white]██[/]' \
17
- "#{
18
- if Terminal.true_color?
19
- Terminal::Ansi.rainbow("\n████████████████████████████████")
20
- end
21
- }"
22
- )
23
- table.add('Screen size', Terminal.size.join(' x '))
20
+ table.add 'Identifier', Terminal.application || 'unidentified'
21
+ table.add 'ANSI support', Terminal.ansi? ? 'yes' : 'no'
22
+ table.add 'Input mode', Terminal.input_mode
23
+ table.add 'Colors', colors
24
+ table.add 'Screen size', Terminal.size.join(' x ')
24
25
  fc = table.columns[0]
25
- fc.width = 13
26
- fc.padding_right = 1
26
+ fc.width = 14
27
+ fc.padding_right = 2
27
28
  fc.align = :right
28
- table.columns[1].style = :bold
29
+ table.columns[1].style = %i[bold bright_yellow]
29
30
  end
30
31
  end
@@ -2,27 +2,29 @@
2
2
 
3
3
  require_relative '../lib/natty-ui'
4
4
 
5
- raw = name = :start
6
- while name != 'Esc'
5
+ event = nil
6
+ while true
7
7
  ui.temporary do
8
8
  ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Keyboard Key Codes[/]' do
9
9
  ui.puts(
10
- "\n#{
11
- case name
12
- when :start
13
- "Your terminal uses [i]#{
14
- Terminal.input_mode
15
- }[/i] mode. Press a key!"
16
- when nil
17
- "[green]#{raw.inspect}[/fg] → [bold bright_green][\\#{raw}]"
10
+ "
11
+ #{
12
+ if event
13
+ "#{event.to_a.size < 2 ? ' Key' : 'Keys'}: [bold bright_green]#{
14
+ event.to_a.map { "[\\#{_1}]" }.join(' ')
15
+ }[/]
16
+ Code: [bright_blue]#{event.raw.inspect}[/]"
18
17
  else
19
- "[green]#{raw.inspect}[/fg] [bold bright_green]#{
20
- name.split('+').map! { "[\\#{_1}]" }.join(' ')
21
- }"
18
+ "Your terminal uses [bright_blue]#{
19
+ Terminal.input_mode
20
+ }[/] mode. Press a key!"
22
21
  end
23
- }\n\n[bright_black](Exit with ESC)"
22
+ }
23
+
24
+ [faint](Exit with ESC)"
24
25
  )
25
26
  end
26
- raw, name = Terminal.read_key(mode: :both)
27
+ event = Terminal.read_key_event
28
+ exit if event.nil? || event.name == 'Esc'
27
29
  end
28
30
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/natty-ui'
4
+
5
+ ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Options and Selections[/]' do
6
+ ui.space
7
+ ui.puts <<~INFO, eol: false
8
+ [i]Options[/i] and [i]selections[/i] allow the user to select from several
9
+ options interactively.
10
+ If ANSI is available the user can use [b][Up][/b] and [b][Down][/b] keys to
11
+ navigate, switch the state of selected item with [b][Space][/b] and complete
12
+ the selection with [b][Enter][/b].
13
+ INFO
14
+
15
+ ui.space
16
+ options =
17
+ ui.select %w[Kitty iTerm2 Ghostty Tabby Rio] do
18
+ ui.puts '[i]Which terminal applications did you already tested?[/i]'
19
+ end
20
+ case options.size
21
+ when 0
22
+ ui.puts 'You selected nothing – test more in future!'
23
+ when 1
24
+ ui.puts "#{options.first} is indeed a nice terminal."
25
+ else
26
+ ui.puts "#{options.join(', ')} are worth to test!"
27
+ end
28
+ end
data/examples/tasks.rb CHANGED
@@ -21,7 +21,7 @@ ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Tasks[/]' do
21
21
 
22
22
  ui.task('Connect to Library') do
23
23
  foo
24
- ui.mark('Server Found', mark: :checkmark)
24
+ ui.mark 'Server Found', mark: :checkmark
25
25
  ui.task('Login...') { some }
26
26
  end
27
27
 
data/examples/vbars.rb ADDED
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/natty-ui'
4
+
5
+ ui.message '[b]​ᓚᕠᗢ NattyUI[/b] [i green]Print Vertical Bars[/]' do
6
+ values = [
7
+ 11.97,
8
+ 14.35,
9
+ 15.51,
10
+ 12.39,
11
+ 14.3,
12
+ 10.6,
13
+ 17.7,
14
+ 14.47,
15
+ 14.56,
16
+ 17.31,
17
+ 12.98,
18
+ 16.21,
19
+ 14.9,
20
+ 17.23,
21
+ 13.35,
22
+ 11.62,
23
+ 14.81,
24
+ 19.7,
25
+ 13.42,
26
+ 14.18
27
+ ].freeze
28
+
29
+ ui.space
30
+ ui.vbars values, style: :blue
31
+ ui.puts 'NattyUI can quick dump values as vertical bars.'
32
+
33
+ ui.space
34
+ ui.vbars values, style: :green, normalize: true, bar_width: 2
35
+ ui.puts(
36
+ 'These are the same values but [i]normalized[/i] and printed with ' \
37
+ 'a fixed bar width.'
38
+ )
39
+ end
@@ -29,7 +29,6 @@ module NattyUI
29
29
  def _init = nil
30
30
  def _assign(_opt) = self
31
31
  def _store(opt) = opt
32
-
33
32
  def as_uint(value) = [0, value.to_i].max
34
33
  def as_nint(value) = ([0, value.to_i].max if value)
35
34
 
@@ -555,9 +554,7 @@ module NattyUI
555
554
 
556
555
  module TextWithAttributes
557
556
  include WithAttributes
558
-
559
557
  attr_reader :text
560
-
561
558
  def empty? = @text.empty?
562
559
  alias _to_s to_s
563
560
  private :_to_s
@@ -7,22 +7,31 @@ module NattyUI
7
7
  def select
8
8
  yield(self) if block_given?
9
9
  pin_line = NattyUI.lines_written
10
- draw(current = 0)
11
- while (key = Terminal.read_key)
12
- case key
10
+ draw
11
+ last = @current
12
+ while (event = Terminal.read_key_event)
13
+ case event.name
13
14
  when 'Esc', 'Ctrl+c'
14
15
  break nil if @abortable
15
- when 'Enter', ' '
16
- break @ret[current]
17
- when 'Up', 'Left', 'Back', 'Shift+Tab'
18
- current = @texts.size - 1 if (current -= 1) < 0
19
- pin_line = NattyUI.back_to_line(pin_line, erase: false)
20
- draw(current)
21
- when 'Down', 'Right', 'Tab'
22
- current = 0 if (current += 1) == @texts.size
23
- pin_line = NattyUI.back_to_line(pin_line, erase: false)
24
- draw(current)
16
+ when 'Enter', 'Space'
17
+ break @ret[@current]
18
+ when 'Home'
19
+ @current = 0
20
+ when 'End'
21
+ @current = @texts.size - 1
22
+ when 'Up', 'Back', 'Shift+Tab', 'i', 'w'
23
+ @current = @texts.size - 1 if (@current -= 1) < 0
24
+ when 'Down', 'Tab', 'k', 's'
25
+ @current = 0 if (@current += 1) == @texts.size
26
+ else
27
+ next unless event.simple?
28
+ c = event.key.ord
29
+ @current = (c - 48).clamp(0, @texts.size - 1) if c.between?(48, 57)
25
30
  end
31
+ next if last == @current
32
+ pin_line = NattyUI.back_to_line(pin_line, erase: false)
33
+ draw
34
+ last = @current
26
35
  end
27
36
  ensure
28
37
  NattyUI.back_to_line(@start_line)
@@ -30,22 +39,23 @@ module NattyUI
30
39
 
31
40
  private
32
41
 
33
- def initialize(parent, args, kwargs, abortable)
42
+ def initialize(parent, args, kwargs, abortable, selected)
34
43
  super(parent)
35
44
  @start_line = NattyUI.lines_written
36
45
  @texts = args + kwargs.values
37
46
  @ret = Array.new(args.size, &:itself) + kwargs.keys
38
47
  @abortable = abortable
48
+ @current = @ret.index(selected) || 0
39
49
  theme = Theme.current
40
50
  @mark = [theme.mark(:choice), theme.choice_style]
41
51
  @mark_current = [theme.mark(:current_choice), theme.choice_current_style]
42
52
  end
43
53
 
44
- def draw(current)
54
+ def draw
45
55
  @texts.each_with_index do |str, idx|
46
- mark, decor = idx == current ? @mark_current : @mark
56
+ mark, style = idx == @current ? @mark_current : @mark
47
57
  @parent.puts(
48
- "#{decor}#{str}",
58
+ "#{style}#{str}",
49
59
  first_line_prefix: mark,
50
60
  first_line_prefix_width: mark.width
51
61
  )
@@ -7,11 +7,12 @@ module NattyUI
7
7
  def select
8
8
  yield(self) if block_given?
9
9
  draw
10
- while (code = Terminal.read_key)
11
- return if @abortable && (code == 'Esc' || code == 'Ctrl+c')
12
- next if code.size > 1
13
- code = code[0].upcase
14
- if @ret.size <= 9 && ('1'..'9').include?(code)
10
+ while (event = Terminal.read_key_event)
11
+ return if @abortable && %w[Esc Ctrl+c].include?(event.name)
12
+ next unless event.simple?
13
+ code = event.raw.upcase
14
+ if @ret.size <= 9
15
+ next unless ('1'..'9').include?(code)
15
16
  code = @ret[code.ord - 49] and break code
16
17
  elsif ('A'..'Z').include?(code)
17
18
  code = @ret[code.ord - 65] and break code
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'element'
4
+
5
+ module NattyUI
6
+ class DumbOptions < Element
7
+ def select
8
+ yield(self) if block_given?
9
+ draw
10
+ while (event = Terminal.read_key_event)
11
+ return if @abortable && %w[Esc Ctrl+c].include?(event.name)
12
+ return @opts.transform_values(&:last) if event.name == 'Enter'
13
+ next unless event.simple?
14
+ code = event.raw.upcase
15
+ if @opts.size <= 9
16
+ next unless ('1'..'9').include?(code)
17
+ offset = 49
18
+ elsif ('A'..'Z').include?(code)
19
+ offset = 65
20
+ else
21
+ next
22
+ end
23
+ key = @opts.keys[code.ord - offset] or next
24
+ @opts[key][-1] = !@opts[key][-1]
25
+ @parent.space
26
+ draw
27
+ end
28
+ ensure
29
+ @parent.space
30
+ end
31
+
32
+ private
33
+
34
+ def initialize(parent, opts, abortable, selected)
35
+ super(parent)
36
+ @opts =
37
+ opts.to_h do |k, v|
38
+ v.is_a?(Enumerable) ? [k, [v[0], !!v[-1]]] : [k, [k, !!v]]
39
+ end
40
+ @abortable = abortable
41
+ @current = @opts.key?(selected) ? selected : @opts.first.first
42
+ theme = Theme.current
43
+ @marks = {
44
+ true => theme.mark(:checkmark),
45
+ false => theme.mark(:choice)
46
+ }.compare_by_identity
47
+ end
48
+
49
+ def draw
50
+ glyph = @opts.size <= 9 ? 1 : 'A'
51
+ @opts.each_pair do |_, (str, selected)|
52
+ mark = @marks[selected]
53
+ @parent.puts(
54
+ str,
55
+ first_line_prefix: "[\\#{glyph}] #{mark}",
56
+ first_line_prefix_width: mark.width + 2
57
+ )
58
+ glyph = glyph.succ
59
+ end
60
+ end
61
+ end
62
+ private_constant :DumbOptions
63
+ end
@@ -32,12 +32,12 @@ module NattyUI
32
32
  self
33
33
  end
34
34
 
35
- alias _to_s to_s
36
- private :_to_s
37
-
38
35
  # @!visibility private
39
36
  alias to_s inspect
40
37
 
38
+ alias _to_s to_s
39
+ private :_to_s
40
+
41
41
  private
42
42
 
43
43
  def initialize(parent)
@@ -48,7 +48,6 @@ module NattyUI
48
48
 
49
49
  module WithStatus
50
50
  attr_reader :status
51
-
52
51
  def active? = @status.nil?
53
52
  def closed? = !active?
54
53
  def ok? = @state == :ok