natty-ui 0.27.0 → 0.28.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: db28cf57db8670d12ed258d70765447c08bd51462acc7907ea9072b64117f965
4
+ data.tar.gz: 36e9c43bf76fcb1e68b450a1289bcffa8b4cfb33fa2d575ed9b1b92dc6ecce69
5
5
  SHA512:
6
- metadata.gz: d9c75d24c0363076c3e0d41ac458d4f13a6552811d166028d5d758ba408d20aa63907a471ee56c4fe4b0638db1cb03e915d0b6c606e8770a9753d59eafb7c951
7
- data.tar.gz: 77a95400ba528d57f3e1b559ac1ffa584c68a60bcc45d212341bc803031f204abac44e269db1d81903a4629b7c9c466c27acae66d84c2f802a3486bab37a929b
6
+ metadata.gz: e19e8e97300a844d294f61e9d4e6c43f5db5fe5a7122ff7c07c7bdd460e229ffffb0b6c943fe1e9f015bf91008824312746290098e10c7851ece75b7bfcb21bf
7
+ data.tar.gz: c6caff65104a42913c3f38ad53b0d628b11aff7517f6450d562c7f41e3b99234caaa48d8e266dd7abb6ca3a83546cd27a019612d0ee6f9e40e249717d26ecfd1
@@ -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,6 +13,8 @@ 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
19
  'tasks' => 'Tasks'
18
20
  }.freeze
@@ -23,7 +25,7 @@ ui.space
23
25
 
24
26
  while true
25
27
  selected =
