natty-ui 0.28.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: db28cf57db8670d12ed258d70765447c08bd51462acc7907ea9072b64117f965
4
- data.tar.gz: 36e9c43bf76fcb1e68b450a1289bcffa8b4cfb33fa2d575ed9b1b92dc6ecce69
3
+ metadata.gz: 3d1b81e5e7afebe8166a6532c00df911d53b189f6eb4b282e828492b0d4a123f
4
+ data.tar.gz: ef24f92d9c696f966e6dbe3fdcb7eba55c649099551b50dcb83922f1702a1d2a
5
5
  SHA512:
6
- metadata.gz: e19e8e97300a844d294f61e9d4e6c43f5db5fe5a7122ff7c07c7bdd460e229ffffb0b6c943fe1e9f015bf91008824312746290098e10c7851ece75b7bfcb21bf
7
- data.tar.gz: c6caff65104a42913c3f38ad53b0d628b11aff7517f6450d562c7f41e3b99234caaa48d8e266dd7abb6ca3a83546cd27a019612d0ee6f9e40e249717d26ecfd1
6
+ metadata.gz: 610d16c334a76042430e2cf9ff0ae876347ecb24417134adbda55dae569871b7e1e91408bab79770ba3da8ed9379dcf3834bc54aa6673d5081c376cc3c58778d
7
+ data.tar.gz: 024bc0a945ca27ec2379b7170343e40e23d555c65780b766c30751bc8c4e093766e79081bb6a5aae93cc3be8c9f8c474ca03b84fe1b5e4fa6307858d816a13bd
data/examples/examples.rb CHANGED
@@ -16,11 +16,10 @@ EXAMPLES = {
16
16
  'vbars' => 'Print Vertical Bars',
17
17
  'hbars' => 'Print Horizontal Bars',
18
18
  'sections' => 'Sections',
19
- 'tasks' => 'Tasks'
19
+ 'tasks' => 'Tasks',
20
+ 'options' => 'Options and Selections'
20
21
  }.freeze
21
22
 
22
- DEFAULT_MODE = NattyUI.input_mode == :default
23
-
24
23
  ui.space
25
24
 
26
25
  while true
@@ -34,12 +33,12 @@ while true
34
33
  ui.div('[faint](Abort with [\\ESC])', padding: [1, 0, 1])
35
34
  end
36
35
 
37
- ui.space unless DEFAULT_MODE
36
+ ui.space unless Terminal.ansi?
38
37
  break unless selected
39
38
 
40
39
  ui.temporary do
41
40
  load("#{__dir__}/#{selected}.rb")
42
- if DEFAULT_MODE
41
+ if Terminal.ansi?
43
42
  ui.await { ui.puts '[faint][\\Press ENTER to continue...]' }
44
43
  else
45
44
  ui.space
@@ -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
@@ -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,24 +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 = @ret.index(@selected) || 0)
10
+ draw
11
+ last = @current
11
12
  while (event = Terminal.read_key_event)
12
13
  case event.name
13
14
  when 'Esc', 'Ctrl+c'
14
15
  break nil if @abortable
15
- when 'Enter', ' '
16
- break @ret[current]
16
+ when 'Enter', 'Space'
17
+ break @ret[@current]
17
18
  when 'Home'
18
- current = 0
19
+ @current = 0
19
20
  when 'End'
20
- current = @texts.size - 1
21
- when 'Up', 'Back', 'Shift+Tab', 'i'
22
- current = @texts.size - 1 if (current -= 1) < 0
23
- when 'Down', 'Tab', 'k'
24
- current = 0 if (current += 1) == @texts.size
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
26
32
  pin_line = NattyUI.back_to_line(pin_line, erase: false)
27
- draw(current)
33
+ draw
34
+ last = @current
28
35
  end
29
36
  ensure
30
37
  NattyUI.back_to_line(@start_line)
@@ -38,17 +45,17 @@ module NattyUI
38
45
  @texts = args + kwargs.values
39
46
  @ret = Array.new(args.size, &:itself) + kwargs.keys
40
47
  @abortable = abortable
41
- @selected = selected
48
+ @current = @ret.index(selected) || 0
42
49
  theme = Theme.current
43
50
  @mark = [theme.mark(:choice), theme.choice_style]
44
51
  @mark_current = [theme.mark(:current_choice), theme.choice_current_style]
45
52
  end
46
53
 
