gorails 0.1.2 → 0.1.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.
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