26
- ui.choice(**EXAMPLES, abortable: true) do
28
+ ui.choice(**EXAMPLES, abortable: true, selected: selected) do
27
29
  ui.cols(
28
30
  "[red] /\\_/\\\n( o.o )\n > ^ <",
29
31
  '[bright_green b]Select a natty example:',
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
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
@@ -7,22 +7,24 @@ 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(current = @ret.index(@selected) || 0)
11
+ while (event = Terminal.read_key_event)
12
+ case event.name
13
13
  when 'Esc', 'Ctrl+c'
14
14
  break nil if @abortable
15
15
  when 'Enter', ' '
16
16
  break @ret[current]
17
- when 'Up', 'Left', 'Back', 'Shift+Tab'
17
+ when 'Home'
18
+ current = 0
19
+ when 'End'
20
+ current = @texts.size - 1
21
+ when 'Up', 'Back', 'Shift+Tab', 'i'
18
22
  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'
23
+ when 'Down', 'Tab', 'k'
22
24
  current = 0 if (current += 1) == @texts.size
23
- pin_line = NattyUI.back_to_line(pin_line, erase: false)
24
- draw(current)
25
25
  end
26
+ pin_line = NattyUI.back_to_line(pin_line, erase: false)
27
+ draw(current)
26
28
  end
27
29
  ensure
28
30
  NattyUI.back_to_line(@start_line)
@@ -30,12 +32,13 @@ module NattyUI
30
32
 
31
33
  private
32
34
 
33
- def initialize(parent, args, kwargs, abortable)
35
+ def initialize(parent, args, kwargs, abortable, selected)
34
36
  super(parent)
35
37
  @start_line = NattyUI.lines_written
36
38
  @texts = args + kwargs.values
37
39
  @ret = Array.new(args.size, &:itself) + kwargs.keys
38
40
  @abortable = abortable
41
+ @selected = selected
39
42
  theme = Theme.current
40
43
  @mark = [theme.mark(:choice), theme.choice_style]
41
44
  @mark_current = [theme.mark(:current_choice), theme.choice_current_style]
@@ -7,10 +7,10 @@ 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
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
14
  if @ret.size <= 9 && ('1'..'9').include?(code)
15
15
  code = @ret[code.ord - 49] and break code
16
16
  elsif ('A'..'Z').include?(code)
@@ -15,12 +15,12 @@ module NattyUI
15
15
  # Print given text as lines.
16
16
  #
17
17
  # @example Print two lines text, right aligned
18
- # ui.puts("Two lines", "of nice text", align: :right)
18
+ # ui.puts "Two lines", "of nice text", align: :right
19
19
  # # => Two lines
20
20
  # # => of nice text
21
21
  #
22
22
  # @example Print two lines text, with a prefix
23
- # ui.puts("Two lines", "of nice text", prefix: ': ')
23
+ # ui.puts "Two lines", "of nice text", prefix: ': '
24
24
  # # => : Two lines
25
25
  # # => : of nice text
26
26
  #
@@ -39,6 +39,7 @@ module NattyUI
39
39
  def puts(*text, **options)
40
40
  bbcode = true if (bbcode = options[:bbcode]).nil?
41
41
  max_width = options[:max_width] || Terminal.columns
42
+ max_width = Terminal.columns + max_width if max_width < 0
42
43
 
43
44
  prefix_width =
44
45
  if (prefix = options[:prefix])
@@ -272,8 +273,8 @@ module NattyUI
272
273
 
273
274
  # Print a horizontal rule.
274
275
  #
275
- # @example
276
- # ui.hr(:heavy)
276
+ # @example Print double line
277
+ # ui.hr :double
277
278
  #
278
279
  # @param type [Symbol]
279
280
  # border type
@@ -305,10 +306,10 @@ module NattyUI
305
306
  # - any text as prefix
306
307
  #
307
308
  # @example Print all Ruby files as a numbered list
308
- # ui.ls(Dir['*/**/*.rb'], glyph: 1)
309
+ # ui.ls Dir['*/**/*.rb'], glyph: 1
309
310
  #
310
311
  # @example Print all Ruby files as a bullet point list (with green bullets)
311
- # ui.ls(Dir['*/**/*.rb'], glyph: '[green]•[/fg]')
312
+ # ui.ls Dir['*/**/*.rb'], glyph: '[green]•[/fg]'
312
313
  #
313
314
  # @param items [#to_s]
314
315
  # one or more convertible objects to list
@@ -416,6 +417,86 @@ module NattyUI
416
417
  table(**tab_att) { |table| table.add { _1.add(*text, **att) } }
417
418
  end
418
419
 
420
+ # Dump given values as vertical bars.
421
+ #
422
+ # @example Draw green bars
423
+ # ui.vbars 1..10, style: :green
424
+ #
425
+ # @example Draw very big bars
426
+ # ui.vbars 1..10, bar_width: 5, height: 20
427
+ #
428
+ # @param values [#to_a, Array<Numeric>] values to print
429
+ # @param normalize [true, false] whether the values should be normalized
430
+ # @param height [Integer] output height
431
+ # @param bar_width [:auto, :min, Integer] with of each bar
432
+ # @param style [Symbol, Array<Symbol>, nil] drawing style
433
+ #
434
+ # @raise [ArgumentError] if any value is negative
435
+ #
436
+ # @return (see puts)
437
+ def vbars(
438
+ values,
439
+ normalize: false,
440
+ height: 10,
441
+ bar_width: :auto,
442
+ style: nil
443
+ )
444
+ return self if (values = values.to_a).empty?
445
+ if values.any?(&:negative?)
446
+ raise(ArgumentError, 'values can not be negative')
447
+ end
448
+ puts(
449
+ *VBarsRenderer.lines(
450
+ values,
451
+ columns,
452
+ height,
453
+ normalize,
454
+ bar_width,
455
+ Terminal.ansi? ? style : nil
456
+ )
457
+ )
458
+ end
459
+
460
+ # Dump given values as horizontal bars.
461
+ #
462
+ # @example Draw green bars
463
+ # ui.hbars 1..10, style: :green
464
+ #
465
+ # @example Draw bars in half sreen width
466
+ # ui.hbars 1..10, style: :blue, width: 0.5
467
+ #
468
+ # @param values [#to_a, Array<Numeric>] values to print
469
+ # @param with_values [true, false] whether the values should be printed too
470
+ # @param normalize [true, false] whether the values should be normalized
471
+ # @param height [Integer] output height
472
+ # @param bar_width [:auto, :min, Integer] with of each bar
473
+ # @param style [Symbol, Array<Symbol>, nil] bar drawing style
474
+ # @param text_style [Symbol, Array<Symbol>, nil] text style
475
+ #
476
+ # @raise [ArgumentError] if any value is negative
477
+ #
478
+ # @return (see puts)
479
+ def hbars(
480
+ values,
481
+ with_values: true,
482
+ normalize: false,
483
+ width: :auto,
484
+ style: nil,
485
+ text_style: nil
486
+ )
487
+ return self if (values = values.to_a).empty?
488
+ if values.any?(&:negative?)
489
+ raise(ArgumentError, 'values can not be negative')
490
+ end
491
+ style = text_style = nil unless Terminal.ansi?
492
+ size = Utils.as_size(3..columns, width)
493
+ if with_values
494
+ puts(*HBarsRenderer.lines(values, size, normalize, style, text_style))
495
+ else
496
+ puts(*HBarsRenderer.lines_bars_only(values, size, normalize, style))
497
+ end
498
+ end
499
+
419
500
  # Dynamically display a task progress.
420
501
  # When a `max` parameter is given the progress will be displayed as a
421
502
  # progress bar below the `title`. Otherwise the progress is displayed just
@@ -434,15 +515,15 @@ module NattyUI
434
515
  # end
435
516
  #
436
517
  # @example Display simple progress
437
- # progress = ui.progress('Check some stuff')
518
+ # progress = ui.progress 'Check some stuff'
438
519
  # 10.times do
439
520
  # # simulate some work
440
- # sleep(0.1)
521
+ # sleep 0.1
441
522
  #
442
523
  # # here we actualize the progress
443
524
  # progress.step
444
525
  # end
445
- # progress.ok('Stuff checked ok')
526
+ # progress.ok 'Stuff checked ok'
446
527
  #
447
528
  # @overload progress(title, max: nil, pin: false)
448
529
  # @param title [#to_s]
@@ -491,10 +572,10 @@ module NattyUI
491
572
  #
492
573
  # @example
493
574
  # ui.section do |section|
494
- # section.h1('About Sections')
575
+ # section.h1 'About Sections'
495
576
  # section.space
496
- # section.puts('Sections are areas of text elements.')
497
- # section.puts('You can use any other feature inside such an area.')
577
+ # section.puts 'Sections are areas of text elements.'
578
+ # section.puts 'You can use any other feature inside such an area.'
498
579
  # end
499
580
  # # => ╭────╶╶╶
500
581
  # # => │ ╴╶╴╶─═══ About Sections ═══─╴╶╴╶
@@ -643,18 +724,14 @@ module NattyUI
643
724
  #
644
725
  # @return [true, false]
645
726
  # wheter the user inputs a positive result
727
+ # @return nil
728
+ # in error case
646
729
  #
647
730
  def await(yes: 'Enter', no: 'Esc')
648
- temporary do |arg|
649
- yield(arg) if block_given?
650
- while (key = Terminal.read_key)
651
- if (no == key) || (no.is_a?(Enumerable) && no.include?(key))
652
- return false
653
- end
654
- if (yes == key) || (yes.is_a?(Enumerable) && yes.include?(key))
655
- return true
656
- end
657
- end
731
+ return __await(yes, no) unless block_given?
732
+ temporary do |temp|
733
+ yield(temp)
734
+ __await(yes, no)
658
735
  end
659
736
  end
660
737
 
@@ -727,12 +804,12 @@ module NattyUI
727
804
  # @return [nil]
728
805
  # when user aborted the selection
729
806
  #
730
- def choice(*choices, abortable: false, **kwchoices, &block)
807
+ def choice(*choices, abortable: false, selected: nil, **kwchoices, &block)
731
808
  return if choices.empty? && kwchoices.empty?
732
809
  choice =
733
810
  case NattyUI.input_mode
734
811
  when :default
735
- Choice.new(self, choices, kwchoices, abortable)
812
+ Choice.new(self, choices, kwchoices, abortable, selected)
736
813
  when :dumb
737
814
  DumbChoice.new(self, choices, kwchoices, abortable)
738
815
  else
@@ -757,7 +834,7 @@ module NattyUI
757
834
  #
758
835
  # @example Show tempoary information
759
836
  # ui.temporary do
760
- # ui.info('Information', 'This text will disappear when you pressed ENTER.')
837
+ # ui.info 'Information', 'This text will disappear when you pressed ENTER.'
761
838
  # ui.await
762
839
  # end
763
840
  #
@@ -783,15 +860,27 @@ module NattyUI
783
860
  __sec(color, "#{Theme.current.mark(color)}#{title}", text, &block)
784
861
  end
785
862
 
863
+ def __await(yes, no)
864
+ while (event = Terminal.read_key_event&.name)
865
+ if (no == event) || (no.is_a?(Enumerable) && no.include?(event))
866
+ return false
867
+ end
868
+ if (yes == event) || (yes.is_a?(Enumerable) && yes.include?(event))
869
+ return true
870
+ end
871
+ end
872
+ end
873
+
786
874
  EOL__ = Terminal.ansi? ? "\e[m\n" : "\n"
787
875
  private_constant :EOL__
788
876
  end
789
877
 
790
878
  dir = __dir__
791
879
  autoload :Choice, "#{dir}/choice.rb"
792
- autoload :CompactLSRenderer, "#{dir}/ls_renderer.rb"
793
880
  autoload :DumbChoice, "#{dir}/dumb_choice.rb"
881
+ autoload :CompactLSRenderer, "#{dir}/ls_renderer.rb"
794
882
  autoload :Framed, "#{dir}/framed.rb"
883
+ autoload :HBarsRenderer, "#{dir}/hbars_renderer.rb"
795
884
  autoload :LSRenderer, "#{dir}/ls_renderer.rb"
796
885
  autoload :Progress, "#{dir}/progress.rb"
797
886
  autoload :DumbProgress, "#{dir}/progress.rb"
@@ -801,6 +890,18 @@ module NattyUI
801
890
  autoload :Temporary, "#{dir}/temporary.rb"
802
891
  autoload :Theme, "#{dir}/theme.rb"
803
892
  autoload :Utils, "#{dir}/utils.rb"
804
-
805
- private_constant :Choice, :DumbChoice, :LSRenderer, :CompactLSRenderer
893
+ autoload :VBarsRenderer, "#{dir}/vbars_renderer.rb"
894
+
895
+ private_constant(
896
+ :Choice,
897
+ :DumbChoice,
898
+ :CompactLSRenderer,
899
+ :Framed,
900
+ :HBarsRenderer,
901
+ :LSRenderer,
902
+ :Progress,
903
+ :DumbProgress,
904
+ :Utils,
905
+ :VBarsRenderer
906
+ )
806
907
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'utils'
4
+
5
+ module NattyUI
6
+ module HBarsRenderer
7
+ class << self
8
+ def lines(vals, width, normalize, style, text_style)
9
+ if text_style
10
+ bots = Ansi[*text_style]
11
+ eots = Ansi::RESET
12
+ end
13
+ texts = vals.map { Str.new(_1) }
14
+ tw = texts.max_by(&:width).width
15
+ size = width - tw - 1
16
+ if size < 2 # text only
17
+ return texts.map { "#{bots}#{' ' * (tw - _1.width)}#{_1}#{eots}" }
18
+ end
19
+ if style
20
+ bos = Ansi[*style]
21
+ eos = Ansi::RESET
22
+ end
23
+ vals = normalize ? normalize!(vals, size) : adjust!(vals, size)
24
+ texts.map.with_index do |str, idx|
25
+ "#{bots}#{' ' * (tw - str.width)}#{str}#{eots}#{bos}▕#{
26
+ '▆' * vals[idx]
27
+ }#{eos}"
28
+ end
29
+ end
30
+
31
+ def lines_bars_only(vals, width, normalize, style)
32
+ if style
33
+ bos = Ansi[*style]
34
+ eos = Ansi::RESET
35
+ end
36
+ width -= 1
37
+ vals = normalize ? normalize!(vals, width) : adjust!(vals, width)
38
+ vals.map { "#{bos}▕#{'▆' * _1}#{eos}" }
39
+ end
40
+
41
+ private
42
+
43
+ def adjust!(vals, size)
44
+ max = vals.max.to_f
45
+ vals.map { ((_1 / max) * size).round }
46
+ end
47
+
48
+ def normalize!(vals, size)
49
+ min, max = vals.minmax
50
+ return Array.new(vals.size, size) if min == max
51
+ max = (max - min).to_f
52
+ vals.map { (((_1 - min) / max) * size).round }
53
+ end
54
+ end
55
+ end
56
+
57
+ private_constant :HBarsRenderer
58
+ end
@@ -156,6 +156,7 @@ module NattyUI
156
156
  ["#{@style}#{' ' * @padding[3]}", "#{' ' * @padding[1]}[/]"]
