cli-kit 5.1.0 → 5.2.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,24 +6,22 @@ module CLI
6
6
  module Kit
7
7
  module Args
8
8
  class Definition
9
- extend T::Sig
10
-
11
9
  Error = Class.new(Args::Error)
12
10
  ConflictingFlag = Class.new(Error)
13
11
  InvalidFlag = Class.new(Error)
14
12
  InvalidLookup = Class.new(Error)
15
13
  InvalidPosition = Class.new(Error)
16
14
 
17
- sig { returns(T::Array[Flag]) }
15
+ #: Array[Flag]
18
16
  attr_reader :flags
19
17
 
20
- sig { returns(T::Array[Option]) }
18
+ #: Array[Option]
21
19
  attr_reader :options
22
20
 
23
- sig { returns(T::Array[Position]) }
21
+ #: Array[Position]
24
22
  attr_reader :positions
25
23
 
26
- sig { params(name: Symbol, short: T.nilable(String), long: T.nilable(String), desc: T.nilable(String)).void }
24
+ #: (Symbol name, ?short: String?, ?long: String?, ?desc: String?) -> void
27
25
  def add_flag(name, short: nil, long: nil, desc: nil)
28
26
  short, long = strip_prefixes_and_validate(short, long)
29
27
  flag = Flag.new(name: name, short: short, long: long, desc: desc)
@@ -31,18 +29,7 @@ module CLI
31
29
  @flags << flag
32
30
  end
33
31
 
34
- sig do
35
- params(
36
- name: Symbol, short: T.nilable(String), long: T.nilable(String),
37
- desc: T.nilable(String),
38
- default: T.any(
39
- NilClass,
40
- String, T.proc.returns(String),
41
- T::Array[String], T.proc.returns(T::Array[String])
42
- ),
43
- required: T::Boolean, multi: T::Boolean
44
- ).void
45
- end
32
+ #: (Symbol name, ?short: String?, ?long: String?, ?desc: String?, ?default: (String | ^-> String | Array[String] | ^-> Array[String])?, ?required: bool, ?multi: bool) -> void
46
33
  def add_option(name, short: nil, long: nil, desc: nil, default: nil, required: false, multi: false)
47
34
  short, long = strip_prefixes_and_validate(short, long)
