natty-ui 0.5.1 → 0.5.3

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: d21c8bb3dc22c6d6b18eedf7a4b39306ea43899aa9e27534fa6858c248d4809f
4
- data.tar.gz: 17acf409c7bcd42220c6f1bc5d3ece680ceb9a17fa74eeb9177314a3c693282e
3
+ metadata.gz: 6a717eec681b358c4979684881f16d5217dea7ebacca3baf46f84edfc318d39b
4
+ data.tar.gz: 2829903b6bf15aa81d33259bf77633d6ed6b9e5f88a598bc858b881be94da4cc
5
5
  SHA512:
6
- metadata.gz: 90750739bbcdd5b6121babd1fea66aed45a65a66d6c41d2c87f14ff174ad030d35514d2113cf34772679e40606fd11479756e81e5283ff49df6c298efbe81868
7
- data.tar.gz: d031f5804ce9c6b75b15d815d67809009a854d306859dc4ed1da3ff914136913d5a1e2cc1866c79414f53e26052e5393cf73e5bdd9c25425c73e5cc9fbf234db
6
+ metadata.gz: 274f008deb82e73ba4a6c0b93d2a4e4cea3afdd60284d8fdc8e462e56cf04f6e5bda8a25af1c1707cd5a8c92612d48f445f5d127fb5c6531d183b3b8ac424279
7
+ data.tar.gz: 770c07b0085ac1efd565b141fae6f704899a89b7e8b648fd27e687166a13676edd3a38039d8f4aeae7c490849cf39a5d2d22daed25d6a1c0b9540340b21483f4
data/README.md CHANGED
@@ -40,29 +40,13 @@ UI.framed 'Text Below In Frame' do |framed|
40
40
  end
41
41
  ```
42
42
 
43
- or use progression displays like progress bars and much much more!
43
+ or use progression displays like progress bars.
44
44
 
45
- ![illustration](https://raw.githubusercontent.com/mblumtritt/natty-ui/main/examples/illustration.svg)
46
-
47
- ### But there is more!
48
-
49
- Have a look at the [examples](./examples/) directory to get an impression of the current feature set.
50
-
51
- ```sh
52
- ruby ./examples/basic.rb
53
- ```
54
-
55
- or see the non-ANSI version
56
-
57
- ```sh
58
- NO_COLOR=1 ruby ./examples/basic.rb
59
- ```
45
+ 🚀 There are much more [features](https://rubydoc.info/gems/natty-ui/NattyUI/Features)!
60
46
 
61
- There are much more **[features](https://rubydoc.info/gems/natty-ui/NattyUI/Features)**!
47
+ 📕 See the [online help](https://rubydoc.info/gems/natty-ui/NattyUI) for more details or have a look at the [examples](./examples/) directory to get an impression of the current feature set.
62
48
 
63
- ### NO_COLOR Convention
64
-
65
- NattyUI follows the [NO_COLOR convention](https://no-color.org).
49
+ ![illustration](https://raw.githubusercontent.com/mblumtritt/natty-ui/main/examples/illustration.svg)
66
50
 
67
51
  ## Installation
68
52
 
@@ -84,32 +68,28 @@ After that you only need one line of code to have everything together
84
68
  require 'natty-ui'
85
69
  ```
86
70
 