157
157
  end
158
158
  end
159
+ private_constant :Cell
159
160
  end
160
161
  private_constant :TableRenderer
161
162
  end
@@ -59,6 +59,19 @@ module NattyUI
59
59
  end
60
60
  end
61
61
  alias margin padding
62
+
63
+ # @!visibility private
64
+ def as_size(range, value)
65
+ return range.begin if value == :min
66
+ return range.end if value.nil? || value.is_a?(Symbol)
67
+ (
68
+ if value.is_a?(Numeric)
69
+ (value > 0 && value < 1 ? (range.end * value) : value).round
70
+ else
71
+ value.to_i
72
+ end
73
+ ).clamp(range)
74
+ end
62
75
  end
63
76
 
64
77
  POS_ALI = %i[right centered].freeze
@@ -79,11 +92,25 @@ module NattyUI
79
92
  @width
80
93
  end
81
94
 
82
- def initialize(str, width = nil)
83
- @to_s = Ansi.bbcode(str).freeze
84
- return unless width
85
- @width = @width.is_a?(Integer) ? width : Text.width(self)
86
- freeze
95
+ def +(other)
96
+ other = Str.new(other) unless other.is_a?(Str)
97
+ Str.new(@to_s + other.to_s, width + other.width)
98
+ end
99
+
100
+ if Terminal.ansi?
101
+ def initialize(str, width = nil)
102
+ @to_s = Ansi.bbcode(str).freeze
103
+ return unless width
104
+ @width = @width.is_a?(Integer) ? width : Text.width(self)
105
+ freeze
106
+ end
107
+ else
108
+ def initialize(str, width = nil)
109
+ @to_s = Ansi.plain(str).freeze
110
+ return unless width
111
+ @width = @width.is_a?(Integer) ? width : Text.width(self)
112
+ freeze
113
+ end
87
114
  end
