gorails 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -1
  3. data/Gemfile.lock +1 -1
  4. data/bin/update-deps +95 -0
  5. data/exe/gorails +3 -2
  6. data/lib/gorails/commands/railsbytes.rb +10 -10
  7. data/lib/gorails/commands.rb +1 -4
  8. data/lib/gorails/version.rb +1 -1
  9. data/lib/gorails.rb +11 -20
  10. data/vendor/deps/cli-kit/REVISION +1 -0
  11. data/vendor/deps/cli-kit/lib/cli/kit/args/definition.rb +301 -0
  12. data/vendor/deps/cli-kit/lib/cli/kit/args/evaluation.rb +237 -0
  13. data/vendor/deps/cli-kit/lib/cli/kit/args/parser/node.rb +131 -0
  14. data/vendor/deps/cli-kit/lib/cli/kit/args/parser.rb +128 -0
  15. data/vendor/deps/cli-kit/lib/cli/kit/args/tokenizer.rb +132 -0
  16. data/vendor/deps/cli-kit/lib/cli/kit/args.rb +15 -0
  17. data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +29 -0
  18. data/vendor/deps/cli-kit/lib/cli/kit/command_help.rb +256 -0
  19. data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +141 -0
  20. data/vendor/deps/cli-kit/lib/cli/kit/config.rb +137 -0
  21. data/vendor/deps/cli-kit/lib/cli/kit/core_ext.rb +30 -0
  22. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +165 -0
  23. data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +99 -0
  24. data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +94 -0
  25. data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +89 -0
  26. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +95 -0
  27. data/vendor/deps/cli-kit/lib/cli/kit/opts.rb +284 -0
  28. data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +67 -0
  29. data/vendor/deps/cli-kit/lib/cli/kit/sorbet_runtime_stub.rb +142 -0
  30. data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +253 -0
  31. data/vendor/deps/cli-kit/lib/cli/kit/support.rb +10 -0
  32. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +350 -0
  33. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +133 -0
  34. data/vendor/deps/cli-kit/lib/cli/kit/version.rb +7 -0
  35. data/vendor/deps/cli-kit/lib/cli/kit.rb +151 -0
  36. data/vendor/deps/cli-ui/REVISION +1 -0
  37. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +180 -0
  38. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +98 -0
  39. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +216 -0
  40. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +116 -0
  41. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +176 -0
  42. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +149 -0
  43. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +112 -0
  44. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +300 -0
  45. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +92 -0
  46. data/vendor/deps/cli-ui/lib/cli/ui/os.rb +58 -0
  47. data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +72 -0
  48. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +102 -0
  49. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +534 -0
  50. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +36 -0
  51. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +354 -0
  52. data/vendor/deps/cli-ui/lib/cli/ui/sorbet_runtime_stub.rb +143 -0
  53. data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +46 -0
  54. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +292 -0
  55. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +82 -0
  56. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +264 -0
  57. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +53 -0
  58. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +107 -0
  59. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +6 -0
  60. data/vendor/deps/cli-ui/lib/cli/ui/widgets/base.rb +37 -0
  61. data/vendor/deps/cli-ui/lib/cli/ui/widgets/status.rb +75 -0
  62. data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +91 -0
  63. data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +63 -0
  64. data/vendor/deps/cli-ui/lib/cli/ui.rb +356 -0
  65. metadata +57 -1