47
- def draw(current)
54
+ def draw
48
55
  @texts.each_with_index do |str, idx|
49
- mark, decor = idx == current ? @mark_current : @mark
56
+ mark, style = idx == @current ? @mark_current : @mark
50
57
  @parent.puts(
51
- "#{decor}#{str}",
58
+ "#{style}#{str}",
52
59
  first_line_prefix: mark,
53
60
  first_line_prefix_width: mark.width
54
61
  )
@@ -11,7 +11,8 @@ module NattyUI
11
11
  return if @abortable && %w[Esc Ctrl+c].include?(event.name)
12
12
  next unless event.simple?
13
13
  code = event.raw.upcase
14
- if @ret.size <= 9 && ('1'..'9').include?(code)
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
@@ -38,8 +38,16 @@ module NattyUI
38
38
  # itself
39
39
  def puts(*text, **options)
40
40
  bbcode = true if (bbcode = options[:bbcode]).nil?
41
+
41
42
  max_width = options[:max_width] || Terminal.columns
42
- max_width = Terminal.columns + max_width if max_width < 0
43
+ return self if max_width == 0
44
+ if max_width < 1
45
+ if max_width > 0
46
+ max_width *= Terminal.columns
47
+ elsif max_width < 0
48
+ max_width += Terminal.columns
49
+ end
50
+ end
43
51
 
44
52
  prefix_width =
45
53
  if (prefix = options[:prefix])
@@ -90,7 +98,7 @@ module NattyUI
90
98
 
91
99
  if (align = options[:align]).nil?
92
100
  lines.each do |line|
93
- Terminal.print(prefix, line, suffix, EOL__, bbcode: false)
101
+ Terminal.print(prefix, line, suffix, __eol, bbcode: false)
94
102
  @lines_written += 1
95
103
  prefix, prefix_next = prefix_next, nil if prefix_next
96
104
  end
@@ -110,7 +118,7 @@ module NattyUI
110
118
  ' ' * (max_width - width),
111
119
  line,
112
120
  suffix,
113
- EOL__,
121
+ __eol,
114
122
  bbcode: false
115
123
  )
116
124
  @lines_written += 1
@@ -125,7 +133,7 @@ module NattyUI
125
133
  line,
126
134
  ' ' * (space - lw),
127
135
  suffix,
128
- EOL__,
136
+ __eol,
129
137
  bbcode: false
130
138
  )
131
139
  @lines_written += 1
@@ -138,7 +146,7 @@ module NattyUI
138
146
  line,
139
147
  ' ' * (max_width - width),
140
148
  suffix,
141
- EOL__,
149
+ __eol,
142
150
  bbcode: false
143
151
  )
144
152
  @lines_written += 1
@@ -148,6 +156,20 @@ module NattyUI
148
156
  self
149
157
  end
150
158
 
159
+ # Print given text with a decoration mark.
160
+ #
161
+ # @param text (see puts)
162
+ # @param mark [Symbol, #to_s]
163
+ # marker type
164
+ #
165
+ # @return (see puts)
166
+ def mark(*text, mark: :default, **options)
167
+ mark = Theme.current.mark(mark)
168
+ options[:first_line_prefix] = mark
169
+ options[:first_line_prefix_width] = mark.width
170
+ puts(*text, **options)
171
+ end
172
+
151
173
  # Print given text as lines like {#puts}. Used in elements with temporary
152
174
  # output like {#task} the text will be kept ("pinned").
153
175
  #
@@ -169,21 +191,7 @@ module NattyUI
169
191
  #
170
192
  # @return (see puts)
171
193
  def pin(*text, mark: nil, **options)
172
- options[:pin] = true
173
- options[:first_line_prefix] = Theme.current.mark(mark) if mark
174
- puts(*text, **options)
175
- end
176
-
177
- # Print given text with a decoration mark.
178
- #
179
- # @param text (see puts)
180
- # @param mark [Symbol, #to_s]
181
- # marker type
182
- #
183
- # @return (see puts)
184
- def mark(*text, mark: :default)
185
- mark = Theme.current.mark(mark)
186
- puts(*text, first_line_prefix: mark, first_line_prefix_width: mark.width)
194
+ mark(*text, mark: mark, pin: true, **options)
187
195
  end
188
196
 
189
197
  # Print given text as a quotation.
@@ -198,7 +206,7 @@ module NattyUI
198
206
  *text,