88
115
  end
89
116
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NattyUI
4
+ module VBarsRenderer
5
+ class << self
6
+ def lines(vals, width, height, normalize, bar_width, style)
7
+ if style
8
+ bos = Ansi[*style]
9
+ eos = Ansi::RESET
10
+ end
11
+ if ((bar_width != :auto) && bar_width <= 1) || (vals.size * 2 > width)
12
+ db = '▉'
13
+ ds = ' '
14
+ el = "#{bos}#{'▔' * vals.size}#{eos}"
15
+ vals = vals.take(width) if vals.size > width
16
+ else
17
+ bw = (width - vals.size) / vals.size
18
+ bw = [bw, bar_width].min if bar_width != :auto
19
+ db = "#{'█' * bw} "
20
+ bw += 1
21
+ ds = ' ' * bw
22
+ el = "#{bos}#{'▔' * ((bw * vals.size) - 1)}#{eos}"
23
+ end
24
+ height -= 1
25
+ vals = normalize ? normalize!(vals, height) : adjust!(vals, height)
26
+ height
27
+ .downto(1)
28
+ .map { |i| "#{bos}#{vals.map { _1 < i ? ds : db }.join}#{eos}" } << el
29
+ end
30
+
31
+ private
32
+
33
+ def adjust!(vals, height)
34
+ max = vals.max.to_f
35
+ vals.map { ((_1 / max) * height).round }
36
+ end
37
+
38
+ def normalize!(vals, height)
39
+ min, max = vals.minmax
40
+ return Array.new(vals.size, height) if min == max
41
+ max = (max - min).to_f
42
+ vals.map { (((_1 - min) / max) * height).round }
43
+ end
44
+ end
45
+ end
46
+
47
+ private_constant :VBarsRenderer
48
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module NattyUI
4
4
  # The version number of the gem.
