cli-ui 2.4.0 → 2.6.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.
@@ -6,11 +6,9 @@ require 'cli/ui/frame'
6
6
  module CLI
7
7
  module UI
8
8
  module Frame
9
+ # @abstract
9
10
  module FrameStyle
10
11
  include Kernel
11
- extend T::Sig
12
- extend T::Helpers
13
- abstract!
14
12
 
15
13
  autoload(:Box, 'cli/ui/frame/frame_style/box')
16
14
  autoload(:Bracket, 'cli/ui/frame/frame_style/bracket')
@@ -21,14 +19,12 @@ module CLI
21
19
  }
22
20
 
23
21
  class << self
24
- extend T::Sig
25
-
26
22
  # Lookup a frame style via its name
27
23
  #
28
24
  # ==== Attributes
29
25
  #
30
26
  # * +symbol+ - frame style name to lookup
31
- sig { params(name: T.any(String, Symbol)).returns(FrameStyle) }
27
+ #: ((String | Symbol) name) -> FrameStyle
32
28
  def lookup(name)
33
29
  MAP.fetch(name.to_sym).call
34
30
  rescue KeyError
@@ -36,16 +32,22 @@ module CLI
36
32
  end
37
33
  end
38
34
 
39
- sig { abstract.returns(Symbol) }
40
- def style_name; end
35
+ # @abstract
36
+ #: -> Symbol
37
+ def style_name
38
+ raise(NotImplementedError)
39
+ end
41
40
 
42
41
  # Returns the character(s) that should be printed at the beginning
43
42
  # of lines inside this frame
44
- sig { abstract.returns(String) }
45
- def prefix; end
43
+ # @abstract
44
+ #: -> String
45
+ def prefix
46
+ raise(NotImplementedError)
47
+ end
46
48
 
47
49
  # Returns the printing width of the prefix
48
- sig { returns(Integer) }
50
+ #: -> Integer
49
51
  def prefix_width
50
52
  CLI::UI::ANSI.printing_width(prefix)
51
53
  end
@@ -60,8 +62,11 @@ module CLI
60
62
  #
61
63
  # * +:color+ - (required) The color of the frame.
62
64
  #
63
- sig { abstract.params(text: String, color: CLI::UI::Color).returns(String) }
64
- def start(text, color:); end
65
+ # @abstract
66
+ #: (String, color: CLI::UI::Color) -> String
67
+ def start(text, color:)
68
+ raise(NotImplementedError)
69
+ end
65
70
 
66
71
  # Draws the "Close" line for this frame style
67
72
  #
@@ -74,8 +79,11 @@ module CLI
74
79
  # * +:color+ - (required) The color of the frame.
75
80
  # * +:right_text+ - Text to print at the right of the line. Defaults to nil
76
81
  #
77
- sig { abstract.params(text: String, color: CLI::UI::Color, right_text: T.nilable(String)).returns(String) }
78
- def close(text, color:, right_text: nil); end
82
+ # @abstract
83
+ #: (String, color: CLI::UI::Color, ?right_text: String?) -> String
84
+ def close(text, color:, right_text: nil)
85
+ raise(NotImplementedError)
86
+ end
79
87
 
80
88
  # Draws a "divider" line for the current frame style
81
89
  #
@@ -87,24 +95,25 @@ module CLI
87
95
  #
88
96
  # * +:color+ - (required) The color of the frame.
89
97
  #
90
- sig { abstract.params(text: String, color: CLI::UI::Color).returns(String) }
91
- def divider(text, color:); end
98
+ # @abstract
99
+ #: (String, color: CLI::UI::Color) -> String
100
+ def divider(text, color:)
101
+ raise(NotImplementedError)
102
+ end
92
103
 
93
- sig { params(x: Integer, str: String).returns(String) }
104
+ #: (Integer x, String str) -> String
94
105
  def print_at_x(x, str)
95
106
  CLI::UI::ANSI.cursor_horizontal_absolute(1 + x) + str
96
107
  end
97
108
 
98
109
  class InvalidFrameStyleName < ArgumentError
99
- extend T::Sig
100
-
101
- sig { params(name: T.any(String, Symbol)).void }
110
+ #: ((String | Symbol) name) -> void
102
111
  def initialize(name)