48
35
  option = Option.new(
@@ -53,20 +40,7 @@ module CLI
53
40
  @options << option
54
41
  end
55
42
 
56
- sig do
57
- params(
58
- name: Symbol,
59
- required: T::Boolean,
60
- multi: T::Boolean,
61
- desc: T.nilable(String),
62
- default: T.any(NilClass, String, T.proc.returns(String)),
63
- skip: T.any(
64
- NilClass,
65
- T.proc.returns(T::Boolean),
66
- T.proc.params(arg0: String).returns(T::Boolean),
67
- ),
68
- ).void
69
- end
43
+ #: (Symbol name, required: bool, multi: bool, ?desc: String?, ?default: (String | ^-> String)?, ?skip: (^-> bool | ^(String arg0) -> bool)?) -> void
70
44
  def add_position(name, required:, multi:, desc: nil, default: nil, skip: nil)
71
45
  position = Position.new(
72
46
  name: name, desc: desc, required: required, multi: multi,
@@ -77,7 +51,7 @@ module CLI
77
51
  @positions << position
78
52
  end
79
53
 
80
- sig { void }
54
+ #: -> void
81
55
  def initialize
82
56
  @flags = []
83
57
  @options = []
@@ -88,19 +62,15 @@ module CLI
88
62
  end
89
63
 
90
64
  module OptBase
91
- extend T::Sig
92
-
93
- sig { returns(Symbol) }
65
+ #: Symbol
94
66
  attr_reader :name
95
67
 
96
- sig { returns(T.nilable(String)) }
68
+ #: String?
97
69
  attr_reader :desc
98
70
  end
99
71
 
100
72
  module OptValue
101
- extend T::Sig
102
-
103
- sig { returns(T.any(NilClass, String, T::Array[String])) }
73
+ #: -> (String | Array[String])?
104
74
  def default
105
75
  if @default.is_a?(Proc)
106
76
  @default.call
@@ -109,43 +79,42 @@ module CLI
109
79
  end
110
80
  end
111
81
 
112
- sig { returns(T::Boolean) }
82
+ #: -> bool
113
83
  def dynamic_default?
114
84
  @default.is_a?(Proc)
115
85
  end
116
86
 
117
- sig { returns(T::Boolean) }
87
+ #: -> bool
118
88
  def required?
119
89
  @required
120
90
  end
121
91
 
122
- sig { returns(T::Boolean) }
92
+ #: -> bool
123
93
  def multi?
124
94
  @multi
125
95
  end
126
96
 
127
- sig { returns(T::Boolean) }
97
+ #: -> bool
128
98
  def optional?
129
99
  !required?
130
100
  end
131
101
  end
132
102
 
133
103
  class Flag
134
- extend T::Sig
135
104
  include OptBase
136
105
 
137
- sig { returns(T.nilable(String)) }
106
+ #: String?
138
107
  attr_reader :short
139
108
 
140
- sig { returns(T.nilable(String)) }
109
+ #: String?
141
110
  attr_reader :long
142
111
 
143
- sig { returns(String) }
112
+ #: -> String
144
113
  def as_written_by_user
145
114
  long ? "--#{long}" : "-#{short}"
146
115
  end
147
116
 
148
- sig { params(name: Symbol, short: T.nilable(String), long: T.nilable(String), desc: T.nilable(String)).void }
117
+ #: (name: Symbol, ?short: String?, ?long: String?, ?desc: String?) -> void
149
118
  def initialize(name:, short: nil, long: nil, desc: nil)
150
119
  if long&.start_with?('-') || short&.start_with?('-')
151
120
  raise(ArgumentError, 'invalid - prefix')
@@ -159,24 +128,10 @@ module CLI
159
128
  end
160
129
 
161
130
  class Position
162
- extend T::Sig
163
131
  include OptBase
164
132
  include OptValue
165
133
 
166
- sig do
167
- params(
168
- name: Symbol,
169
- desc: T.nilable(String),
170
- required: T::Boolean,
171
- multi: T::Boolean,
172
- default: T.any(NilClass, String, T.proc.returns(String)),
173
- skip: T.any(
174
- NilClass,
175
- T.proc.returns(T::Boolean),
176
- T.proc.params(arg0: String).returns(T::Boolean),
177
- ),
178
- ).void
179
- end
134
+ #: (name: Symbol, desc: String?, required: bool, multi: bool, ?default: (String | ^-> String)?, ?skip: (^-> bool | ^(String arg0) -> bool)?) -> void
180
135
  def initialize(name:, desc:, required:, multi:, default: nil, skip: nil)
181
136
  if multi && (default || required)
182
137
  raise(ArgumentError, 'multi-valued positions cannot have a default or required value')
@@ -190,34 +145,24 @@ module CLI
190
145
  @skip = skip
191
146
  end
192
147
 
193
- sig { params(arg: String).returns(T::Boolean) }
148
+ #: (String arg) -> bool
194
149
  def skip?(arg)
195
150
  if @skip.nil?
196
151
  false
197
- elsif T.must(@skip).arity == 0
198
- T.cast(@skip, T.proc.returns(T::Boolean)).call
152
+ elsif @skip.arity == 0
153
+ prc = @skip #: as ^() -> bool
154
+ prc.call
199
155
  else
200
- T.cast(@skip, T.proc.params(arg0: String).returns(T::Boolean)).call(arg)
156
+ prc = @skip #: as ^(String) -> bool
157
+ prc.call(arg)
201
158
  end
202
159
  end
203
160
  end
204
161
 
205
162
  class Option < Flag
206
- extend T::Sig
207
163
  include OptValue
208
164
 
209
- sig do
210
- params(
211
- name: Symbol, short: T.nilable(String), long: T.nilable(String),
212
- desc: T.nilable(String),
213
- default: T.any(
214
- NilClass,
215
- String, T.proc.returns(String),
216
- T::Array[String], T.proc.returns(T::Array[String])
217
- ),
218
- required: T::Boolean, multi: T::Boolean
219
- ).void
220
- end
165
+ #: (name: Symbol, ?short: String?, ?long: String?, ?desc: String?, ?default: (String | ^-> String | Array[String] | ^-> Array[String])?, ?required: bool, ?multi: bool) -> void
221
166
  def initialize(name:, short: nil, long: nil, desc: nil, default: nil, required: false, multi: false)
222
167
  if multi && required
223
168
  raise(ArgumentError, 'multi-valued options cannot have a required value')
@@ -230,7 +175,7 @@ module CLI
230
175
  end
231
176
  end
232
177
 
233
- sig { params(name: Symbol).returns(T.nilable(Flag)) }
178
+ #: (Symbol name) -> Flag?
234
179
  def lookup_flag(name)
235
180
  flagopt = @by_name[name]
236
181
  if flagopt.class == Flag
@@ -238,7 +183,7 @@ module CLI
238
183
  end
239
184
  end
240
185
 
241
- sig { params(name: Symbol).returns(T.nilable(Option)) }
186
+ #: (Symbol name) -> Option?
242
187
  def lookup_option(name)
243
188
  flagopt = @by_name[name]
244
189
  if flagopt.class == Option
@@ -246,21 +191,21 @@ module CLI
246
191
  end
247
192
  end
248
193
 
249
- sig { params(name: String).returns(T.any(Flag, Option, NilClass)) }
194
+ #: (String name) -> (Flag | Option)?
250
195
  def lookup_short(name)
251
196
  raise(InvalidLookup, "invalid '-' prefix") if name.start_with?('-')
252
197
 
253
198
  @by_short[name]
254
199
  end
255
200
 
256
- sig { params(name: String).returns(T.any(Flag, Option, NilClass)) }
201
+ #: (String name) -> (Flag | Option)?
257
202
  def lookup_long(name)
258
203
  raise(InvalidLookup, "invalid '-' prefix") if name.start_with?('-')
259
204
 
260
205
  @by_long[name]
261
206
  end
262
207
 
263
- sig { params(name: Symbol).returns(T.nilable(Position)) }
208
+ #: (Symbol name) -> Position?
264
209
  def lookup_position(name)
265
210
  position = @by_name[name]
266
211
  if position.class == Position
@@ -270,12 +215,12 @@ module CLI
270
215
 
271
216
  private
272
217
 
273
- sig { params(position: Position).void }
218
+ #: (Position position) -> void
274
219
  def validate_order(position)
275
220
  raise(InvalidPosition, 'Cannot have any more positional arguments after multi') if @positions.last&.multi?
276
221
  end
277
222
 
278
- sig { params(short: String).returns(String) }
223
+ #: (String short) -> String
279
224
  def strip_short_prefix(short)
280
225
  unless short.match?(/^-[^-]/)
281
226
  raise(InvalidFlag, "Short flag '#{short}' does not start with '-'")
@@ -287,7 +232,7 @@ module CLI
287
232
  short.sub(/^-/, '')
288
233
  end
289
234
 
290
- sig { params(long: String).returns(String) }
235
+ #: (String long) -> String
291
236
  def strip_long_prefix(long)
292
237
  unless long.match?(/^--[^-]/)
293
238
  raise(InvalidFlag, "Long flag '#{long}' does not start with '--'")
@@ -296,10 +241,7 @@ module CLI
296
241
  long.sub(/^--/, '')
297
242
  end
298
243
 
299
- sig do
300
- params(short: T.nilable(String), long: T.nilable(String))
301
- .returns([T.nilable(String), T.nilable(String)])
302
- end
244
+ #: (String? short, String? long) -> [String?, String?]
303
245
  def strip_prefixes_and_validate(short, long)
304
246
  if short.nil? && long.nil?
305
247
  raise(Error, 'One or more of short and long must be specified')
@@ -311,7 +253,7 @@ module CLI
311
253
  [short, long]
312
254
  end
313
255
 
314
- sig { params(flagopt: Flag).void }
256
+ #: (Flag flagopt) -> void
315
257
  def add_resolution(flagopt)
316
258
  if flagopt.short
317
259
  if (existing = @by_short[flagopt.short])
@@ -330,7 +272,7 @@ module CLI
330
272
  add_name_resolution(flagopt)
331
273
  end
332
274
 
333
- sig { params(arg: T.any(Flag, Position)).void }
275
+ #: ((Flag | Position) arg) -> void
334
276
  def add_name_resolution(arg)
335
277
  if (existing = @by_name[arg.name])
336
278
  raise(ConflictingFlag, "Flag '#{arg.name}' already defined by #{existing.name}")
@@ -6,38 +6,31 @@ module CLI
6
6
  module Kit
7
7
  module Args
8
8
  class Evaluation
9
- extend T::Sig
10
-
11
9
  Error = Class.new(Args::Error)
12
10
 
13
11
  class MissingRequiredOption < Error
14
- extend T::Sig
15
- sig { params(name: String).void }
12
+ #: (String name) -> void
16
13
  def initialize(name)
17
14
  super("missing required option `#{name}'")
18
15
  end
19
16
  end
20
17
 
21
18
  class MissingRequiredPosition < Error
22
- extend T::Sig
23
- sig { void }
19
+ #: -> void
24
20
  def initialize
25
21
  super('more arguments required')
26
22
  end
27
23
  end
28
24
 
29
25
  class TooManyPositions < Error
30
- extend T::Sig
31
- sig { void }
26
+ #: -> void
32
27
  def initialize
33
28
  super('too many arguments')
34
29
  end
35
30
  end
36
31
 
37
32
  class FlagProxy
38
- extend T::Sig
39
-
40
- sig { params(sym: Symbol).returns(T::Boolean) }
33
+ #: (Symbol sym) -> bool
41
34
  def method_missing(sym)
42
35
  flag = @evaluation.defn.lookup_flag(sym)
43
36
  unless flag
@@ -47,21 +40,19 @@ module CLI
47
40
  @evaluation.send(:lookup_flag, flag)
48
41
  end
49
42
 
50
- sig { params(sym: Symbol, include_private: T::Boolean).returns(T::Boolean) }
43
+ #: (Symbol sym, ?bool include_private) -> bool
51
44
  def respond_to_missing?(sym, include_private = false)
52
45
  !!@evaluation.defn.lookup_flag(sym)
53
46
  end
54
47
 
55
- sig { params(evaluation: Evaluation).void }
48
+ #: (Evaluation evaluation) -> void
56
49
  def initialize(evaluation)
57
50
  @evaluation = evaluation
58
51
  end
59
52
  end
60
53
 
61
54
  class OptionProxy
62
- extend T::Sig
63
-
64
- sig { params(sym: Symbol).returns(T.any(NilClass, String, T::Array[String])) }
55
+ #: (Symbol sym) -> (String | Array[String])?
65
56
  def method_missing(sym)
66
57
  opt = @evaluation.defn.lookup_option(sym)
67
58
  unless opt
@@ -71,21 +62,19 @@ module CLI
71
62
  @evaluation.send(:lookup_option, opt)
72
63
  end
73
64
 
74
- sig { params(sym: Symbol, include_private: T::Boolean).returns(T::Boolean) }
65
+ #: (Symbol sym, ?bool include_private) -> bool
75
66
  def respond_to_missing?(sym, include_private = false)
76
67
  !!@evaluation.defn.lookup_option(sym)
77
68
  end
78
69
 
79
- sig { params(evaluation: Evaluation).void }
70
+ #: (Evaluation evaluation) -> void
80
71
  def initialize(evaluation)
81
72
  @evaluation = evaluation
82
73
  end
83
74
  end
84
75
 
85
76
  class PositionProxy
86
- extend T::Sig
87
-
88
- sig { params(sym: Symbol).returns(T.any(NilClass, String, T::Array[String])) }
77
+ #: (Symbol sym) -> (String | Array[String])?
89
78
  def method_missing(sym)
90
79
  position = @evaluation.defn.lookup_position(sym)
91
80
  unless position
@@ -95,57 +84,54 @@ module CLI
95
84
  @evaluation.send(:lookup_position, position)
96
85
  end
97
86
 
98
- sig { params(sym: Symbol, include_private: T::Boolean).returns(T::Boolean) }
87
+ #: (Symbol sym, ?bool include_private) -> bool
99
88
  def respond_to_missing?(sym, include_private = false)
100
89
  !!@evaluation.defn.lookup_position(sym)
101
90
  end
102
91
 
103
- sig { params(evaluation: Evaluation).void }
92
+ #: (Evaluation evaluation) -> void
104
93
  def initialize(evaluation)
105
94
  @evaluation = evaluation
106
95
  end
107
96
  end
108
97
 
109
- sig { returns(FlagProxy) }
98
+ #: -> FlagProxy
110
99
  def flag
111
100
  @flag_proxy ||= FlagProxy.new(self)
112
101
  end
113
102
 
114
- sig { returns(OptionProxy) }
103
+ #: -> OptionProxy
115
104
  def opt
116
105
  @option_proxy ||= OptionProxy.new(self)
117
106
  end
118
107
 
119
- sig { returns(PositionProxy) }
108
+ #: -> PositionProxy
120
109
  def position
121
110
  @position_proxy ||= PositionProxy.new(self)
122
111
  end
123
112
 
124
- sig { returns(Definition) }
113
+ #: Definition
125
114
  attr_reader :defn
126
115
 
127
- sig { returns(T::Array[Parser::Node]) }
116
+ #: Array[Parser::Node]
128
117
  attr_reader :parse
129
118
 
130
- sig { returns(T::Array[String]) }
119
+ #: -> Array[String]
131
120
  def unparsed
132
121
  @unparsed ||= begin
133
- nodes = T.cast(
134
- parse.select { |node| node.is_a?(Parser::Node::Unparsed) },
135
- T::Array[Parser::Node::Unparsed],
136
- )
122
+ nodes = parse.select { |node| node.is_a?(Parser::Node::Unparsed) } #: as Array[Parser::Node::Unparsed]
137
123
  nodes.flat_map(&:value)
138
124
  end
139
125
  end
140
126
 
141
- sig { params(defn: Definition, parse: T::Array[Parser::Node]).void }
127
+ #: (Definition defn, Array[Parser::Node] parse) -> void
142
128
  def initialize(defn, parse)
143
129
  @defn = defn
144
130
  @parse = parse
145
131
  check_required_options!
146
132
  end
147
133
 
148
- sig { void }
134
+ #: -> void
149
135
  def check_required_options!
150
136
  @defn.options.each do |opt|
151
137
  next unless opt.required?
@@ -153,56 +139,54 @@ module CLI
153
139
  node = @parse.detect do |node|
154
140
  node.is_a?(Parser::Node::Option) && node.name.to_sym == opt.name
155
141
  end
156
- if !node || T.cast(node, Parser::Node::Option).value.nil?
142
+ unless node
143
+ raise(MissingRequiredOption, opt.as_written_by_user)
144
+ end
145
+
146
+ node = node #: as Parser::Node::Option
147
+ if node.value.nil?
157
148
  raise(MissingRequiredOption, opt.as_written_by_user)
158
149
  end
159
150
  end
160
151
  end
161
152
 
162
- sig { void }
153
+ #: -> void
163
154
  def resolve_positions!
164
155
  args_i = 0
165
156
  @position_values = Hash.new
166
157
  @defn.positions.each do |position|
167
158
  raise(MissingRequiredPosition) if position.required? && args_i >= args.size
168
- next if args_i >= args.size || position.skip?(T.must(args[args_i]))
159
+ next if args_i >= args.size || position.skip?(
160
+ args[args_i], #: as !nil
161
+ )
169
162
 
170
163
  if position.multi?
171
164
  @position_values[position.name] = args[args_i..]
172
165
  args_i = args.size
173
166
  else
174
- @position_values[position.name] = T.must(args[args_i])
167
+ @position_values[position.name] = args[args_i] #: as !nil
175
168
  args_i += 1
176
169
  end
177
170
  end
178
171
  raise(TooManyPositions) if args_i < args.size
179
172
  end
180
173
 
181
- sig { params(flag: Definition::Flag).returns(T::Boolean) }
174
+ #: (Definition::Flag flag) -> bool
182
175
  def lookup_flag(flag)
183
176
  if flag.short
184
- flags = T.cast(
185
- parse.select { |node| node.is_a?(Parser::Node::ShortFlag) },
186
- T::Array[Parser::Node::ShortFlag],
187
- )
177
+ flags = parse.select { |node| node.is_a?(Parser::Node::ShortFlag) } #: as Array[Parser::Node::ShortFlag]
188
178
  return true if flags.any? { |node| node.value == flag.short }
189
179
  end
190
180
  if flag.long
191
- flags = T.cast(
192
- parse.select { |node| node.is_a?(Parser::Node::LongFlag) },
193
- T::Array[Parser::Node::LongFlag],
194
- )
181
+ flags = parse.select { |node| node.is_a?(Parser::Node::LongFlag) } #: as Array[Parser::Node::LongFlag]
195
182
  return true if flags.any? { |node| node.value == flag.long }
196
183
  end
197
184
  false
198
185
  end
199
186
 
200
- sig { params(opt: Definition::Option).returns(T.any(NilClass, String, T::Array[String])) }
187
+ #: (Definition::Option opt) -> (String | Array[String])?
201
188
  def lookup_option(opt)
202
- opts = T.cast(
203
- parse.select { |node| node.is_a?(Parser::Node::ShortOption) || node.is_a?(Parser::Node::LongOption) },
204
- T::Array[T.any(Parser::Node::ShortOption, Parser::Node::LongOption)],
205
- )
189
+ opts = parse.select { |node| node.is_a?(Parser::Node::ShortOption) || node.is_a?(Parser::Node::LongOption) } #: as Array[Parser::Node::ShortOption | Parser::Node::LongOption]
206
190
  matches = opts.select { |node| (opt.short && node.name == opt.short) || (opt.long && node.name == opt.long) }
207
191
  if (last = matches.last)
208
192
  return (opt.multi? ? matches.map(&:value) : last.value)
@@ -211,20 +195,17 @@ module CLI
211
195
  opt.default
212
196
  end
213
197
 
214
- sig { params(position: Definition::Position).returns(T.any(NilClass, String, T::Array[String])) }
198
+ #: (Definition::Position position) -> (String | Array[String])?
215
199
  def lookup_position(position)
216
200
  @position_values.fetch(position.name) { position.multi? ? [] : position.default }
217
201
  end
218
202
 
219
203
  private
220
204
 
221
- sig { returns(T::Array[String]) }
205
+ #: -> Array[String]
222
206
  def args
223
207
  @args ||= begin
224
- nodes = T.cast(
225
- parse.select { |node| node.is_a?(Parser::Node::Argument) },
226
- T::Array[Parser::Node::Argument],
227
- )
208
+ nodes = parse.select { |node| node.is_a?(Parser::Node::Argument) } #: as Array[Parser::Node::Argument]
228
209
  nodes.map(&:value)
229
210
  end
230
211
  end