cli-kit 5.1.0 → 5.3.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.
- checksums.yaml +4 -4
- data/.github/release.yml +20 -0
- data/.github/workflows/release.yml +52 -0
- data/.github/workflows/ruby.yml +1 -1
- data/.rubocop.sorbet.yml +1 -0
- data/.rubocop.yml +2 -2
- data/Gemfile +1 -1
- data/Gemfile.lock +23 -24
- data/Rakefile +0 -1
- data/bin/testunit +0 -1
- data/cli-kit.gemspec +2 -1
- data/examples/minimal/example.rb +1 -1
- data/examples/single-file/example.rb +4 -3
- data/gen/lib/gen/commands/help.rb +1 -3
- data/gen/lib/gen/commands/new.rb +2 -6
- data/gen/lib/gen/commands.rb +1 -7
- data/gen/lib/gen/entry_point.rb +1 -5
- data/gen/lib/gen/generator.rb +15 -19
- data/gen/lib/gen/help.rb +3 -7
- data/lib/cli/kit/args/definition.rb +37 -95
- data/lib/cli/kit/args/evaluation.rb +40 -59
- data/lib/cli/kit/args/parser/node.rb +19 -23
- data/lib/cli/kit/args/parser.rb +12 -16
- data/lib/cli/kit/args/tokenizer.rb +15 -18
- data/lib/cli/kit/base_command.rb +4 -8
- data/lib/cli/kit/command_help.rb +24 -27
- data/lib/cli/kit/command_registry.rb +40 -36
- data/lib/cli/kit/config.rb +210 -17
- data/lib/cli/kit/core_ext.rb +118 -8
- data/lib/cli/kit/error_handler.rb +49 -39
- data/lib/cli/kit/executor.rb +7 -16
- data/lib/cli/kit/ini.rb +8 -12
- data/lib/cli/kit/levenshtein.rb +7 -5
- data/lib/cli/kit/logger.rb +8 -10
- data/lib/cli/kit/opts.rb +26 -86
- data/lib/cli/kit/parse_args.rb +5 -10
- data/lib/cli/kit/resolver.rb +4 -6
- data/lib/cli/kit/support/test_helper.rb +10 -5
- data/lib/cli/kit/system.rb +25 -114
- data/lib/cli/kit/util.rb +15 -31
- data/lib/cli/kit/version.rb +1 -1
- data/lib/cli/kit.rb +19 -36
- metadata +18 -3
- data/lib/cli/kit/sorbet_runtime_stub.rb +0 -154
data/lib/cli/kit/ini.rb
CHANGED
|
@@ -17,14 +17,10 @@ module CLI
|
|
|
17
17
|
# See the ini_test.rb file for more examples
|
|
18
18
|
#
|
|
19
19
|
class Ini
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
sig { returns(T::Hash[String, T::Hash[String, String]]) }
|
|
20
|
+
#: Hash[String, Hash[String, String]]
|
|
23
21
|
attr_accessor :ini
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
params(path: T.nilable(String), config: T.nilable(String), default_section: String).void
|
|
27
|
-
end
|
|
23
|
+
#: (?String? path, ?config: String?, ?default_section: String) -> void
|
|
28
24
|
def initialize(path = nil, config: nil, default_section: '[global]')
|
|
29
25
|
@config = if path && File.exist?(path)
|
|
30
26
|
File.readlines(path)
|
|
@@ -35,7 +31,7 @@ module CLI
|
|
|
35
31
|
@current_key = default_section
|
|
36
32
|
end
|
|
37
33
|
|
|
38
|
-
|
|
34
|
+
#: -> Hash[String, Hash[String, String]]
|
|
39
35
|
def parse
|
|
40
36
|
return @ini if @config.nil?
|
|
41
37
|
|
|
@@ -53,19 +49,19 @@ module CLI
|
|
|
53
49
|
@ini
|
|
54
50
|
end
|
|
55
51
|
|
|
56
|
-
|
|
52
|
+
#: -> String
|
|
57
53
|
def git_format
|
|
58
54
|
to_ini(git_format: true)
|
|
59
55
|
end
|
|
60
56
|
|
|
61
|
-
|
|
57
|
+
#: -> String
|
|
62
58
|
def to_s
|
|
63
59
|
to_ini
|
|
64
60
|
end
|
|
65
61
|
|
|
66
62
|
private
|
|
67
63
|
|
|
68
|
-
|
|
64
|
+
#: (?git_format: bool) -> String
|
|
69
65
|
def to_ini(git_format: false)
|
|
70
66
|
optional_tab = git_format ? "\t" : ''
|
|
71
67
|
str = []
|
|
@@ -79,14 +75,14 @@ module CLI
|
|
|
79
75
|
str.join("\n")
|
|
80
76
|
end
|
|
81
77
|
|
|
82
|
-
|
|
78
|
+
#: (String key, String val) -> void
|
|
83
79
|
def set_val(key, val)
|
|
84
80
|
current_key = @current_key
|
|
85
81
|
@ini[current_key] ||= {}
|
|
86
82
|
@ini[current_key][key] = val
|
|
87
83
|
end
|
|
88
84
|
|
|
89
|
-
|
|
85
|
+
#: (String k) -> bool
|
|
90
86
|
def section_designator?(k)
|
|
91
87
|
k.start_with?('[') && k.end_with?(']')
|
|
92
88
|
end
|
data/lib/cli/kit/levenshtein.rb
CHANGED
|
@@ -28,13 +28,13 @@ require 'cli/kit'
|
|
|
28
28
|
module CLI
|
|
29
29
|
module Kit
|
|
30
30
|
module Levenshtein
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
|
|
33
33
|
# This code is based directly on the Text gem implementation
|
|
34
34
|
# Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
|
|
35
35
|
#
|
|
36
36
|
# Returns a value representing the "cost" of transforming str1 into str2
|
|
37
|
-
|
|
37
|
+
#: (String str1, String str2) -> Integer
|
|
38
38
|
def distance(str1, str2)
|
|
39
39
|
n = str1.length
|
|
40
40
|
m = str2.length
|
|
@@ -51,10 +51,12 @@ module CLI
|
|
|
51
51
|
j = 0
|
|
52
52
|
while j < m
|
|
53
53
|
cost = char1 == str2_codepoints[j] ? 0 : 1
|
|
54
|
+
a = d[j] #: as !nil
|
|
55
|
+
b = d[j + 1] #: as !nil
|
|
54
56
|
x = min3(
|
|
55
|
-
|
|
57
|
+
b + 1,
|
|
56
58
|
i + 1, # deletion
|
|
57
|
-
|
|
59
|
+
a + cost, # substitution
|
|
58
60
|
)
|
|
59
61
|
d[j] = i
|
|
60
62
|
i = x
|
|
@@ -74,7 +76,7 @@ module CLI
|
|
|
74
76
|
# faster than `[a, b, c].min` and puts less GC pressure.
|
|
75
77
|
# See https://github.com/yuki24/did_you_mean/pull/1 for a performance
|
|
76
78
|
# benchmark.
|
|
77
|
-
|
|
79
|
+
#: (Integer a, Integer b, Integer c) -> Integer
|
|
78
80
|
def min3(a, b, c)
|
|
79
81
|
if a < b && a < c
|
|
80
82
|
a
|
data/lib/cli/kit/logger.rb
CHANGED
|
@@ -7,15 +7,13 @@ require 'fileutils'
|
|
|
7
7
|
module CLI
|
|
8
8
|
module Kit
|
|
9
9
|
class Logger
|
|
10
|
-
extend T::Sig
|
|
11
|
-
|
|
12
10
|
MAX_LOG_SIZE = 5 * 1024 * 1000 # 5MB
|
|
13
11
|
MAX_NUM_LOGS = 10
|
|
14
12
|
|
|
15
13
|
# Constructor for CLI::Kit::Logger
|
|
16
14
|
#
|
|
17
15
|
# @param debug_log_file [String] path to the file where debug logs should be stored
|
|
18
|
-
|
|
16
|
+
#: (debug_log_file: String, ?env_debug_name: String) -> void
|
|
19
17
|
def initialize(debug_log_file:, env_debug_name: 'DEBUG')
|
|
20
18
|
FileUtils.mkpath(File.dirname(debug_log_file))
|
|
21
19
|
@debug_logger = ::Logger.new(debug_log_file, MAX_NUM_LOGS, MAX_LOG_SIZE)
|
|
@@ -27,7 +25,7 @@ module CLI
|
|
|
27
25
|
#
|
|
28
26
|
# @param msg [String] the message to log
|
|
29
27
|
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
30
|
-
|
|
28
|
+
#: (String msg, ?debug: bool) -> void
|
|
31
29
|
def info(msg, debug: true)
|
|
32
30
|
$stdout.puts CLI::UI.fmt(msg)
|
|
33
31
|
@debug_logger.info(format_debug(msg)) if debug
|
|
@@ -38,7 +36,7 @@ module CLI
|
|
|
38
36
|
#
|
|
39
37
|
# @param msg [String] the message to log
|
|
40
38
|
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
41
|
-
|
|
39
|
+
#: (String msg, ?debug: bool) -> void
|
|
42
40
|
def warn(msg, debug: true)
|
|
43
41
|
$stdout.puts CLI::UI.fmt("{{yellow:#{msg}}}")
|
|
44
42
|
@debug_logger.warn(format_debug(msg)) if debug
|
|
@@ -49,7 +47,7 @@ module CLI
|
|
|
49
47
|
#
|
|
50
48
|
# @param msg [String] the message to log
|
|
51
49
|
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
52
|
-
|
|
50
|
+
#: (String msg, ?debug: bool) -> void
|
|
53
51
|
def error(msg, debug: true)
|
|
54
52
|
$stderr.puts CLI::UI.fmt("{{red:#{msg}}}")
|
|
55
53
|
@debug_logger.error(format_debug(msg)) if debug
|
|
@@ -60,7 +58,7 @@ module CLI
|
|
|
60
58
|
#
|
|
61
59
|
# @param msg [String] the message to log
|
|
62
60
|
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
63
|
-
|
|
61
|
+
#: (String msg, ?debug: bool) -> void
|
|
64
62
|
def fatal(msg, debug: true)
|
|
65
63
|
$stderr.puts CLI::UI.fmt("{{red:{{bold:Fatal:}} #{msg}}}")
|
|
66
64
|
@debug_logger.fatal(format_debug(msg)) if debug
|
|
@@ -70,7 +68,7 @@ module CLI
|
|
|
70
68
|
# Logs to the debug file, taking into account CLI::UI::StdoutRouter.current_id
|
|
71
69
|
#
|
|
72
70
|
# @param msg [String] the message to log
|
|
73
|
-
|
|
71
|
+
#: (String msg) -> void
|
|
74
72
|
def debug(msg)
|
|
75
73
|
$stdout.puts CLI::UI.fmt(msg) if debug?
|
|
76
74
|
@debug_logger.debug(format_debug(msg))
|
|
@@ -78,7 +76,7 @@ module CLI
|
|
|
78
76
|
|
|
79
77
|
private
|
|
80
78
|
|
|
81
|
-
|
|
79
|
+
#: (String msg) -> String
|
|
82
80
|
def format_debug(msg)
|
|
83
81
|
msg = CLI::UI.fmt(msg)
|
|
84
82
|
return msg unless CLI::UI::StdoutRouter.current_id
|
|
@@ -86,7 +84,7 @@ module CLI
|
|
|
86
84
|
"[#{CLI::UI::StdoutRouter.current_id&.fetch(:id, nil)}] #{msg}"
|
|
87
85
|
end
|
|
88
86
|
|
|
89
|
-
|
|
87
|
+
#: -> bool
|
|
90
88
|
def debug?
|
|
91
89
|
val = ENV[@env_debug_name]
|
|
92
90
|
!!val && val != '0' && val != ''
|
data/lib/cli/kit/opts.rb
CHANGED
|
@@ -5,16 +5,11 @@ require 'cli/kit'
|
|
|
5
5
|
module CLI
|
|
6
6
|
module Kit
|
|
7
7
|
class Opts
|
|
8
|
-
extend T::Sig
|
|
9
|
-
|
|
10
8
|
module Mixin
|
|
11
|
-
extend T::Sig
|
|
12
9
|
include Kernel
|
|
13
10
|
|
|
14
11
|
module MixinClassMethods
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
sig { params(included_module: Module).void }
|
|
12
|
+
#: (Module included_module) -> void
|
|
18
13
|
def include(included_module)
|
|
19
14
|
super
|
|
20
15
|
return unless included_module.is_a?(MixinClassMethods)
|
|
@@ -28,36 +23,26 @@ module CLI
|
|
|
28
23
|
track_method(method_name)
|
|
29
24
|
end
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
#: (Symbol method_name) -> void
|
|
32
27
|
def track_method(method_name)
|
|
33
28
|
@tracked_methods ||= []
|
|
34
29
|
@tracked_methods << method_name unless @tracked_methods.include?(method_name)
|
|
35
30
|
end
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
#: -> Array[Symbol]
|
|
38
33
|
def tracked_methods
|
|
39
34
|
@tracked_methods || []
|
|
40
35
|
end
|
|
41
36
|
end
|
|
42
37
|
|
|
43
38
|
class << self
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
sig { params(klass: Module).void }
|
|
39
|
+
#: (Module klass) -> void
|
|
47
40
|
def included(klass)
|
|
48
41
|
klass.extend(MixinClassMethods)
|
|
49
42
|
end
|
|
50
43
|
end
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
params(
|
|
54
|
-
name: Symbol,
|
|
55
|
-
short: T.nilable(String),
|
|
56
|
-
long: T.nilable(String),
|
|
57
|
-
desc: T.nilable(String),
|
|
58
|
-
default: T.any(NilClass, String, T.proc.returns(String)),
|
|
59
|
-
).returns(T.nilable(String))
|
|
60
|
-
end
|
|
45
|
+
#: (?name: Symbol, ?short: String?, ?long: String?, ?desc: String?, ?default: (String | ^-> String)?) -> String?
|
|
61
46
|
def option(name: infer_name, short: nil, long: nil, desc: nil, default: nil)
|
|
62
47
|
unless default.nil?
|
|
63
48
|
raise(ArgumentError, 'declare options with non-nil defaults using `option!` instead of `option`')
|
|
@@ -74,15 +59,7 @@ module CLI
|
|
|
74
59
|
end
|
|
75
60
|
end
|
|
76
61
|
|
|
77
|
-
|
|
78
|
-
params(
|
|
79
|
-
name: Symbol,
|
|
80
|
-
short: T.nilable(String),
|
|
81
|
-
long: T.nilable(String),
|
|
82
|
-
desc: T.nilable(String),
|
|
83
|
-
default: T.any(NilClass, String, T.proc.returns(String)),
|
|
84
|
-
).returns(String)
|
|
85
|
-
end
|
|
62
|
+
#: (?name: Symbol, ?short: String?, ?long: String?, ?desc: String?, ?default: (String | ^-> String)?) -> String
|
|
86
63
|
def option!(name: infer_name, short: nil, long: nil, desc: nil, default: nil)
|
|
87
64
|
case @obj
|
|
88
65
|
when Args::Definition
|
|
@@ -95,15 +72,7 @@ module CLI
|
|
|
95
72
|
end
|
|
96
73
|
end
|
|
97
74
|
|
|
98
|
-
|
|
99
|
-
params(
|
|
100
|
-
name: Symbol,
|
|
101
|
-
short: T.nilable(String),
|
|
102
|
-
long: T.nilable(String),
|
|
103
|
-
desc: T.nilable(String),
|
|
104
|
-
default: T.any(T::Array[String], T.proc.returns(T::Array[String])),
|
|
105
|
-
).returns(T::Array[String])
|
|
106
|
-
end
|
|
75
|
+
#: (?name: Symbol, ?short: String?, ?long: String?, ?desc: String?, ?default: (Array[String] | ^-> Array[String])) -> Array[String]
|
|
107
76
|
def multi_option(name: infer_name, short: nil, long: nil, desc: nil, default: [])
|
|
108
77
|
case @obj
|
|
109
78
|
when Args::Definition
|
|
@@ -116,14 +85,7 @@ module CLI
|
|
|
116
85
|
end
|
|
117
86
|
end
|
|
118
87
|
|
|
119
|
-
|
|
120
|
-
params(
|
|
121
|
-
name: Symbol,
|
|
122
|
-
short: T.nilable(String),
|
|
123
|
-
long: T.nilable(String),
|
|
124
|
-
desc: T.nilable(String),
|
|
125
|
-
).returns(T::Boolean)
|
|
126
|
-
end
|
|
88
|
+
#: (?name: Symbol, ?short: String?, ?long: String?, ?desc: String?) -> bool
|
|
127
89
|
def flag(name: infer_name, short: nil, long: nil, desc: nil)
|
|
128
90
|
case @obj
|
|
129
91
|
when Args::Definition
|
|
@@ -134,7 +96,7 @@ module CLI
|
|
|
134
96
|
end
|
|
135
97
|
end
|
|
136
98
|
|
|
137
|
-
|
|
99
|
+
#: (?name: Symbol, ?desc: String?) -> String
|
|
138
100
|
def position!(name: infer_name, desc: nil)
|
|
139
101
|
case @obj
|
|
140
102
|
when Args::Definition
|
|
@@ -145,18 +107,7 @@ module CLI
|
|
|
145
107
|
end
|
|
146
108
|
end
|
|
147
109
|
|
|
148
|
-
|
|
149
|
-
params(
|
|
150
|
-
name: Symbol,
|
|
151
|
-
desc: T.nilable(String),
|
|
152
|
-
default: T.any(NilClass, String, T.proc.returns(String)),
|
|
153
|
-
skip: T.any(
|
|
154
|
-
NilClass,
|
|
155
|
-
T.proc.returns(T::Boolean),
|
|
156
|
-
T.proc.params(arg0: String).returns(T::Boolean),
|
|
157
|
-
),
|
|
158
|
-
).returns(T.nilable(String))
|
|
159
|
-
end
|
|
110
|
+
#: (?name: Symbol, ?desc: String?, ?default: (String | ^-> String)?, ?skip: (^-> bool | ^(String arg0) -> bool)?) -> String?
|
|
160
111
|
def position(name: infer_name, desc: nil, default: nil, skip: nil)
|
|
161
112
|
case @obj
|
|
162
113
|
when Args::Definition
|
|
@@ -167,7 +118,7 @@ module CLI
|
|
|
167
118
|
end
|
|
168
119
|
end
|
|
169
120
|
|
|
170
|
-
|
|
121
|
+
#: (?name: Symbol, ?desc: String?) -> Array[String]
|
|
171
122
|
def rest(name: infer_name, desc: nil)
|
|
172
123
|
case @obj
|
|
173
124
|
when Args::Definition
|
|
@@ -180,14 +131,14 @@ module CLI
|
|
|
180
131
|
|
|
181
132
|
private
|
|
182
133
|
|
|
183
|
-
|
|
134
|
+
#: (String? label) -> Symbol?
|
|
184
135
|
def symbolize(label)
|
|
185
136
|
return if label.nil?
|
|
186
137
|
|
|
187
138
|
label.split('#').last&.to_sym
|
|
188
139
|
end
|
|
189
140
|
|
|
190
|
-
|
|
141
|
+
#: -> Symbol
|
|
191
142
|
def infer_name
|
|
192
143
|
to_skip = 1
|
|
193
144
|
Kernel.caller_locations.each do |loc|
|
|
@@ -197,7 +148,7 @@ module CLI
|
|
|
197
148
|
to_skip -= 1
|
|
198
149
|
next
|
|
199
150
|
end
|
|
200
|
-
return
|
|
151
|
+
return symbolize(loc.label) #: as !nil
|
|
201
152
|
end
|
|
202
153
|
raise(ArgumentError, 'could not infer name')
|
|
203
154
|
end
|
|
@@ -206,24 +157,18 @@ module CLI
|
|
|
206
157
|
|
|
207
158
|
DEFAULT_OPTIONS = [:helpflag]
|
|
208
159
|
|
|
209
|
-
|
|
160
|
+
#: -> bool
|
|
210
161
|
def helpflag
|
|
211
162
|
flag(name: :help, short: '-h', long: '--help', desc: 'Show this help message')
|
|
212
163
|
end
|
|
213
164
|
|
|
214
|
-
|
|
165
|
+
#: -> Array[String]
|
|
215
166
|
def unparsed
|
|
216
167
|
obj = assert_result!
|
|
217
168
|
obj.unparsed
|
|
218
169
|
end
|
|
219
170
|
|
|
220
|
-
|
|
221
|
-
params(
|
|
222
|
-
block: T.nilable(
|
|
223
|
-
T.proc.params(arg0: Symbol, arg1: T.nilable(String)).void,
|
|
224
|
-
),
|
|
225
|
-
).returns(T.untyped)
|
|
226
|
-
end
|
|
171
|
+
#: ?{ (Symbol arg0, String? arg1) -> void } -> untyped
|
|
227
172
|
def each_option(&block)
|
|
228
173
|
return enum_for(:each_option) unless block_given?
|
|
229
174
|
|
|
@@ -235,13 +180,7 @@ module CLI
|
|
|
235
180
|
end
|
|
236
181
|
end
|
|
237
182
|
|
|
238
|
-
|
|
239
|
-
params(
|
|
240
|
-
block: T.nilable(
|
|
241
|
-
T.proc.params(arg0: Symbol, arg1: T::Boolean).void,
|
|
242
|
-
),
|
|
243
|
-
).returns(T.untyped)
|
|
244
|
-
end
|
|
183
|
+
#: ?{ (Symbol arg0, bool arg1) -> void } -> untyped
|
|
245
184
|
def each_flag(&block)
|
|
246
185
|
return enum_for(:each_flag) unless block_given?
|
|
247
186
|
|
|
@@ -253,7 +192,7 @@ module CLI
|
|
|
253
192
|
end
|
|
254
193
|
end
|
|
255
194
|
|
|
256
|
-
|
|
195
|
+
#: (String name) -> (String | bool)?
|
|
257
196
|
def [](name)
|
|
258
197
|
obj = assert_result!
|
|
259
198
|
if obj.opt.respond_to?(name)
|
|
@@ -263,7 +202,7 @@ module CLI
|
|
|
263
202
|
end
|
|
264
203
|
end
|
|
265
204
|
|
|
266
|
-
|
|
205
|
+
#: (String name) -> String?
|
|
267
206
|
def lookup_option(name)
|
|
268
207
|
obj = assert_result!
|
|
269
208
|
obj.opt.send(name)
|
|
@@ -272,7 +211,7 @@ module CLI
|
|
|
272
211
|
nil
|
|
273
212
|
end
|
|
274
213
|
|
|
275
|
-
|
|
214
|
+
#: (String name) -> bool
|
|
276
215
|
def lookup_flag(name)
|
|
277
216
|
obj = assert_result!
|
|
278
217
|
obj.flag.send(name)
|
|
@@ -280,17 +219,18 @@ module CLI
|
|
|
280
219
|
false
|
|
281
220
|
end
|
|
282
221
|
|
|
283
|
-
|
|
222
|
+
#: -> Args::Evaluation
|
|
284
223
|
def assert_result!
|
|
285
224
|
raise(NotImplementedError, 'not implemented') if @obj.is_a?(Args::Definition)
|
|
286
225
|
|
|
287
226
|
@obj
|
|
288
227
|
end
|
|
289
228
|
|
|
290
|
-
|
|
229
|
+
#: (Args::Definition defn) -> void
|
|
291
230
|
def define!(defn)
|
|
292
231
|
@obj = defn
|
|
293
|
-
|
|
232
|
+
klass = self.class #: as Mixin::MixinClassMethods
|
|
233
|
+
klass.tracked_methods.each do |m|
|
|
294
234
|
send(m)
|
|
295
235
|
end
|
|
296
236
|
DEFAULT_OPTIONS.each do |m|
|
|
@@ -298,7 +238,7 @@ module CLI
|
|
|
298
238
|
end
|
|
299
239
|
end
|
|
300
240
|
|
|
301
|
-
|
|
241
|
+
#: (Args::Evaluation ev) -> void
|
|
302
242
|
def evaluate!(ev)
|
|
303
243
|
@obj = ev
|
|
304
244
|
ev.resolve_positions!
|
data/lib/cli/kit/parse_args.rb
CHANGED
|
@@ -6,18 +6,12 @@ module CLI
|
|
|
6
6
|
# because sorbet type-checking takes the pedantic route that module doesn't include Kernel, therefore
|
|
7
7
|
# this is necessary (even tho it's ~probably fine~)
|
|
8
8
|
include Kernel
|
|
9
|
-
extend T::Sig
|
|
10
9
|
|
|
11
|
-
#
|
|
10
|
+
# untyped is used in two places. The interpretation of dynamic values from the provided `opts`
|
|
12
11
|
# and the resulting args[:opts] is pretty broad. There seems to be minimal value in expressing a
|
|
13
|
-
# tighter subset of
|
|
12
|
+
# tighter subset of untyped.
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
params(
|
|
17
|
-
args: T.any(Array, String),
|
|
18
|
-
opts_defn: T::Hash[Symbol, T::Array[T.untyped]],
|
|
19
|
-
).returns(T::Hash[Symbol, T.untyped])
|
|
20
|
-
end
|
|
14
|
+
#: ((Array | String) args, Hash[Symbol, Array[untyped]] opts_defn) -> Hash[Symbol, untyped]
|
|
21
15
|
def parse_args(args, opts_defn)
|
|
22
16
|
start_opts, parser_config = opts_defn.reduce([{}, []]) do |(ini, pcfg), (n, cfg)|
|
|
23
17
|
(vals, desc, short, klass) = cfg
|
|
@@ -38,7 +32,8 @@ module CLI
|
|
|
38
32
|
long = "--#{n.to_s.tr("_", "-")}" + (mark.nil? ? '' : " #{mark}")
|
|
39
33
|
opt_args = klass.nil? ? [short, long, desc] : [short, long, klass, desc]
|
|
40
34
|
|
|
41
|
-
|
|
35
|
+
unsafe_opt_p = opt_p #: as untyped
|
|
36
|
+
unsafe_opt_p.on(*opt_args) do |v|
|
|
42
37
|
acc_opts[n] = if acc_opts.key?(n)
|
|
43
38
|
Array(acc_opts[n]) + Array(v || def_val)
|
|
44
39
|
else
|
data/lib/cli/kit/resolver.rb
CHANGED
|
@@ -5,15 +5,13 @@ require 'cli/kit'
|
|
|
5
5
|
module CLI
|
|
6
6
|
module Kit
|
|
7
7
|
class Resolver
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
sig { params(tool_name: String, command_registry: CLI::Kit::CommandRegistry).void }
|
|
8
|
+
#: (tool_name: String, command_registry: CLI::Kit::CommandRegistry) -> void
|
|
11
9
|
def initialize(tool_name:, command_registry:)
|
|
12
10
|
@tool_name = tool_name
|
|
13
11
|
@command_registry = command_registry
|
|
14
12
|
end
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
#: (Array[String] args) -> [singleton(CLI::Kit::BaseCommand), String, Array[String]]
|
|
17
15
|
def call(args)
|
|
18
16
|
args = args.dup
|
|
19
17
|
command_name = args.shift
|
|
@@ -30,7 +28,7 @@ module CLI
|
|
|
30
28
|
|
|
31
29
|
private
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
#: (String? name) -> void
|
|
34
32
|
def command_not_found(name)
|
|
35
33
|
CLI::UI::Frame.open('Command not found', color: :red, timing: false) do
|
|
36
34
|
$stderr.puts(CLI::UI.fmt("{{command:#{@tool_name} #{name}}} was not found"))
|
|
@@ -59,7 +57,7 @@ module CLI
|
|
|
59
57
|
end
|
|
60
58
|
end
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
#: -> Array[String]
|
|
63
61
|
def commands_and_aliases
|
|
64
62
|
@command_registry.command_names + @command_registry.aliases.keys
|
|
65
63
|
end
|
|
@@ -14,7 +14,8 @@ module CLI
|
|
|
14
14
|
CLI::Kit::System.reset!
|
|
15
15
|
# this is in minitest, but sorbet doesn't know that. probably we
|
|
16
16
|
# could structure this better.
|
|
17
|
-
|
|
17
|
+
uself = self #: as untyped
|
|
18
|
+
uself.assert(false, errors) if should_raise && !errors.nil?
|
|
18
19
|
errors
|
|
19
20
|
end
|
|
20
21
|
|
|
@@ -67,7 +68,8 @@ module CLI
|
|
|
67
68
|
|
|
68
69
|
# Otherwise handle the command
|
|
69
70
|
if expected_command[:allow]
|
|
70
|
-
|
|
71
|
+
uself = self #: as untyped
|
|
72
|
+
uself.original_system(*a, sudo: sudo, env: env, **kwargs)
|
|
71
73
|
else
|
|
72
74
|
FakeSuccess.new(expected_command[:success])
|
|
73
75
|
end
|
|
@@ -83,7 +85,8 @@ module CLI
|
|
|
83
85
|
|
|
84
86
|
# Otherwise handle the command
|
|
85
87
|
if expected_command[:allow]
|
|
86
|
-
|
|
88
|
+
uself = self #: as untyped
|
|
89
|
+
uself.original_capture2(*a, sudo: sudo, env: env, **kwargs)
|
|
87
90
|
else
|
|
88
91
|
[
|
|
89
92
|
expected_command[:stdout],
|
|
@@ -102,7 +105,8 @@ module CLI
|
|
|
102
105
|
|
|
103
106
|
# Otherwise handle the command
|
|
104
107
|
if expected_command[:allow]
|
|
105
|
-
|
|
108
|
+
uself = self #: as untyped
|
|
109
|
+
uself.original_capture2e(*a, sudo: sudo, env: env, **kwargs)
|
|
106
110
|
else
|
|
107
111
|
[
|
|
108
112
|
expected_command[:stdout],
|
|
@@ -121,7 +125,8 @@ module CLI
|
|
|
121
125
|
|
|
122
126
|
# Otherwise handle the command
|
|
123
127
|
if expected_command[:allow]
|
|
124
|
-
|
|
128
|
+
uself = self #: as untyped
|
|
129
|
+
uself.original_capture3(*a, sudo: sudo, env: env, **kwargs)
|
|
125
130
|
else
|
|
126
131
|
[
|
|
127
132
|
expected_command[:stdout],
|