199
207
  prefix: quote,
200
208
  prefix_width: quote.width,
201
- max_width: width < 20 ? nil : width.to_i
209
+ max_width: width < 20 ? nil : width.round
202
210
  )
203
211
  end
204
212
 
@@ -735,7 +743,8 @@ module NattyUI
735
743
  end
736
744
  end
737
745
 
738
- # Request a user's chocie.
746
+ # Allows the user to select an option from a selection.
747
+ # The selected option is returned.
739
748
  #
740
749
  # @overload choice(*choices, abortable: false)
741
750
  # @param [#to_s] choices
@@ -773,6 +782,8 @@ module NattyUI
773
782
  # one or more alternatives to select from
774
783
  # @param [true, false] abortable
775
784
  # whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
785
+ # @param [#to_s, nil] selected
786
+ # optionally pre-selected option
776
787
  #
777
788
  # @return [Object]
778
789
  # key for selected choice
@@ -795,6 +806,8 @@ module NattyUI
795
806
  # one or more alternatives to select from
796
807
  # @param [true, false] abortable
797
808
  # whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
809
+ # @param [Integer] selected
810
+ # pre-selected option index
798
811
  #
799
812
  # @yieldparam temp [Temporary]
800
813
  # temporary displayed section (section will be erased after input)
@@ -807,17 +820,79 @@ module NattyUI
807
820
  def choice(*choices, abortable: false, selected: nil, **kwchoices, &block)
808
821
  return if choices.empty? && kwchoices.empty?
809
822
  choice =
810
- case NattyUI.input_mode
811
- when :default
823
+ if Terminal.ansi?
812
824
  Choice.new(self, choices, kwchoices, abortable, selected)
813
- when :dumb
814
- DumbChoice.new(self, choices, kwchoices, abortable)
815
825
  else
816
- return
826
+ DumbChoice.new(self, choices, kwchoices, abortable)
817
827
  end
818
828
  __with(choice) { choice.select(&block) }
819
829
  end
820
830
 
831
+ # Allows the user to select from several options.
832
+ # All options are returned with their selection status.
833
+ #
834
+ # @param [{#to_s => [true,false]}] choices
835
+ # Hash of options and their selection state
836
+ # @param [true, false] abortable
837
+ # whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
838
+ # @param [#to_s, nil] selected
839
+ # optionally pre-selected key
840
+ #
841
+ # @yieldparam temp [Temporary]
842
+ # temporary displayed section (section will be erased after input)
843
+ #
844
+ # @return [{#to_s => [true,false]}]
845
+ # Hash of options and their selection state
846
+ # @return [nil]
847
+ # when user aborted the selection
848
+ def options(abortable: false, selected: nil, **choices, &block)
849
+ return {} if choices.empty?
850
+ options =
851
+ if Terminal.ansi?
852
+ Options.new(self, choices, abortable, selected)
853
+ else
854
+ DumbOptions.new(self, choices, abortable, selected)
855
+ end
856
+ __with(options) { options.select(&block) }
857
+ end
858
+
859
+ # Allows the user to select from several options.
860
+ # The selected options are returned.
861
+ #
862
+ # @example Select a terminal
863
+ # ui.select %w[Kitty iTerm2 Ghostty Tabby Rio] do
864
+ # ui.puts '[i]Which terminal applications did you already tested?[/i]'
865
+ # end
866
+ #
867
+ # @param [Array<#to_s>] choices
868
+ # selectable options
869
+ # @param [true, false] abortable
870
+ # whether the user is allowed to abort with 'Esc' or 'Ctrl+c'
871
+ # @param [Integer, :all, nil] selected
872
+ # optionally pre-selected option index or `:all` to pre-select all items
873
+ # @yieldparam temp [Temporary]
874
+ # temporary displayed section (section will be erased after input)
875
+ #
876
+ # @return [Array<#to_s>]
877
+ # selected options
878
+ # @return [nil]
879
+ # when user aborted the selection
880
+ def select(*choices, abortable: false, selected: nil, &block)
881
+ return [] if choices.empty?
882
+ choices = choices[0] if choices.size == 1 && choices[0].is_a?(Enumerable)
883
+ if selected == :all
884
+ sel = true
885
+ elsif selected
886
+ selected = choices[selected.to_i]
887
+ end
888
+ options(
889
+ abortable: abortable,
890
+ selected: selected,
891
+ **choices.to_h { [_1, sel] },
892
+ &block
893
+ ).filter_map { |key, selected| key if selected }
894
+ end
895
+
821
896
  #