87
- ## Unicode Support
88
-
89
- Unicode is generally supported. This means that for the calculation of screen outputs the different width of characters is considered. For this the wonderful Gem [unicode/display_width](https://github.com/janlelis/unicode-display_width) is used.
71
+ ## Run Examples
90
72
 
91
- To be able to use Unicode characters that consist of multiple combinations (like some emoji), you have to explicitly load the Gem unicode/emoji _before_ NattyUI. It is not included automatically, because in most cases it is not needed (and we can save the overhead most of the time).
73
+ You can execute the examples by
92
74
 
93
- If you need the full beauty of Unicode just load it in that order:
94
-
95
- ```ruby
96
- require 'unicode/emoji'
97
- require 'natty-ui'
75
+ ```sh
76
+ ruby ./examples/basic.rb
98
77
  ```
99
78
 
100
- **Hint**: The compromise of not automatically supporting emojis results from the fact that not all terminals can output all emojis correctly. You can easily check this yourself by
79
+ or see the non-ANSI version
101
80
 
102
81
  ```sh
103
- echo "👨‍👩‍👦 👩‍❤️‍👨"
82
+ NO_COLOR=1 ruby ./examples/basic.rb
104
83
  ```
105
84
 
106
- in your terminal window.
85
+ ## NO_COLOR Convention
86
+
87
+ NattyUI follows the [NO_COLOR convention](https://no-color.org).
107
88
 
108
89
  ## TODO
109
90
 
110
91
  Since I did not complete the tests and not all my ideas are already implemented I have this Todo list:
111
92
 
112
- - add samples to README
113
93
  - add more samples to help
114
94
  - add more tests
115
95
  - simple prompt
data/examples/basic.rb CHANGED
@@ -5,6 +5,8 @@ require_relative '../lib/natty-ui'
5
5
 
6
6
  UI = NattyUI::StdOut
7
7
 
8
+ UI.space
9
+
8
10
  UI.h1 'NattyUI Basic Feature Demo', <<~TEXT
9
11
 
10
12
  This is a short demo of the basic features of [[i117 bold]]NattyUI[[/]].
data/examples/colors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # require 'natty-ui'
2
4
  require_relative '../lib/natty-ui'
3
5
 
@@ -46,16 +46,16 @@ module NattyUI
46
46
 
47
47
  def title_attr(str, symbol)
48
48
  color = COLORS[symbol]
49
- if color
50
- {
51
- prefix:
49
+ {
50
+ prefix:
51
+ if color
52
52
  "#{Ansi[:bold, :italic, color]}#{str}" \
53
- "#{Ansi[:reset, :bold, color]} ",
54
- suffix: Ansi.reset
55
- }
56
- else
57
- { prefix: "#{Ansi[:bold, 231]}#{str} ", suffix: Ansi.reset }
58
- end
53
+ "#{Ansi[:reset, :bold, color]} "
54
+ else
55
+ "#{Ansi[:bold, 231]}#{str} "
56
+ end,
57
+ suffix: Ansi.reset
58
+ }
59
59
  end
60
60
 
61
61
  COLORS = {
@@ -167,12 +167,6 @@ module NattyUI
167
167
  end
168
168
  end
169
169
 
170
- TITLE_PREFIX = "#{Ansi[:bold, :italic, 117]}➔#{Ansi[:reset, 117]} ".freeze
171
- INDICATOR_ATTRIBUTE = Ansi[:bold, 220].freeze
172
- BAR_COLOR = Ansi[39, 295].freeze
173
- BAR_BACK = Ansi[236, 492].freeze
174
- BAR_INK = Ansi[:bold, 255, :on_default].freeze
175
-
176
170
  def draw_final = (wrapper.stream << Ansi.line_clear).flush
177
171
 
178
172
  def redraw
@@ -194,6 +188,12 @@ module NattyUI
194
188
  )
195
189
  }"
196
190
  end
191
+
192
+ TITLE_PREFIX = "#{Ansi[:bold, :italic, 117]}➔#{Ansi[:reset, 117]} ".freeze
193
+ INDICATOR_ATTRIBUTE = Ansi[:bold, 220].freeze
194
+ BAR_COLOR = Ansi[39, 295].freeze
195
+ BAR_BACK = Ansi[236, 492].freeze
196
+ BAR_INK = Ansi[:bold, 255, :on_default].freeze
197
197
  end
198
198
 
199
199
  PAGE_BEGIN =
@@ -2,5 +2,5 @@
2
2
 
3
3
  module NattyUI
4
4
  # @return [String] the version number of the gem
5
- VERSION = '0.5.1'
5
+ VERSION = '0.5.3'
6
6
  end
@@ -22,6 +22,8 @@ module NattyUI
22
22
  # sec.failed('You should have an opinion!')
23
23
  # end
24
24
  #
25
+ # @see NattyUI.in_stream
26
+ #
25
27
  # @param question [#to_s] Question to display
26
28
  # @param yes [#to_s] chars which will be used to answer 'Yes'
27
29
  # @param no [#to_s] chars which will be used to answer 'No'
@@ -24,17 +24,14 @@ module NattyUI
24
24
 
25
25
  # Close the element.
26
26
  #
27
- # @return [Element] itself when used without a code block
28
- # @return [nil] when used with a code block
27
+ # @return [Element] itself
29
28
  def close = _close(:closed)
30
29
 
31
30
  alias _to_s to_s
32
31
  private :_to_s
33
32
 
34
33
  # @!visibility private
35
- def inspect
36
- "#{_to_s[..-2]} status=#{@status}}}>"
37
- end
34
+ def inspect = "#{_to_s[..-2]} status=#{@status}}}>"
38
35
 
39
36
  protected
40
37
 
@@ -49,9 +46,7 @@ module NattyUI
49
46
  @wrapper
50
47
  end
51
48
 
52
- def initialize(parent)
53
- @parent = parent
54
- end
49
+ def initialize(parent) = (@parent = parent)
55
50
 
56
51
  def _close(state)
57
52
  return self if @status
@@ -11,11 +11,7 @@ module NattyUI
11
11
  wrapper.class.const_get(type).__send__(:new, self).__send__(:_call, *args)
12
12
  end
13
13
 
14
- def _section(type, args, **opts, &block)
15
- __section(self, type, args, **opts, &block)
16
- end
17
-
18
- def __section(owner, type, args, **opts, &block)
14
+ def _section(owner, type, args, **opts, &block)
19
15
  sec = wrapper.class.const_get(type).__send__(:new, owner, **opts)
20
16
  sec.puts(*args) if args && !args.empty?
21
17
  block ? sec.__send__(:_call, &block) : sec
@@ -7,17 +7,18 @@ module NattyUI
7
7
  # Creates frame-enclosed section with a highlighted `title` and
8
8
  # prints given additional arguments as lines into the section.
9
9
  #
10
- # When no block is given, the section must be closed, see {Section#close}.
10
+ # When no block is given, the section must be closed, see
11
+ # {Wrapper::Element#close}.
11
12
  #
12
13
  # @param [#to_s] title object to print as section title
13
14
  # @param [Array<#to_s>] args more objects to print
14
15
  # @param [Symbol] type frame type;
15
16
  # valid types are `:rounded`, `:simple`, `:heavy`, `:semi`, `:double`
16
- # @yieldparam [Wrapper::Framed] section the created section
17
+ # @yieldparam [Wrapper::Framed] framed the created section
17
18
  # @return [Object] the result of the code block
18
19
  # @return [Wrapper::Framed] itself, when no code block is given
19
20
  def framed(title, *args, type: :rounded, &block)
20
- _section(:Framed, args, title: title, type: type, &block)
21
+ _section(self, :Framed, args, title: title, type: type, &block)
21
22
  end
22
23
  end
23
24
 
@@ -7,11 +7,11 @@ module NattyUI
7
7
  # Creates section with a H1 title.
8
8
  #
9
9
  # @param (see #information)
10
- # @yieldparam [Wrapper::Heading] section the created section
10
+ # @yieldparam [Wrapper::Heading] heading the created section
11
11
  # @return [Object] the result of the code block
12
12
  # @return [Wrapper::Heading] itself, when no code block is given
13
13
  def h1(title, *args, &block)
14
- _section(:Heading, args, title: title, weight: 1, &block)
14
+ _section(self, :Heading, args, title: title, weight: 1, &block)
15
15
  end
16
16
 
17
17
  # Creates section with a H2 title.
@@ -20,7 +20,7 @@ module NattyUI
20
20
  # @yieldparam (see #h1)
21
21
  # @return (see #h1)
22
22
  def h2(title, *args, &block)
23
- _section(:Heading, args, title: title, weight: 2, &block)
23
+ _section(self, :Heading, args, title: title, weight: 2, &block)
24
24
  end
25
25
 
26
26
  # Creates section with a H3 title.
@@ -29,7 +29,7 @@ module NattyUI
29
29
  # @yieldparam (see #h1)
30
30
  # @return (see #h1)
31
31
  def h3(title, *args, &block)
32
- _section(:Heading, args, title: title, weight: 3, &block)
32
+ _section(self, :Heading, args, title: title, weight: 3, &block)
33
33
  end
34
34
 
35
35
  # Creates section with a H4 title.
@@ -38,7 +38,7 @@ module NattyUI
38
38
  # @yieldparam (see #h1)
39
39
  # @return (see #h1)
40
40
  def h4(title, *args, &block)
41
- _section(:Heading, args, title: title, weight: 4, &block)
41
+ _section(self, :Heading, args, title: title, weight: 4, &block)
42
42
  end
43
43
 
44
44
  # Creates section with a H5 title.
@@ -47,7 +47,7 @@ module NattyUI
47
47
  # @yieldparam (see #h1)
48
48
  # @return (see #h1)
49
49
  def h5(title, *args, &block)
50
- _section(:Heading, args, title: title, weight: 5, &block)
50
+ _section(self, :Heading, args, title: title, weight: 5, &block)
51
51
  end
52
52
  end
53
53
 
@@ -10,11 +10,11 @@ module NattyUI
10
10
  # @param [#to_s] title object to print as section title
11
11
  # @param [Array<#to_s>] args more objects to print
12
12
  # @param [#to_s] symbol symbol/prefix used for the title
13
- # @yieldparam [Wrapper::Message] section the created section
13
+ # @yieldparam [Wrapper::Message] message the created section
14
14
  # @return [Object] the result of the code block
15
15
  # @return [Wrapper::Message] itself, when no code block is given
16
16
  def message(title, *args, symbol: :default, &block)
17
- _section(:Message, args, title: title, symbol: symbol, &block)
17
+ _section(self, :Message, args, title: title, symbol: symbol, &block)
18
18
  end
19
19
  alias msg message
20
20
 
@@ -26,7 +26,7 @@ module NattyUI
26
26
  # @yieldparam (see #message)
27
27
  # @return (see #message)
28
28
  def information(title, *args, &block)
29
- _section(:Message, args, title: title, symbol: :information, &block)
29
+ _section(self, :Message, args, title: title, symbol: :information, &block)
30
30
  end
31
31
  alias info information
32
32
 
@@ -37,7 +37,7 @@ module NattyUI
37
37
  # @yieldparam (see #message)
38
38
  # @return (see #message)
39
39
  def warning(title, *args, &block)
40
- _section(:Message, args, title: title, symbol: :warning, &block)
40
+ _section(self, :Message, args, title: title, symbol: :warning, &block)
41
41
  end
42
42
  alias warn warning
43
43
 
@@ -48,7 +48,7 @@ module NattyUI
48
48
  # @yieldparam (see #message)
49
49
  # @return (see #message)
50
50
  def error(title, *args, &block)
51
- _section(:Message, args, title: title, symbol: :error, &block)
51
+ _section(self, :Message, args, title: title, symbol: :error, &block)
52
52
  end
53
53
  alias err error
54
54
 
@@ -61,7 +61,7 @@ module NattyUI
61
61
  # @yieldparam (see #message)
62
62
  # @return (see #message)
63
63
  def completed(title, *args, &block)
64
- _section(:Message, args, title: title, symbol: :completed, &block)
64
+ _section(self, :Message, args, title: title, symbol: :completed, &block)
65
65
  end
66
66
  alias done completed
67
67
  alias ok completed
@@ -76,7 +76,7 @@ module NattyUI
76
76
  # @yieldparam (see #message)
77
77
  # @return (see #message)
78
78
  def failed(title, *args, &block)
79
- _section(:Message, args, title: title, symbol: :failed, &block)
79
+ _section(self, :Message, args, title: title, symbol: :failed, &block)
80
80
  end
81
81
  end
82
82
 
@@ -14,7 +14,7 @@ module NattyUI
14
14
  # @param [##to_f] max_value maximum value of the progress
15
15
  # @return [Wrapper::Progress] the created progress element
16
16
  def progress(title, max_value: nil)
17
- _section(:Progress, nil, title: title, max_value: max_value)
17
+ _section(self, :Progress, nil, title: title, max_value: max_value)
18
18
  end
19
19
  end
20
20
 
@@ -24,6 +24,8 @@ module NattyUI
24
24
  # )
25
25
  # # => 'a' or 'b' or 'c' or nil if user aborted
26
26
  #
27
+ # @see NattyUI.in_stream
28
+ #
27
29
  # @param question [#to_s] Question to display
28
30
  # @param choices [#to_s] choices selectable via index (0..9)
29
31
  # @param result [Symbol] defines how the result ist returned
@@ -49,7 +51,7 @@ module NattyUI
49
51
  choices = grab(choices, kw_choices)
50
52
  return if choices.empty?
51
53
  wrapper.temporary do
52
- __section(
54
+ _section(
53
55
  @parent,
54
56
  :Message,
55
57
  choices.map { |k, v| "#{k} #{v}" },
@@ -12,7 +12,7 @@ module NattyUI
12
12
  # @return [Object] the result of the code block
13
13
  # @return [Wrapper::Section] itself, when no code block is given
14
14
  def section(*args, &block)
15
- _section(:Section, args, prefix: ' ', suffix: ' ', &block)
15
+ _section(self, :Section, args, prefix: ' ', suffix: ' ', &block)
16
16
  end
17
17
  alias sec section
18
18
 
@@ -23,13 +23,13 @@ module NattyUI
23
23
  # @yieldparam (see #section)
24
24
  # @return (see #section)
25
25
  def quote(*args, &block)
26
- _section(:Section, args, prefix: '▍ ', prefix_attr: 39, &block)
26
+ _section(self, :Section, args, prefix: '▍ ', prefix_attr: 39, &block)
27
27
  end
28
28
  end
29
29
 
30
30
  class Wrapper
31
31
  #
32
- # Visual element to keep text lines together.
32
+ # Visual {Element} to keep text lines together.
33
33
  #
34
34
  # A section can contain other elements and sections.
35
35
  #
@@ -38,21 +38,23 @@ module NattyUI
38
38
  class Section < Element
39
39
  # Close the section.
40
40
  #
41
- # @return [Section] itself when used without a code block
42
- # @return [nil] when used with a code block
41
+ # @return [Section] itself
43
42
  def close = _close(:closed)
44
43
 
45
44
  # Print given arguments as lines into the section.
45
+ # Optionally limit the line width to given `max_width`.
46
46
  #
47
- # @overload puts(...)
47
+ # @overload puts(..., max_width: nil)
48
48
  # @param [#to_s] ... objects to print
49
+ # @param [Integer, nil] max_width maximum line width
49
50
  # @comment @param [#to_s, nil] prefix line prefix
50
51
  # @comment @param [#to_s, nil] suffix line suffix
51
52
  # @return [Section] itself
52
- def puts(*args, prefix: nil, suffix: nil)
53
+ def puts(*args, max_width: nil, prefix: nil, suffix: nil)
53
54
  return self if @status
54
55
  @parent.puts(
55
56
  *args,
57
+ max_width: max_width,
56
58
  prefix: prefix ? "#{@prefix}#{prefix}" : @prefix,
57
59
  suffix: suffix ? "#{@suffix}#{suffix}" : @suffix
58
60
  )
@@ -66,7 +68,7 @@ module NattyUI
66
68
  # @return [Section] itself
67
69
  def space(lines = 1)
68
70
  @parent.puts(
69
- *Array.new([lines.to_i, 1].max),
71
+ "\n" * ([lines.to_i, 1].max - 1),
70
72
  prefix: @prefix,
71
73
  suffix: @suffix
72
74
  )
@@ -86,9 +88,7 @@ module NattyUI
86
88
  #
87
89
  # @yield [Section] itself
88
90
  # @return [Object] block result
89
- def temporary
90
- block_given? ? yield(self) : self
91
- end
91
+ def temporary = block_given? ? yield(self) : self
92
92
 
93
93
  protected
94
94
 
@@ -11,11 +11,11 @@ module NattyUI
11
11
  # or {#failed}.
12
12
  #
13
13
  # @param (see #information)
14
- # @yieldparam [Wrapper::Task] section the created section
14
+ # @yieldparam [Wrapper::Task] task the created section
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(:Task, args, title: title, &block)
18
+ _section(self, :Task, args, title: title, &block)
19
19
  end
20
20
  end
21
21
 
@@ -34,7 +34,7 @@ module NattyUI
34
34
  @status = :completed if @status == :closed
35
35
  @temp.call
36
36
  end
37
- __section(
37
+ _section(
38
38
  @parent,
39
39
  :Message,
40
40
  @final_text,
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'stringio'
4
3
  require_relative 'wrapper/ask'
5
4
  require_relative 'wrapper/framed'
6
5
  require_relative 'wrapper/heading'
@@ -28,13 +27,13 @@ module NattyUI
28
27
  # @return [[Integer, Integer]] screen size as rows and columns
29
28
  def screen_size
30
29
  return @stream.winsize if @ws
31
- [ENV['LINES'].to_i.nonzero? || 25, ENV['COLUMNS'].to_i.nonzero? || 80]
30
+ [ENV['LINES'].to_i.nonzero? || 24, ENV['COLUMNS'].to_i.nonzero? || 80]
32
31
  end
33
32
 
34
33
  # @attribute [r] screen_rows
35
34
  # @return [Integer] number of screen rows
36
35
  def screen_rows
37
- @ws ? @stream.winsize[0] : (ENV['LINES'].to_i.nonzero? || 25)
36
+ @ws ? @stream.winsize[0] : (ENV['LINES'].to_i.nonzero? || 24)
38
37
  end
39
38
 
40
39
  # @attribute [r] screen_columns
@@ -46,24 +45,22 @@ module NattyUI
46
45
  # @!group Tool functions
47
46
 
48
47
  # Print given arguments as lines to the output stream.
48
+ # Optionally limit the line width to given `max_width`.
49
49
  #
50
- # @overload puts(...)
50
+ # @overload puts(..., max_width: nil)
51
51
  # @param [#to_s] ... objects to print
52
+ # @param [Integer, nil] max_width maximum line width
52
53
  # @comment @param [#to_s, nil] prefix line prefix
53
54
  # @comment @param [#to_s, nil] suffix line suffix
54
55
  # @return [Wrapper] itself
55
- def puts(*args, prefix: nil, suffix: nil)
56
+ def puts(*args, max_width: nil, prefix: nil, suffix: nil)
56
57
  if args.empty?
57
58
  @stream.puts(embellish("#{prefix}#{suffix}"))
58
59
  @lines_written += 1
59
60
  else
60
- StringIO.open do |io|
61
- io.puts(*args)
62
- io.rewind
63
- io.each(chomp: true) do |line|
64
- @stream.puts(embellish("#{prefix}#{line}#{suffix}"))
65
- @lines_written += 1
66
- end
61
+ NattyUI.each_line(*args, max_width: max_width) do |line|
62
+ @stream.puts(embellish("#{prefix}#{line}#{suffix}"))
63
+ @lines_written += 1
67
64
  end
68
65
  end
69
66
  @stream.flush
@@ -77,7 +74,7 @@ module NattyUI
77
74
  # @return [Wrapper] itself
78
75
  def space(lines = 1)
79
76
  lines = [lines.to_i, 1].max
80
- @stream.puts(*Array.new(lines))
77
+ @stream << ("\n" * lines)
81
78
  @lines_written += lines
82
79
  @stream.flush
83
80
  self
@@ -154,7 +151,7 @@ module NattyUI
154
151
  def initialize(stream)
155
152
  @stream = stream
156
153
  @lines_written = 0
157
- @ws = stream.respond_to?(:winsize) && stream.winsize&.size == 2
154
+ @ws = stream.respond_to?(:winsize) && stream.winsize&.all?(&:positive?)
158
155
  rescue Errno::ENOTTY
159
156
  @ws = false
160
157
  end
data/lib/natty-ui.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'unicode/display_width'
3
+ require 'readline'
4
+ unless defined?(Reline)
5
+ # only load the Reline::Unicode part
6
+ # @!visibility private
7
+ module Reline
8
+ def self.ambiguous_width = 1
9
+ end
10
+ require 'reline/unicode'
11
+ end
4
12
  require_relative 'natty-ui/wrapper'
5
13
  require_relative 'natty-ui/ansi_wrapper'
6
14
 
@@ -71,7 +79,7 @@ module NattyUI
71
79
  # @return ]String] edited string
72
80
  def embellish(str)
73
81
  str = str.to_s
74
- return '' if str.empty?
82
+ return +'' if str.empty?
75
83
  reset = false
76
84
  ret =
77
85
  str.gsub(/(\[\[((?~\]\]))\]\])/) do
@@ -111,10 +119,56 @@ module NattyUI
111
119
  # @return [Integer] the display size
112
120
  def display_width(str)
113
121
  str = str.to_s
114
- return 0 if str.empty?
115
- ret = Unicode::DisplayWidth.of(str, 1)
116
- ret -= emoji_extra_width_of(str) if defined?(Unicode::Emoji)
117
- [ret, 0].max
122
+ str.empty? ? 0 : Reline::Unicode.calculate_width(str)
123
+ end
124
+
125
+ # Convert given arguments into strings and yield each line.
126
+ # Optionally limit the line width to given `max_width`.
127
+ #
128
+ # @overload each_line(..., max_width: nil)
129
+ # @param [#to_s] ... objects to print
130
+ # @param [#to_i, nil] max_width maximum line width
131
+ # @yieldparam [String] line string line
132
+ # @return [nil]
133
+ # @overload each_line(..., max_width: nil)
134
+ # @param [#to_s] ... objects to print
135
+ # @param [#to_i, nil] max_width maximum line width
136
+ # @return [Enumerator] line enumerator
137
+ def each_line(*strs, max_width: nil, &block)
138
+ return to_enum(__method__, *strs, max_width: max_width) unless block
139
+ unless max_width
140
+ strs.each { |str| str.to_s.each_line(chomp: true, &block) }
141
+ return nil
142
+ end
143
+ max_width = max_width.to_i
144
+ return if max_width <= 0
145
+ strs.each do |str|
146
+ str
147
+ .to_s
148
+ .each_line(chomp: true) do |line|
149
+ Reline::Unicode.split_by_width(line, max_width)[0].each do |part|
150
+ yield(part) if part
151
+ end
152
+ end
153
+ end
154
+ nil
155
+ end
156
+
157
+ # Read user input line from {.in_stream}.
158
+ #
159
+ # @see .valid_out?
160
+ #
161
+ # @param [#to_s] prompt input prompt
162
+ # @param [IO] stream writeable IO used to display output
163
+ # @return [String] user input line
164
+ # @return [nil] when user interrputed input with `^C` or `^D`
165
+ def readline(prompt = nil, stream: StdOut.stream)
166
+ Readline.output = stream
167
+ Readline.input = @in_stream
168
+ Readline.readline(prompt.to_s)
169
+ rescue Interrupt
170
+ stream.puts
171
+ nil
118
172
  end
119
173
 
120
174
  private
@@ -125,17 +179,6 @@ module NattyUI
125
179
  stream.tty? ? AnsiWrapper : Wrapper
126
180
  end
127
181
 
128
- def emoji_extra_width_of(string)
129
- ret = 0
130
- string.scan(Unicode::Emoji::REGEX) do |emoji|
131
- ret += 2 * emoji.scan(EMOJI_MODIFIER_REGEX).size
132
- emoji.scan(EMOKI_ZWJ_REGEX) do |zwj_succ|
133
- ret += Unicode::DisplayWidth.of(zwj_succ, 1, {})
134
- end
135
- end
136
- ret
137
- end
138
-
139
182
  def stderr_is_stdout?
140
183
  STDOUT.tty? && STDERR.tty? && STDOUT.pos == STDERR.pos
141
184
  rescue IOError, SystemCallError
@@ -143,12 +186,6 @@ module NattyUI
143
186
  end
144
187
  end
145
188
 
146
- if defined?(Unicode::Emoji)
147
- EMOJI_MODIFIER_REGEX = /[#{Unicode::Emoji::EMOJI_MODIFIERS.pack('U*')}]/
148
- EMOKI_ZWJ_REGEX = /(?<=#{[Unicode::Emoji::ZWJ].pack('U')})./
149
- private_constant :EMOJI_MODIFIER_REGEX, :EMOKI_ZWJ_REGEX
150
- end
151
-
152
189
  # Instance for standard output.
153
190
  StdOut = new(STDOUT)
154
191
 
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: natty-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-09 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: unicode-display_width
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '2.5'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '2.5'
11
+ date: 2023-11-11 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description: |
28
14
  This is the beautiful, nice, nifty, fancy, neat, pretty, cool, lovely,
29
15
  natty user interface you like to have for your command line interfaces