103
112
  super
104
113
  @name = name
105
114
  end
106
115
 
107
- sig { returns(String) }
116
+ #: -> String
108
117
  def message
109
118
  keys = FrameStyle::MAP.keys.map(&:inspect).join(', ')
110
119
  "invalid frame style: #{@name.inspect} " \
data/lib/cli/ui/frame.rb CHANGED
@@ -12,9 +12,7 @@ module CLI
12
12
  DEFAULT_FRAME_COLOR = CLI::UI.resolve_color(:cyan)
13
13
 
14
14
  class << self
15
- extend T::Sig
16
-
17
- sig { returns(FrameStyle) }
15
+ #: -> FrameStyle
18
16
  def frame_style
19
17
  @frame_style ||= FrameStyle::Box
20
18
  end
@@ -27,7 +25,7 @@ module CLI
27
25
  #
28
26
  # * +symbol+ or +FrameStyle+ - the default frame style to use for frames
29
27
  #
30
- sig { params(frame_style: FrameStylable).void }
28
+ #: (frame_stylable frame_style) -> void
31
29
  def frame_style=(frame_style)
32
30
  @frame_style = CLI::UI.resolve_style(frame_style)
33
31
  end
@@ -75,18 +73,7 @@ module CLI
75
73
  # ┏━━ Open ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
76
74
  #
77
75
  #