822
897
  # @!endgroup
823
898
  #
@@ -871,17 +946,20 @@ module NattyUI
871
946
  end
872
947
  end
873
948
 
874
- EOL__ = Terminal.ansi? ? "\e[m\n" : "\n"
875
- private_constant :EOL__
949
+ def __eol
950
+ @__eol ||= Terminal.ansi? ? "\e[m\n" : "\n"
951
+ end
876
952
  end
877
953
 
878
954
  dir = __dir__
879
955
  autoload :Choice, "#{dir}/choice.rb"
880
956
  autoload :DumbChoice, "#{dir}/dumb_choice.rb"
957
+ autoload :DumbOptions, "#{dir}/dumb_options.rb"
881
958
  autoload :CompactLSRenderer, "#{dir}/ls_renderer.rb"
882
959
  autoload :Framed, "#{dir}/framed.rb"
883
960
  autoload :HBarsRenderer, "#{dir}/hbars_renderer.rb"
884
961
  autoload :LSRenderer, "#{dir}/ls_renderer.rb"
962
+ autoload :Options, "#{dir}/options.rb"
885
963
  autoload :Progress, "#{dir}/progress.rb"
886
964
  autoload :DumbProgress, "#{dir}/progress.rb"
887
965
  autoload :Section, "#{dir}/section.rb"