@@ -0,0 +1,237 @@
1
+ # typed: true
2
+ require 'cli/kit'
3
+
4
+ module CLI
5
+ module Kit
6
+ module Args
7
+ class Evaluation
8
+ extend T::Sig
9
+
10
+ Error = Class.new(Args::Error)
11
+
12
+ class MissingRequiredOption < Error
13
+ extend T::Sig
14
+ sig { params(name: String).void }
15
+ def initialize(name)
16
+ super("missing required option `#{name}'")
17
+ end
18
+ end
19
+
20
+ class MissingRequiredPosition < Error
21
+ extend T::Sig
22
+ sig { void }
23
+ def initialize
24
+ super('more arguments required')
25
+ end
26
+ end
27
+
28
+ class TooManyPositions < Error
29
+ extend T::Sig
30
+ sig { void }
31
+ def initialize
32
+ super('too many arguments')
33
+ end
34
+ end
35
+
36
+ class FlagProxy
37
+ extend T::Sig
38
+
39
+ sig { params(sym: Symbol).returns(T::Boolean) }
40
+ def method_missing(sym)
41
+ flag = @evaluation.defn.lookup_flag(sym)
42
+ unless flag
43
+ raise NoMethodError, "undefined flag `#{sym}' for #{self}"
44
+ end
45
+
46
+ @evaluation.send(:lookup_flag, flag)
47
+ end
48
+
49
+ sig { params(sym: Symbol, include_private: T::Boolean).returns(T::Boolean) }
50
+ def respond_to_missing?(sym, include_private = false)
51
+ !!@evaluation.defn.lookup_flag(sym)
52
+ end
53
+
54
+ sig { params(evaluation: Evaluation).void }
55
+ def initialize(evaluation)
56
+ @evaluation = evaluation
57
+ end
58
+ end
59
+
60
+ class OptionProxy
61
+ extend T::Sig
62
+
63
+ sig { params(sym: Symbol).returns(T.any(NilClass, String, T::Array[String])) }
64
+ def method_missing(sym)
65
+ opt = @evaluation.defn.lookup_option(sym)
66
+ unless opt
67
+ raise NoMethodError, "undefined option `#{sym}' for #{self}"
68
+ end
69
+
70
+ @evaluation.send(:lookup_option, opt)
71
+ end
72
+
73
+ sig { params(sym: Symbol, include_private: T::Boolean).returns(T::Boolean) }
74
+ def respond_to_missing?(sym, include_private = false)
75
+ !!@evaluation.defn.lookup_option(sym)
76
+ end
77
+
78
+ sig { params(evaluation: Evaluation).void }
79
+ def initialize(evaluation)
80
+ @evaluation = evaluation
81
+ end
82
+ end
83
+
84
+ class PositionProxy
85
+ extend T::Sig
86
+
87
+ sig { params(sym: Symbol).returns(T.any(NilClass, String, T::Array[String])) }
88
+ def method_missing(sym)
89
+ position = @evaluation.defn.lookup_position(sym)
90
+ unless position
91
+ raise NoMethodError, "undefined position `#{sym}' for #{self}"
92
+ end
93
+
94
+ @evaluation.send(:lookup_position, position)
95
+ end
96
+
97
+ sig { params(sym: Symbol, include_private: T::Boolean).returns(T::Boolean) }
98
+ def respond_to_missing?(sym, include_private = false)
99
+ !!@evaluation.defn.lookup_position(sym)
100
+ end
101
+
102
+ sig { params(evaluation: Evaluation).void }
103
+ def initialize(evaluation)
104
+ @evaluation = evaluation
105
+ end
106
+ end
107
+
108
+ sig { returns(FlagProxy) }
109
+ def flag
110
+ @flag_proxy ||= FlagProxy.new(self)
111
+ end
112
+
113
+ sig { returns(OptionProxy) }
114
+ def opt
115
+ @option_proxy ||= OptionProxy.new(self)
116
+ end
117
+
118
+ sig { returns(PositionProxy) }
119
+ def position
120
+ @position_proxy ||= PositionProxy.new(self)
121
+ end
122
+
123
+ sig { returns(Definition) }
124
+ attr_reader :defn
125
+
126
+ sig { returns(T::Array[Parser::Node]) }
127
+ attr_reader :parse
128
+
129
+ sig { returns(T::Array[String]) }
130
+ def unparsed
131
+ @unparsed ||= begin
132
+ nodes = T.cast(
133
+ parse.select { |node| node.is_a?(Parser::Node::Unparsed) },
134
+ T::Array[Parser::Node::Unparsed],
135
+ )
136
+ nodes.flat_map(&:value)
137
+ end
138
+ end
139
+
140
+ sig { params(defn: Definition, parse: T::Array[Parser::Node]).void }
141
+ def initialize(defn, parse)
142
+ @defn = defn
143
+ @parse = parse
144
+ check_required!
145
+ end
146
+
147
+ sig { void }
148
+ def check_required!
149
+ @defn.options.each do |opt|
150
+ next unless opt.required
151
+
152
+ node = @parse.detect do |node|
153
+ node.is_a?(Parser::Node::Option) && node.name == opt.name
154
+ end
155
+ if !node || T.cast(node, Parser::Node::Option).value.nil?
156
+ raise(MissingRequiredOption, opt.as_written_by_user)
157
+ end
158
+ end
159
+ min_positions = @defn.positions.count(&:required?)
160
+ max_positions = if @defn.positions.last&.multiple?
161
+ Float::INFINITY
162
+ else
163
+ min_positions + @defn.positions.count(&:optional?)
164
+ end
165
+ raise(MissingRequiredPosition) if args.size < min_positions
166
+ raise(TooManyPositions) if args.size > max_positions
167
+ end
168
+
169
+ sig { params(flag: Definition::Flag).returns(T::Boolean) }
170
+ def lookup_flag(flag)
171
+ if flag.short
172
+ flags = T.cast(
173
+ parse.select { |node| node.is_a?(Parser::Node::ShortFlag) },
174
+ T::Array[Parser::Node::ShortFlag],
175
+ )
176
+ return true if flags.any? { |node| node.value == flag.short }
177
+ end
178
+ if flag.long
179
+ flags = T.cast(
180
+ parse.select { |node| node.is_a?(Parser::Node::LongFlag) },
181
+ T::Array[Parser::Node::LongFlag],
182
+ )
183
+ return true if flags.any? { |node| node.value == flag.long }
184
+ end
185
+ false
186
+ end
187
+
188
+ sig { params(opt: Definition::Option).returns(T.any(NilClass, String, T::Array[String])) }
189
+ def lookup_option(opt)
190
+ if opt.short
191
+ opts = T.cast(
192
+ parse.select { |node| node.is_a?(Parser::Node::ShortOption) },
193
+ T::Array[Parser::Node::ShortOption],
194
+ )
195
+ matches = opts.reverse.select { |node| node.name == opt.short }
196
+ if (first = matches.first)
197
+ return(opt.multi ? matches.map(&:value) : first.value)
198
+ end
199
+ end
200
+ if opt.long
201
+ opts = T.cast(
202
+ parse.select { |node| node.is_a?(Parser::Node::LongOption) },
203
+ T::Array[Parser::Node::LongOption],
204
+ )
205
+ matches = opts.reverse.select { |node| node.name == opt.long }
206
+ if (first = matches.first)
207
+ return(opt.multi ? matches.map(&:value) : first.value)
208
+ end
209
+ end
210
+ opt.multi ? [] : opt.default
211
+ end
212
+
213
+ sig { params(position: Definition::Position).returns(T.any(NilClass, String, T::Array[String])) }
214
+ def lookup_position(position)
215
+ if position.multiple?
216
+ args[position.index..]
217
+ else
218
+ args[position.index]
219
+ end
220
+ end
221
+
222
+ private
223
+
224
+ sig { returns(T::Array[String]) }
225
+ def args
226
+ @args ||= begin
227
+ nodes = T.cast(
228
+ parse.select { |node| node.is_a?(Parser::Node::Argument) },
229
+ T::Array[Parser::Node::Argument],
230
+ )
231
+ nodes.map(&:value)
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,131 @@
1
+ # typed: true
2
+ require 'cli/kit'
3
+
4
+ module CLI
5
+ module Kit
6
+ module Args
7
+ class Parser
8
+ class Node
9
+ extend T::Sig
10
+
11
+ sig { void }
12
+ def initialize
13
+ end
14
+
15
+ sig { params(other: T.untyped).returns(T::Boolean) }
16
+ def ==(other)
17
+ self.class == other.class
18
+ end
19
+
20
+ class Option < Node
21
+ extend T::Sig
22
+
23
+ sig { returns(String) }
24
+ attr_reader :name
25
+
26
+ sig { returns(String) }
27
+ attr_reader :value
28
+
29
+ sig { params(name: String, value: String).void }
30
+ def initialize(name, value)
31
+ @name = name
32
+ @value = value
33
+ super()
34
+ end
35
+ private_class_method(:new) # don't instantiate this class directly
36
+
37
+ sig { returns(String) }
38
+ def inspect
39
+ "#<#{self.class.name} #{@name}=#{@value}>"
40
+ end
41
+
42
+ sig { params(other: T.untyped).returns(T::Boolean) }
43
+ def ==(other)
44
+ !!(super(other) && @value == other.value && @name == other.name)
45
+ end
46
+ end
47
+
48
+ class LongOption < Option
49
+ public_class_method(:new)
50
+ end
51
+
52
+ class ShortOption < Option
53
+ public_class_method(:new)
54
+ end
55
+
56
+ class Flag < Node
57
+ sig { returns(String) }
58
+ attr_reader :value
59
+
60
+ sig { params(value: String).void }
61
+ def initialize(value)
62
+ @value = value
63
+ super()
64
+ end
65
+ private_class_method(:new) # don't instantiate this class directly
66
+
67
+ sig { returns(String) }
68
+ def inspect
69
+ "#<#{self.class.name} #{@value}>"
70
+ end
71
+
72
+ sig { params(other: T.untyped).returns(T::Boolean) }
73
+ def ==(other)
74
+ !!(super(other) && @value == other.value)
75
+ end
76
+ end
77
+
78
+ class LongFlag < Flag
79
+ public_class_method(:new)
80
+ end
81
+
82
+ class ShortFlag < Flag
83
+ public_class_method(:new)
84
+ end
85
+
86
+ class Argument < Node
87
+ sig { returns(String) }
88
+ attr_reader :value
89
+
90
+ sig { params(value: String).void }
91
+ def initialize(value)
92
+ @value = value
93
+ super()
94
+ end
95
+
96
+ sig { returns(String) }
97
+ def inspect
98
+ "#<#{self.class.name} #{@value}>"
99
+ end
100
+
101
+ sig { params(other: T.untyped).returns(T::Boolean) }
102
+ def ==(other)
103
+ !!(super(other) && @value == other.value)
104
+ end
105
+ end
106
+
107
+ class Unparsed < Node
108
+ sig { returns(T::Array[String]) }
109
+ attr_reader :value
110
+
111
+ sig { params(value: T::Array[String]).void }
112
+ def initialize(value)
113
+ @value = value
114
+ super()
115
+ end
116
+
117
+ sig { returns(String) }
118
+ def inspect
119
+ "#<#{self.class.name} #{@value.join(" ")}>"
120
+ end
121
+
122
+ sig { params(other: T.untyped).returns(T::Boolean) }
123
+ def ==(other)
124
+ !!(super(other) && @value == other.value)
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,128 @@
1
+ # typed: true
2
+ require 'cli/kit'
3
+
4
+ module CLI
5
+ module Kit
6
+ module Args
7
+ class Parser
8
+ extend T::Sig
9
+
10
+ autoload :Node, 'cli/kit/args/parser/node'
11
+
12
+ Error = Class.new(Args::Error)
13
+
14
+ class InvalidOptionError < Error
15
+ extend T::Sig
16
+ sig { params(option: String).void }
17
+ def initialize(option)
18
+ super("invalid option -- '#{option}'")
19
+ end
20
+ end
21
+
22
+ class OptionRequiresAnArgumentError < Error
23
+ extend T::Sig
24
+ sig { params(option: String).void }
25
+ def initialize(option)
26
+ super("option requires an argument -- '#{option}'")
27
+ end
28
+ end
29
+
30
+ sig { params(tokens: T::Array[Tokenizer::Token]).returns(T::Array[Node]) }
31
+ def parse(tokens)
32
+ nodes = T.let([], T::Array[Node])
33
+ args = T.let(tokens, T::Array[T.nilable(Tokenizer::Token)])
34
+ args << nil # to make each_cons pass (args.last, nil) on the final round.
35
+ state = :init
36
+ # TODO: test that "--height -- 3" is parsed correctly.
37
+ args.each_cons(2) do |(arg, next_arg)|
38
+ case state
39
+ when :skip
40
+ state = :init
41
+ when :init
42
+ state, val = parse_token(T.must(arg), next_arg)
43
+ nodes << val
44
+ when :unparsed
45
+ unless arg.is_a?(Tokenizer::Token::UnparsedArgument)
46
+ raise(Error, 'bug: non-unparsed argument after unparsed argument')
47
+ end
48
+
49
+ unparsed = nodes.last
50
+ unless unparsed.is_a?(Node::Unparsed)
51
+ # :nocov: not actually possible, in theory
52
+ raise(Error, 'bug: parser failed to recognize first unparsed argument')
53
+ # :nocov:
54
+ end
55
+
56
+ unparsed.value << arg.value
57
+ end
58
+ end
59
+ nodes
60
+ end
61
+
62
+ sig { params(definition: Definition).void }
63
+ def initialize(definition)
64
+ @defn = definition
65
+ end
66
+
67
+ private
68
+
69
+ sig do
70
+ params(token: Tokenizer::Token, next_token: T.nilable(Tokenizer::Token))
71
+ .returns([Symbol, Parser::Node])
72
+ end
73
+ def parse_token(token, next_token)
74
+ case token
75
+ when Tokenizer::Token::LongOptionName
76
+ case @defn.lookup_long(token.value)
77
+ when Definition::Option
78
+ [:skip, parse_option(token, next_token)]
79
+ when Definition::Flag
80
+ [:init, Node::LongFlag.new(token.value)]
81
+ else
82
+ raise(InvalidOptionError, token.value)
83
+ end
84
+ when Tokenizer::Token::ShortOptionName
85
+ case @defn.lookup_short(token.value)
86
+ when Definition::Option
87
+ [:skip, parse_option(token, next_token)]
88
+ when Definition::Flag
89
+ [:init, Node::ShortFlag.new(token.value)]
90
+ else
91
+ raise(InvalidOptionError, token.value)
92
+ end
93
+ when Tokenizer::Token::OptionValue
94
+ raise(Error, "bug: unexpected option value in argument parse sequence: #{token.value}")
95
+ when Tokenizer::Token::PositionalArgument
96
+ [:init, Node::Argument.new(token.value)]
97
+ when Tokenizer::Token::OptionValueOrPositionalArgument
98
+ [:init, Node::Argument.new(token.value)]
99
+ when Tokenizer::Token::UnparsedArgument
100
+ [:unparsed, Node::Unparsed.new([token.value])]
101
+ else
102
+ raise(Error, "bug: unexpected token type: #{token.class}")
103
+ end
104
+ end
105
+
106
+ sig { params(arg: Tokenizer::Token::OptionName, next_arg: T.nilable(Tokenizer::Token)).returns(Node) }
107
+ def parse_option(arg, next_arg)
108
+ case next_arg
109
+ when nil, Tokenizer::Token::LongOptionName,
110
+ Tokenizer::Token::ShortOptionName, Tokenizer::Token::PositionalArgument
111
+ raise(OptionRequiresAnArgumentError, arg.value)
112
+ when Tokenizer::Token::OptionValue, Tokenizer::Token::OptionValueOrPositionalArgument
113
+ case arg
114
+ when Tokenizer::Token::LongOptionName
115
+ Node::LongOption.new(arg.value, next_arg.value)
116
+ when Tokenizer::Token::ShortOptionName
117
+ Node::ShortOption.new(arg.value, next_arg.value)
118
+ else
119
+ raise(Error, "bug: unexpected token type: #{arg.class}")
120
+ end
121
+ else
122
+ raise(Error, "bug: unexpected argument type: #{next_arg.class}")
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,132 @@
1
+ # typed: true
2
+ require 'cli/kit'
3
+
4
+ module CLI
5
+ module Kit
6
+ module Args
7
+ module Tokenizer
8
+ extend T::Sig
9
+
10
+ Error = Class.new(Args::Error)
11
+
12
+ class InvalidShortOption < Error
13
+ extend T::Sig
14
+ sig { params(short_option: String).void }
15
+ def initialize(short_option)
16
+ super("invalid short option: '-#{short_option}'")
17
+ end
18
+ end
19
+
20
+ class InvalidCharInShortOption < Error
21
+ extend T::Sig
22
+ sig { params(short_option: String, char: String).void }
23
+ def initialize(short_option, char)
24
+ super("invalid character '#{char}' in short option: '-#{short_option}'")
25
+ end
26
+ end
27
+
28
+ class Token
29
+ extend T::Sig
30
+
31
+ sig { returns(String) }
32
+ attr_reader :value
33
+
34
+ sig { params(value: String).void }
35
+ def initialize(value)
36
+ @value = value
37
+ end
38
+
39
+ sig { returns(String) }
40
+ def inspect
41
+ "#<#{self.class.name} #{@value}>"
42
+ end
43
+
44
+ sig { params(other: T.untyped).returns(T::Boolean) }
45
+ def ==(other)
46
+ self.class == other.class && @value == other.value
47
+ end
48
+
49
+ OptionName = Class.new(Token)
50
+ LongOptionName = Class.new(OptionName)
51
+ ShortOptionName = Class.new(OptionName)
52
+
53
+ OptionValue = Class.new(Token)
54
+ PositionalArgument = Class.new(Token)
55
+ OptionValueOrPositionalArgument = Class.new(Token)
56
+ UnparsedArgument = Class.new(Token)
57
+ end
58
+
59
+ class << self
60
+ extend T::Sig
61
+
62
+ sig { params(raw_args: T::Array[String]).returns(T::Array[Token]) }
63
+ def tokenize(raw_args)
64
+ args = []
65
+
66
+ mode = :init
67
+
68
+ raw_args.each do |arg|
69
+ case mode
70
+ when :unparsed
71
+ args << Token::UnparsedArgument.new(arg)
72
+ when :init
73
+ case arg
74
+ when '--'
75
+ mode = :unparsed
76
+ when /\A--/
77
+ name, value = arg.split('=', 2)
78
+ args << Token::LongOptionName.new(T.must(T.must(name)[2..-1]))
79
+ if value
80
+ args << Token::OptionValue.new(value)
81
+ end
82
+ when /\A-/
83
+ args.concat(tokenize_short_option(T.must(arg[1..-1])))
84
+ else
85
+ args << if args.last.is_a?(Token::OptionName)
86
+ Token::OptionValueOrPositionalArgument.new(arg)
87
+ else
88
+ Token::PositionalArgument.new(arg)
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ args
95
+ end
96
+
97
+ sig { params(arg: String).returns(T::Array[Token]) }
98
+ def tokenize_short_option(arg)
99
+ args = []
100
+ mode = :init
101
+ number = +''
102
+ arg.each_char do |char|
103
+ case mode
104
+ when :numeric
105
+ case char
106
+ when /[0-9]/
107
+ number << char
108
+ else
109
+ raise(InvalidShortOption, arg)
110
+ end
111
+ when :init
112
+ case char
113
+ when /[a-zA-Z]/
114
+ args << Token::ShortOptionName.new(char)
115
+ when /[0-9]/
116
+ mode = :numeric
117
+ number << char
118
+ else
119
+ raise(InvalidCharInShortOption.new(arg, char))
120
+ end
121
+ end
122
+ end
123
+ if number != ''
124
+ args << Token::OptionValue.new(number)
125
+ end
126
+ args
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,15 @@
1
+ # typed: true
2
+ require 'cli/kit'
3
+
4
+ module CLI
5
+ module Kit
6
+ module Args
7
+ Error = Class.new(StandardError)
8
+
9
+ autoload :Definition, 'cli/kit/args/definition'
10
+ autoload :Parser, 'cli/kit/args/parser'
11
+ autoload :Evaluation, 'cli/kit/args/evaluation'
12
+ autoload :Tokenizer, 'cli/kit/args/tokenizer'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ # typed: true
2
+ require 'cli/kit'
3
+
4
+ module CLI
5
+ module Kit
6
+ class BaseCommand
7
+ extend T::Sig
8
+ extend T::Helpers
9
+ include CLI::Kit::CommandHelp
10
+ extend CLI::Kit::CommandHelp::ClassMethods
11
+ abstract!
12
+
13
+ sig { returns(T::Boolean) }
14
+ def self.defined?
15
+ true
16
+ end
17
+
18
+ sig { params(args: T::Array[String], command_name: String).void }
19
+ def self.call(args, command_name)
20
+ new.call(args, command_name)
21
+ end
22
+
23
+ sig { returns(T::Boolean) }
24
+ def has_subcommands?
25
+ false
26
+ end
27
+ end
28
+ end
29
+ end