78
- sig do
79
- type_parameters(:T).params(
80
- text: String,
81
- color: Colorable,
82
- failure_text: T.nilable(String),
83
- success_text: T.nilable(String),
84
- timing: T.any(T::Boolean, Numeric),
85
- frame_style: FrameStylable,
86
- to: IOLike,
87
- block: T.nilable(T.proc.returns(T.type_parameter(:T))),
88
- ).returns(T.nilable(T.type_parameter(:T)))
89
- end
76
+ #: [T] (String text, ?color: colorable, ?failure_text: String?, ?success_text: String?, ?timing: (Numeric | bool), ?frame_style: frame_stylable, ?to: io_like) ?{ -> T } -> T?
90
77
  def open(
91
78
  text,
92
79
  color: DEFAULT_FRAME_COLOR,
@@ -121,7 +108,7 @@ module CLI
121
108
 
122
109
  closed = false
123
110
  begin
124
- success = false
111
+ success = false #: untyped
125
112
  success = yield
126
113
  rescue
127
114
  closed = true
@@ -133,7 +120,8 @@ module CLI
133
120
  ensure
134
121
  unless closed
135
122
  t_diff = elapsed(t_start, timing)
136
- if T.unsafe(success) != false
123
+ success_bool = success #: as untyped
124
+ if success_bool != false
137
125
  close(success_text, color: color, elapsed: t_diff, to: to)
138
126
  else
139
127
  close(failure_text, color: :red, elapsed: t_diff, to: to)
@@ -169,14 +157,7 @@ module CLI
169
157
  #
170
158
  # MUST be inside an open frame or it raises a +UnnestedFrameException+
171
159
  #
172
- sig do
173
- params(
174
- text: T.nilable(String),
175
- color: T.nilable(Colorable),
176
- frame_style: T.nilable(FrameStylable),
177
- to: IOLike,
178
- ).void
179
- end
160
+ #: (String? text, ?color: colorable?, ?frame_style: frame_stylable?, ?to: io_like) -> void
180
161
  def divider(text, color: nil, frame_style: nil, to: $stdout)
181
162
  fs_item = FrameStack.pop
182
163
  raise UnnestedFrameException, 'No frame nesting to unnest' unless fs_item
@@ -218,15 +199,7 @@ module CLI
218
199
  #
219
200
  # MUST be inside an open frame or it raises a +UnnestedFrameException+
220
201
  #
221
- sig do
222
- params(
223
- text: T.nilable(String),
224
- color: T.nilable(Colorable),
225
- elapsed: T.nilable(Numeric),
226
- frame_style: T.nilable(FrameStylable),
227
- to: IOLike,
228
- ).void
229
- end
202
+ #: (String? text, ?color: colorable?, ?elapsed: Numeric?, ?frame_style: frame_stylable?, ?to: io_like) -> void
230
203
  def close(text, color: nil, elapsed: nil, frame_style: nil, to: $stdout)
231
204
  fs_item = FrameStack.pop
232
205
  raise UnnestedFrameException, 'No frame nesting to unnest' unless fs_item
@@ -247,7 +220,7 @@ module CLI
247
220
  #
248
221
  # * +:color+ - The color of the prefix. Defaults to +Thread.current[:cliui_frame_color_override]+
249
222
  #
250
- sig { params(color: T.nilable(Colorable)).returns(String) }
223
+ #: (?color: colorable?) -> String
251
224
  def prefix(color: Thread.current[:cliui_frame_color_override])
252
225
  (+'').tap do |output|
253
226
  items = FrameStack.items
@@ -269,7 +242,7 @@ module CLI
269
242
  end
270
243
 
271
244
  # The width of a prefix given the number of Frames in the stack
272
- sig { returns(Integer) }
245
+ #: -> Integer
273
246
  def prefix_width
274
247
  w = FrameStack.items.reduce(0) do |width, item|
275
248
  width + item.frame_style.prefix_width
@@ -284,11 +257,7 @@ module CLI
284
257
  #
285
258
  # * +color+ - The color to override to
286
259
  #
287
- sig do
288
- type_parameters(:T)
289
- .params(color: Colorable, block: T.proc.returns(T.type_parameter(:T)))
290
- .returns(T.type_parameter(:T))
291
- end
260
+ #: [T] (colorable color) { -> T } -> T
292
261
  def with_frame_color_override(color, &block)
293
262
  prev = Thread.current[:cliui_frame_color_override]
294
263
  Thread.current[:cliui_frame_color_override] = color
@@ -303,7 +272,7 @@ module CLI
303
272
  # Numeric: return it
304
273
  # false: return nil
305
274
  # true: defaults to Time.new
306
- sig { params(start: Time, timing: T.any(Numeric, T::Boolean)).returns(T.nilable(Numeric)) }
275
+ #: (Time start, (Numeric | bool) timing) -> Numeric?
307
276
  def elapsed(start, timing)
308
277
  return timing if timing.is_a?(Numeric)
309
278
  return if timing.is_a?(FalseClass)
data/lib/cli/ui/glyph.rb CHANGED
@@ -6,18 +6,14 @@ require 'cli/ui'
6
6
  module CLI
7
7
  module UI
8
8
  class Glyph
9
- extend T::Sig
10
-
11
9
  class InvalidGlyphHandle < ArgumentError
12
- extend T::Sig
13
-
14
- sig { params(handle: String).void }
10
+ #: (String handle) -> void
15
11
  def initialize(handle)
16
12
  super
17
13
  @handle = handle
18
14
  end
19
15
 
20
- sig { returns(String) }
16
+ #: -> String
21
17
  def message
22
18
  keys = Glyph.available.join(',')
23
19
  "invalid glyph handle: #{@handle} " \
@@ -25,13 +21,13 @@ module CLI
25
21
  end
26
22
  end
27
23
 
28
- sig { returns(String) }
24
+ #: String
29
25
  attr_reader :handle, :to_s, :fmt, :char
30
26
 
31
- sig { returns(T.any(Integer, T::Array[Integer])) }
27
+ #: (Integer | Array[Integer])
32
28
  attr_reader :codepoint
33
29
 
34
- sig { returns(Color) }
30
+ #: Color
35
31
  attr_reader :color
36
32
 
37
33
  # Creates a new glyph
@@ -43,7 +39,7 @@ module CLI
43
39
  # * +plain+ - A fallback plain string to be used in case glyphs are disabled
44
40
  # * +color+ - What color to output the glyph. Check +CLI::UI::Color+ for options.
45
41
  #
46
- sig { params(handle: String, codepoint: T.any(Integer, T::Array[Integer]), plain: String, color: Color).void }
42
+ #: (String handle, (Integer | Array[Integer]) codepoint, String plain, Color color) -> void
47
43
  def initialize(handle, codepoint, plain, color)
48
44
  @handle = handle
49
45
  @codepoint = codepoint
@@ -68,8 +64,6 @@ module CLI
68
64
  WARNING = new('!', [0x26a0, 0xfe0f], '!', Color::YELLOW) # WARNING SIGN + VARIATION SELECTOR 16 (⚠️ )
69
65
 
70
66
  class << self
71
- extend T::Sig
72
-
73
67
  # Looks up a glyph by name
74
68
  #
75
69
  # ==== Raises
@@ -79,7 +73,7 @@ module CLI
79
73
  # ==== Returns
80
74
  # Returns a terminal output-capable string
81
75
  #
82
- sig { params(name: String).returns(Glyph) }
76
+ #: (String name) -> Glyph
83
77
  def lookup(name)
84
78
  MAP.fetch(name.to_s)
85
79
  rescue KeyError
@@ -88,7 +82,7 @@ module CLI
88
82
 
89
83
  # All available glyphs by name
90
84
  #
91
- sig { returns(T::Array[String]) }
85
+ #: -> Array[String]
92
86
  def available
93
87
  MAP.keys
94
88
  end
data/lib/cli/ui/os.rb CHANGED
@@ -6,9 +6,7 @@ require 'rbconfig'
6
6
  module CLI
7
7
  module UI
8
8
  class OS
9
- extend T::Sig
10
-
11
- sig { params(emoji: T::Boolean, color_prompt: T::Boolean, arrow_keys: T::Boolean, shift_cursor: T::Boolean).void }
9
+ #: (?emoji: bool, ?color_prompt: bool, ?arrow_keys: bool, ?shift_cursor: bool) -> void
12
10
  def initialize(emoji: true, color_prompt: true, arrow_keys: true, shift_cursor: false)
13
11
  @emoji = emoji
14
12
  @color_prompt = color_prompt
@@ -16,30 +14,28 @@ module CLI
16
14
  @shift_cursor = shift_cursor
17
15
  end
18
16
 
19
- sig { returns(T::Boolean) }
17
+ #: -> bool
20
18
  def use_emoji?
21
19
  @emoji
22
20
  end
23
21
 
24
- sig { returns(T::Boolean) }
22
+ #: -> bool
25
23
  def use_color_prompt?
26
24
  @color_prompt
27
25
  end
28
26
 
29
- sig { returns(T::Boolean) }
27
+ #: -> bool
30
28
  def suggest_arrow_keys?
31
29
  @arrow_keys
32
30
  end
33
31
 
34
- sig { returns(T::Boolean) }
32
+ #: -> bool
35
33
  def shift_cursor_back_on_horizontal_absolute?
36
34
  @shift_cursor
37
35
  end
38
36
 
39
37
  class << self
40
- extend T::Sig
41
-
42
- sig { returns(OS) }
38
+ #: -> OS
43
39
  def current
44
40
  @current_os ||= case RbConfig::CONFIG['host_os']
45
41
  when /darwin/
@@ -6,11 +6,7 @@ require 'cli/ui'
6
6
  module CLI
7
7
  module UI
8
8
  class Printer
9
- extend T::Sig
10
-
11
9
  class << self
12
- extend T::Sig
13
-
14
10
  # Print a message to a stream with common utilities.
15
11
  # Allows overriding the color, encoding, and target stream.
16
12
  # By default, it formats the string using CLI:UI and rescues common stream errors.
@@ -36,17 +32,7 @@ module CLI
36
32
  #
37
33
  # CLI::UI::Printer.puts('{{x}} Ouch', to: $stderr)
38
34
  #
39
- sig do
40
- params(
41
- msg: String,
42
- frame_color: T.nilable(Colorable),
43
- to: IOLike,
44
- encoding: T.nilable(Encoding),
45
- format: T::Boolean,
46
- graceful: T::Boolean,
47
- wrap: T::Boolean,
48
- ).returns(T::Boolean)
49
- end
35
+ #: (String msg, ?frame_color: colorable?, ?to: io_like, ?encoding: Encoding?, ?format: bool, ?graceful: bool, ?wrap: bool) -> bool
50
36
  def puts(
51
37
  msg,
52
38
  frame_color: nil,
@@ -6,16 +6,12 @@ require 'cli/ui'
6
6
  module CLI
7
7
  module UI
8
8
  class Progress
9
- extend T::Sig
10
-
11
9
  # A Cyan filled block
12
10
  FILLED_BAR = "\e[46m"
13
11
  # A bright white block
14
12
  UNFILLED_BAR = "\e[1;47m"
15
13
 
16
14
  class << self
17
- extend T::Sig
18
-
19
15
  # Add a progress bar to the terminal output
20
16
  #
21
17
  # https://user-images.githubusercontent.com/3074765/33799794-cc4c940e-dd00-11e7-9bdc-90f77ec9167c.gif
@@ -42,21 +38,17 @@ module CLI
42
38
  # bar.tick(percent: 0.05)
43
39
  # bar.update_title('New title')
44
40
  # end
45
- sig do
46
- type_parameters(:T)
47
- .params(
48
- title: T.nilable(String),
49
- width: Integer,
50
- block: T.proc.params(bar: Progress).returns(T.type_parameter(:T)),
51
- )
52
- .returns(T.type_parameter(:T))
53
- end
41
+ #: [T] (?String? title, ?width: Integer) { (Progress bar) -> T } -> T
54
42
  def progress(title = nil, width: Terminal.width, &block)
55
- bar = Progress.new(title, width: width)
56
- print(CLI::UI::ANSI.hide_cursor)
57
- yield(bar)
43
+ bar = nil #: Progress?
44
+ CLI::UI::ProgressReporter.with_progress(mode: :progress) do |reporter|
45
+ bar = Progress.new(title, width: width, reporter: reporter)
46
+ print(CLI::UI::ANSI.hide_cursor)
47
+ yield(bar)
48
+ end
58
49
  ensure
59
- puts(bar)
50
+ puts(bar) if bar
51
+
60
52
  CLI::UI.raw do
61
53
  print(ANSI.show_cursor)
62
54
  end
@@ -69,12 +61,14 @@ module CLI
69
61
  #
70
62
  # * +:title+ - The title of the progress bar
71
63
  # * +:width+ - The width of the terminal
64
+ # * +:reporter+ - The progress reporter instance
72
65
  #
73
- sig { params(title: T.nilable(String), width: Integer).void }
74
- def initialize(title = nil, width: Terminal.width)
75
- @percent_done = T.let(0, Numeric)
66
+ #: (?String? title, ?width: Integer, ?reporter: ProgressReporter::Reporter?) -> void
67
+ def initialize(title = nil, width: Terminal.width, reporter: nil)
68
+ @percent_done = 0 #: Numeric
76
69
  @title = title
77
70
  @max_width = width
71
+ @reporter = reporter
78
72
  end
79
73
 
80
74
  # Set the progress of the bar. Typically used in a +Progress.progress+ block
@@ -87,7 +81,7 @@ module CLI
87
81
  #
88
82
  # *Note:* The +:percent+ and +:set_percent must be between 0.00 and 1.0
89
83
  #
90
- sig { params(percent: T.nilable(Numeric), set_percent: T.nilable(Numeric)).void }
84
+ #: (?percent: Numeric?, ?set_percent: Numeric?) -> void
91
85
  def tick(percent: nil, set_percent: nil)
92
86
  raise ArgumentError, 'percent and set_percent cannot both be specified' if percent && set_percent
93
87
 
@@ -95,6 +89,9 @@ module CLI
95
89
  @percent_done = set_percent if set_percent
96
90
  @percent_done = [@percent_done, 1.0].min # Make sure we can't go above 1.0
97
91
 
92
+ # Update terminal progress reporter with current percentage
93
+ @reporter&.set_progress((@percent_done * 100).floor)
94
+
98
95
  print(self)
99
96
 
100
97
  printed_lines = @title ? 2 : 1
@@ -107,14 +104,14 @@ module CLI
107
104
  #
108
105
  # * +new_title+ - title to change the progress bar to
109
106
  #
110
- sig { params(new_title: String).void }
107
+ #: (String new_title) -> void
111
108
  def update_title(new_title)
112
109
  @title = new_title
113
110
  end
114
111
 
115
112
  # Format the progress bar to be printed to terminal
116
113
  #
117
- sig { returns(String) }
114
+ #: -> String
118
115
  def to_s
119
116
  suffix = " #{(@percent_done * 100).floor}%".ljust(5)
120
117
  workable_width = @max_width - Frame.prefix_width - suffix.size