5
- VERSION = '0.27.0'
5
+ VERSION = '0.28.0'
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: natty-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 0.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 0.11.0
18
+ version: '0.12'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 0.11.0
25
+ version: '0.12'
26
26
  description: |
27
27
  This is the beautiful, nice, nifty, fancy, neat, pretty, cool, rich, lovely,
28
28
  natty user interface tool you like to have for your command line applications.
@@ -44,6 +44,7 @@ files:
44
44
  - examples/cols.rb
45
45
  - examples/elements.rb
46
46
  - examples/examples.rb
47
+ - examples/hbars.rb
47
48
  - examples/illustration.rb
48
49
  - examples/info.rb
49
50
  - examples/key-codes.rb
@@ -52,6 +53,7 @@ files:
52
53
  - examples/sections.rb
53
54
  - examples/tables.rb
54
55
  - examples/tasks.rb
56
+ - examples/vbars.rb
55
57
  - lib/natty-ui.rb
56
58
  - lib/natty-ui/attributes.rb
57
59
  - lib/natty-ui/choice.rb
@@ -59,6 +61,7 @@ files:
59
61
  - lib/natty-ui/element.rb
60
62
  - lib/natty-ui/features.rb
61
63
  - lib/natty-ui/framed.rb
64
+ - lib/natty-ui/hbars_renderer.rb
62
65
  - lib/natty-ui/ls_renderer.rb
63
66
  - lib/natty-ui/progress.rb
64
67
  - lib/natty-ui/section.rb
@@ -68,6 +71,7 @@ files:
68
71
  - lib/natty-ui/temporary.rb
69
72
  - lib/natty-ui/theme.rb
70
73
  - lib/natty-ui/utils.rb
74
+ - lib/natty-ui/vbars_renderer.rb
71
75
  - lib/natty-ui/version.rb
72
76
  - lib/natty-ui/width_finder.rb
73
77
  - lib/natty_ui.rb
@@ -76,9 +80,10 @@ licenses:
76
80
  - BSD-3-Clause
77
81
  metadata:
78
82
  rubygems_mfa_required: 'true'
83
+ yard.run: yard
79
84
  source_code_uri: https://github.com/mblumtritt/natty-ui
80
85
  bug_tracker_uri: https://github.com/mblumtritt/natty-ui/issues
81
- documentation_uri: https://rubydoc.info/gems/natty-ui/0.27.0/NattyUI
86
+ documentation_uri: https://rubydoc.info/gems/natty-ui/NattyUI
82
87
  rdoc_options: []
83
88
  require_paths:
84
89
  - lib