@@ -895,10 +973,12 @@ module NattyUI
895
973
  private_constant(
896
974
  :Choice,
897
975
  :DumbChoice,
976
+ :DumbOptions,
898
977
  :CompactLSRenderer,
899
978
  :Framed,
900
979
  :HBarsRenderer,
901
980
  :LSRenderer,
981
+ :Options,
902
982
  :Progress,
903
983
  :DumbProgress,
904
984
  :Utils,
@@ -47,7 +47,6 @@ module NattyUI
47
47
 
48
48
  class Item
49
49
  attr_reader :width
50
-
51
50
  def to_s(in_width) = "#{@str}#{' ' * (in_width - @width)}"
52
51
 
53
52
  def initialize(str)
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'element'
4
+
5
+ module NattyUI
6
+ class Options < Element
7
+ def select
8
+ yield(self) if block_given?
9
+ pin_line = NattyUI.lines_written
10
+ draw
11
+ last = @current
12
+ while (event = Terminal.read_key_event)
13
+ case event.name
14
+ when 'Esc', 'Ctrl+c'
15
+ return if @abortable
16
+ when 'Enter'
17
+ return @opts.transform_values(&:last)
18
+ when 'Space'
19
+ (last = @opts[@current])[-1] = !last[-1]
20
+ when 'a'
21
+ @opts.transform_values { _1[-1] = true }
22
+ last = nil
23
+ when 'n'
24
+ @opts.transform_values { _1[-1] = false }
25
+ last = nil
26
+ when 'Home'
27
+ @current = @opts.first.first
28
+ when 'End'
29
+ @current = @opts.keys.last
30
+ when 'Up', 'Back', 'Shift+Tab', 'i'
31
+ keys = @opts.keys
32
+ @current = keys[keys.index(@current) - 1]
33
+ when 'Down', 'Tab', 'k'
34
+ keys = @opts.keys
35
+ @current = keys[keys.index(@current) + 1] || keys[0]
36
+ end
37
+ next if last == @current
38
+ pin_line = NattyUI.back_to_line(pin_line, erase: false)
39
+ draw
40
+ last = @current
41
+ end
42
+ ensure
43
+ NattyUI.back_to_line(@start_line)
44
+ end
45
+
46
+ private
47
+
48
+ def initialize(parent, opts, abortable, selected)
49
+ super(parent)
50
+ @opts =
51
+ opts.to_h do |k, v|
52
+ v.is_a?(Enumerable) ? [k, [v[0], !!v[-1]]] : [k, [k, !!v]]
53
+ end
54
+ @abortable = abortable
55
+ @current = @opts.key?(selected) ? selected : @opts.first.first
56
+ @start_line = NattyUI.lines_written
57
+ theme = Theme.current
58
+ @style = {
59
+ false => theme.choice_style,
60
+ true => theme.choice_current_style
61
+ }.compare_by_identity
62
+ end
63
+
64
+ def draw
65
+ states = NattyUI::Theme.current.option_states
66
+ @opts.each_pair do |key, (str, selected)|
67
+ mark = states.dig(current = key == @current, selected)
68
+ @parent.puts(
69
+ "#{@style[current]}#{str}",
70
+ first_line_prefix: mark,
71
+ first_line_prefix_width: mark.width
72
+ )
73
+ end
74
+ end
75
+ end
76
+ private_constant :Options
77
+ end
data/lib/natty-ui/task.rb CHANGED
@@ -11,7 +11,7 @@ module NattyUI
11
11
  private
12
12
 
13
13
  def _done(text)
14
- NattyUI.back_to_line(@start_line, erase: :all)
14
+ NattyUI.back_to_line(@start_line)
15
15
  @start_line = nil
16
16
  cm = Theme.current.mark(:checkmark)
17
17
  @parent.puts(
@@ -8,11 +8,10 @@ module NattyUI
8
8
  #
9
9
  class Temporary < Element
10
10
  # @!visibility private
11
- def puts(*objects, **options)
11
+ def puts(*objects, **opts)
12
12
  return self if @state
13
- if options.delete(:pin)
14
- @pins ||= []
15
- @pins << [objects, options.except(:prefix_width, :suffix_width)]
13
+ if opts.delete(:pin)
14
+ (@pins ||= []) << [objects, opts.except(:prefix_width, :suffix_width)]
16
15
  end
17
16
  super
18
17
  end
@@ -20,8 +19,8 @@ module NattyUI
20
19
  # @!visibility private
21
20
  def done
22
21
  return self if @state
23
- NattyUI.back_to_line(@start_line, erase: :all) if @start_line
24
- @pins&.each { |objects, options| puts(*objects, **options) }
22
+ NattyUI.back_to_line(@start_line) if @start_line
23
+ @pins&.each { |objects, opts| puts(*objects, **opts) }
25
24
  @state = :ok
26
25
  self
27
26
  end
@@ -55,7 +55,7 @@ module NattyUI
55
55
  failed: '[bright_red]𝑭[/fg]',
56
56
  current: '[bright_green]➔[/fg]',
57
57
  choice: '[bright_white]◦[/fg]',
58
- current_choice: '[bright_green][/fg]'
58
+ current_choice: '[bright_green][/fg]'
59
59
  )
60
60
  theme.define_section(
61
61
  default: :bright_blue,
@@ -166,11 +166,13 @@ module NattyUI
166
166
  end
167
167
 
168
168
  class Compiled
169
- attr_reader :task_style, :choice_current_style, :choice_style
169
+ attr_reader :task_style,
170
+ :choice_current_style,
171
+ :choice_style,
172
+ :option_states
170
173
 
171
174
  def defined_marks = @mark.keys.sort!
172
175
  def defined_borders = @border.keys.sort!
173
-
174
176
  def heading(index) = @heading[index.to_i.clamp(1, 6) - 1]
175
177
 
176
178
  def mark(value)
@@ -208,12 +210,25 @@ module NattyUI
208
210
  SectionBorder.create(border(theme.section_border)),
209
211
  theme.section_styles.dup.compare_by_identity
210
212
  )
213
+ @option_states = create_option_states
211
214
  end
212
215
 
213
216
  private
214
217
 
215
218
  def as_style(value) = (Ansi[*value].freeze if value)
216
219
 
220
+ def create_option_states
221
+ # [current?][selected?]
222
+ c = @mark[:current_choice]
223
+ n = @mark[:none]
224
+ sel = @mark[:checkmark]
225
+ uns = @mark[:choice]
226
+ {
227
+ false => { false => n + uns, true => n + sel }.compare_by_identity,
228
+ true => { false => c + uns, true => c + sel }.compare_by_identity
229
+ }.compare_by_identity.freeze
230
+ end
231
+
217
232
  def create_sections(template, styles)
218
233
  Hash
219
234
  .new do |h, kind|
@@ -224,7 +239,9 @@ module NattyUI
224
239
 
225
240
  def create_mark(mark)
226
241
  return {} if mark.empty?
227
- with_default(mark.to_h { |n, e| [n.to_sym, Str.new("#{e} ")] })
242
+ mark = mark.to_h { |n, e| [n.to_sym, Str.new("#{e} ")] }
243
+ mark[:none] ||= Str.new('  ', 2)
244
+ with_default(mark)
228
245
  end
229
246
 
230
247
  def create_border(border)
@@ -294,6 +311,7 @@ module NattyUI
294
311
 
295
312
  private_constant :SectionBorder
296
313
  end
314
+ # private_constant :Compiled
297
315
 
298
316
  private
299
317
 
@@ -3,7 +3,6 @@
3
3
  module NattyUI
4
4
  module Utils
5
5
  class << self
6
- # @!visibility private
7
6
  def style(value)
8
7
  value =
9
8
  case value
@@ -22,27 +21,22 @@ module NattyUI
22
21
  value.keep_if { Ansi.valid?(_1) }.empty? ? nil : value
23
22
  end
24
23
 
25
- # @!visibility private
26
24
  def align(value)
27
25
  POS_ALI.include?(value) ? value : :left
28
26
  end
29
27
 
30
- # @!visibility private
31
28
  def position(value)
32
29
  value if POS_ALI.include?(value)
33
30
  end
34
31
 
35
- # @!visibility private
36
32
  def vertical(value)
37
33
  VERT.include?(value) ? value : :top
38
34
  end
39
35
 
40
- # @!visibility private
41
36
  def split_table_attr(values)
42
37
  [values.slice(*TAB_ATTR), values.except(*TAB_ATTR)]
43
38
  end
44
39
 
45
- # @!visibility private
46
40
  def padding(*value)
47
41
  value = value.flatten.take(4).map! { [0, _1.to_i].max }
48
42
  case value.size
@@ -60,7 +54,6 @@ module NattyUI
60
54
  end
61
55
  alias margin padding
62
56
 
63
- # @!visibility private
64
57
  def as_size(range, value)
65
58
  return range.begin if value == :min
66
59
  return range.end if value.nil? || value.is_a?(Symbol)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module NattyUI
4
4
  # The version number of the gem.
5
- VERSION = '0.28.0'
5
+ VERSION = '0.29.0'
6
6
  end
data/lib/natty-ui.rb CHANGED
@@ -36,10 +36,8 @@ module NattyUI
36
36
  # when terminal inoput is not supported
37
37
  def input_mode
38
38
  case Terminal.input_mode
39
- when :csi_u
39
+ when :csi_u, :legacy
40
40
  :default
41
- when :legacy
42
- Terminal.ansi? ? :default : :dumb
43
41
  when :dumb
44
42
  :dumb
45
43
  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.28.0
4
+ version: 0.29.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.12'
18
+ version: 0.12.1
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.12'
25
+ version: 0.12.1
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.
@@ -50,6 +50,7 @@ files:
50
50
  - examples/key-codes.rb
51
51
  - examples/ls.rb
52
52
  - examples/named-colors.rb
53
+ - examples/options.rb
53
54
  - examples/sections.rb
54
55
  - examples/tables.rb
55
56
  - examples/tasks.rb
@@ -58,11 +59,13 @@ files:
58
59
  - lib/natty-ui/attributes.rb
59
60
  - lib/natty-ui/choice.rb
60
61
  - lib/natty-ui/dumb_choice.rb
62
+ - lib/natty-ui/dumb_options.rb
61
63
  - lib/natty-ui/element.rb
62
64
  - lib/natty-ui/features.rb
63
65
  - lib/natty-ui/framed.rb
64
66
  - lib/natty-ui/hbars_renderer.rb
65
67
  - lib/natty-ui/ls_renderer.rb
68
+ - lib/natty-ui/options.rb
66
69
  - lib/natty-ui/progress.rb
67
70
  - lib/natty-ui/section.rb
68
71
  - lib/natty-ui/table.rb
@@ -79,11 +82,11 @@ homepage: https://github.com/mblumtritt/natty-ui
79
82
  licenses:
80
83
  - BSD-3-Clause
81
84
  metadata:
82
- rubygems_mfa_required: 'true'
83
- yard.run: yard
84
85
  source_code_uri: https://github.com/mblumtritt/natty-ui
85
86
  bug_tracker_uri: https://github.com/mblumtritt/natty-ui/issues
86
- documentation_uri: https://rubydoc.info/gems/natty-ui/NattyUI
87
+ documentation_uri: https://rubydoc.info/gems/natty-ui
88
+ rubygems_mfa_required: 'true'
89
+ yard.run: yard
87
90
  rdoc_options: []
88
91
  require_paths:
89
92
  - lib