ronin-core 0.1.0.beta1
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 +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +41 -0
- data/.gitignore +12 -0
- data/.rspec +1 -0
- data/.rubocop.yml +160 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +11 -0
- data/Gemfile +30 -0
- data/README.md +299 -0
- data/Rakefile +34 -0
- data/examples/ruby_shell.rb +11 -0
- data/gemspec.yml +28 -0
- data/lib/ronin/core/class_registry.rb +246 -0
- data/lib/ronin/core/cli/command.rb +87 -0
- data/lib/ronin/core/cli/command_shell/command.rb +110 -0
- data/lib/ronin/core/cli/command_shell.rb +345 -0
- data/lib/ronin/core/cli/generator/options/author.rb +106 -0
- data/lib/ronin/core/cli/generator/options/description.rb +54 -0
- data/lib/ronin/core/cli/generator/options/reference.rb +60 -0
- data/lib/ronin/core/cli/generator/options/summary.rb +54 -0
- data/lib/ronin/core/cli/generator.rb +238 -0
- data/lib/ronin/core/cli/logging.rb +59 -0
- data/lib/ronin/core/cli/options/param.rb +68 -0
- data/lib/ronin/core/cli/options/values/arches.rb +45 -0
- data/lib/ronin/core/cli/options/values/oses.rb +32 -0
- data/lib/ronin/core/cli/printing/arch.rb +71 -0
- data/lib/ronin/core/cli/printing/metadata.rb +113 -0
- data/lib/ronin/core/cli/printing/os.rb +54 -0
- data/lib/ronin/core/cli/printing/params.rb +69 -0
- data/lib/ronin/core/cli/ruby_shell.rb +131 -0
- data/lib/ronin/core/cli/shell.rb +186 -0
- data/lib/ronin/core/git.rb +73 -0
- data/lib/ronin/core/home.rb +86 -0
- data/lib/ronin/core/metadata/authors/author.rb +241 -0
- data/lib/ronin/core/metadata/authors.rb +120 -0
- data/lib/ronin/core/metadata/description.rb +100 -0
- data/lib/ronin/core/metadata/id.rb +88 -0
- data/lib/ronin/core/metadata/references.rb +87 -0
- data/lib/ronin/core/metadata/summary.rb +78 -0
- data/lib/ronin/core/metadata/version.rb +74 -0
- data/lib/ronin/core/params/exceptions.rb +38 -0
- data/lib/ronin/core/params/mixin.rb +317 -0
- data/lib/ronin/core/params/param.rb +137 -0
- data/lib/ronin/core/params/types/boolean.rb +64 -0
- data/lib/ronin/core/params/types/enum.rb +107 -0
- data/lib/ronin/core/params/types/float.rb +68 -0
- data/lib/ronin/core/params/types/integer.rb +100 -0
- data/lib/ronin/core/params/types/numeric.rb +106 -0
- data/lib/ronin/core/params/types/regexp.rb +67 -0
- data/lib/ronin/core/params/types/string.rb +118 -0
- data/lib/ronin/core/params/types/type.rb +54 -0
- data/lib/ronin/core/params/types/uri.rb +72 -0
- data/lib/ronin/core/params/types.rb +62 -0
- data/lib/ronin/core/params.rb +19 -0
- data/lib/ronin/core/version.rb +24 -0
- data/ronin-core.gemspec +59 -0
- data/spec/class_registry_spec.rb +224 -0
- data/spec/cli/command_shell/command_spec.rb +113 -0
- data/spec/cli/command_shell_spec.rb +1114 -0
- data/spec/cli/command_spec.rb +16 -0
- data/spec/cli/fixtures/irb_command +8 -0
- data/spec/cli/fixtures/template/dir/file1.txt +1 -0
- data/spec/cli/fixtures/template/dir/file2.txt +1 -0
- data/spec/cli/fixtures/template/file.erb +1 -0
- data/spec/cli/fixtures/template/file.txt +1 -0
- data/spec/cli/generator/options/author_spec.rb +121 -0
- data/spec/cli/generator/options/description_spec.rb +45 -0
- data/spec/cli/generator/options/reference_spec.rb +53 -0
- data/spec/cli/generator/options/summary_spec.rb +45 -0
- data/spec/cli/generator_spec.rb +244 -0
- data/spec/cli/logging_spec.rb +95 -0
- data/spec/cli/options/param_spec.rb +67 -0
- data/spec/cli/options/values/arches_spec.rb +62 -0
- data/spec/cli/printing/arch_spec.rb +130 -0
- data/spec/cli/printing/metadata_spec.rb +211 -0
- data/spec/cli/printing/os_spec.rb +64 -0
- data/spec/cli/printing/params_spec.rb +63 -0
- data/spec/cli/ruby_shell.rb +99 -0
- data/spec/cli/shell_spec.rb +211 -0
- data/spec/fixtures/example_class_registry/base_class.rb +9 -0
- data/spec/fixtures/example_class_registry/classes/loaded_class.rb +9 -0
- data/spec/fixtures/example_class_registry/classes/name_mismatch.rb +9 -0
- data/spec/fixtures/example_class_registry/classes/no_module.rb +4 -0
- data/spec/fixtures/example_class_registry.rb +8 -0
- data/spec/git_spec.rb +58 -0
- data/spec/home_spec.rb +64 -0
- data/spec/metadata/authors/author_spec.rb +335 -0
- data/spec/metadata/authors_spec.rb +126 -0
- data/spec/metadata/description_spec.rb +74 -0
- data/spec/metadata/id_spec.rb +92 -0
- data/spec/metadata/references_spec.rb +100 -0
- data/spec/metadata/summary_spec.rb +74 -0
- data/spec/metadata/version_spec.rb +72 -0
- data/spec/params/mixin_spec.rb +484 -0
- data/spec/params/param_spec.rb +164 -0
- data/spec/params/types/boolean_spec.rb +56 -0
- data/spec/params/types/enum_spec.rb +94 -0
- data/spec/params/types/float_spec.rb +107 -0
- data/spec/params/types/integer_spec.rb +155 -0
- data/spec/params/types/numeric_spec.rb +138 -0
- data/spec/params/types/regexp_spec.rb +64 -0
- data/spec/params/types/string_spec.rb +174 -0
- data/spec/params/types/type_spec.rb +14 -0
- data/spec/params/types/uri_spec.rb +62 -0
- data/spec/spec_helper.rb +11 -0
- metadata +252 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
4
|
+
#
|
|
5
|
+
# ronin-core is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published
|
|
7
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# ronin-core is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require 'ronin/core/cli/shell'
|
|
20
|
+
|
|
21
|
+
module Ronin
|
|
22
|
+
module Core
|
|
23
|
+
module CLI
|
|
24
|
+
class CommandShell < Shell
|
|
25
|
+
class Command
|
|
26
|
+
|
|
27
|
+
# The command's name.
|
|
28
|
+
#
|
|
29
|
+
# @return [Symbol]
|
|
30
|
+
attr_reader :name
|
|
31
|
+
|
|
32
|
+
# The command's method name.
|
|
33
|
+
#
|
|
34
|
+
# @return [Symbol]
|
|
35
|
+
attr_reader :method_name
|
|
36
|
+
|
|
37
|
+
# The usage string for the command's arguments.
|
|
38
|
+
#
|
|
39
|
+
# @return [String, nil]
|
|
40
|
+
attr_reader :usage
|
|
41
|
+
|
|
42
|
+
# Possible tab completion values for the command's arguments.
|
|
43
|
+
#
|
|
44
|
+
# @return [Array<String>, Symbol, nil]
|
|
45
|
+
attr_reader :completions
|
|
46
|
+
|
|
47
|
+
# The command's one-line summary.
|
|
48
|
+
#
|
|
49
|
+
# @return [String]
|
|
50
|
+
attr_reader :summary
|
|
51
|
+
|
|
52
|
+
# The command's multi-line help output.
|
|
53
|
+
#
|
|
54
|
+
# @return [String]
|
|
55
|
+
attr_reader :help
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# Initializes a command value object.
|
|
59
|
+
#
|
|
60
|
+
# @param [Symbol] name
|
|
61
|
+
# The name of the command.
|
|
62
|
+
#
|
|
63
|
+
# @param [Symbol] method_name
|
|
64
|
+
# The command's method name. Defaults to the name argument.
|
|
65
|
+
#
|
|
66
|
+
# @param [String, nil] usage
|
|
67
|
+
# The usage string for the command's arguments.
|
|
68
|
+
#
|
|
69
|
+
# @param [Array<String>, Symbol, nil] completions
|
|
70
|
+
# Potential tab completion values, or a method name, to complete
|
|
71
|
+
# the command's arguments.
|
|
72
|
+
#
|
|
73
|
+
# @param [String] summary
|
|
74
|
+
# A single line summary for the command.
|
|
75
|
+
#
|
|
76
|
+
# @param [String] help
|
|
77
|
+
# Multi-line help information for the command.
|
|
78
|
+
#
|
|
79
|
+
def initialize(name, method_name: name,
|
|
80
|
+
usage: nil,
|
|
81
|
+
completions: nil,
|
|
82
|
+
summary: ,
|
|
83
|
+
help: summary)
|
|
84
|
+
@name = name
|
|
85
|
+
@method_name = method_name
|
|
86
|
+
@usage = usage
|
|
87
|
+
@summary = summary
|
|
88
|
+
@help = help
|
|
89
|
+
@completions = completions
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
# Converts the command to a String.
|
|
94
|
+
#
|
|
95
|
+
# @return [String]
|
|
96
|
+
# The command name and the optional usage.
|
|
97
|
+
#
|
|
98
|
+
def to_s
|
|
99
|
+
if @usage
|
|
100
|
+
"#{@name} #{@usage}"
|
|
101
|
+
else
|
|
102
|
+
@name.to_s
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
4
|
+
#
|
|
5
|
+
# ronin-core is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published
|
|
7
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# ronin-core is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require 'ronin/core/cli/shell'
|
|
20
|
+
require 'ronin/core/cli/command_shell/command'
|
|
21
|
+
|
|
22
|
+
require 'shellwords'
|
|
23
|
+
|
|
24
|
+
module Ronin
|
|
25
|
+
module Core
|
|
26
|
+
module CLI
|
|
27
|
+
#
|
|
28
|
+
# Base class for all custom command shells.
|
|
29
|
+
#
|
|
30
|
+
# ## Example
|
|
31
|
+
#
|
|
32
|
+
# class HTTPShell < Ronin::Core::CLI::Shell
|
|
33
|
+
#
|
|
34
|
+
# shell_name 'http'
|
|
35
|
+
#
|
|
36
|
+
# command :get, usage: 'PATH [HEADERS...]',
|
|
37
|
+
# summary: 'Sends a GET request'
|
|
38
|
+
# def get(path,*headers)
|
|
39
|
+
# # ...
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# command :post, usage: 'PATH DATA [HEADERS...]',
|
|
43
|
+
# summary: 'Sends a POST request'
|
|
44
|
+
# def post(path,data,*headers)
|
|
45
|
+
# # ...
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# end
|
|
49
|
+
#
|
|
50
|
+
# HTTPShell.start
|
|
51
|
+
# # http> get /foo
|
|
52
|
+
#
|
|
53
|
+
# @api semipublic
|
|
54
|
+
#
|
|
55
|
+
class CommandShell < Shell
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# The registered shell commands.
|
|
59
|
+
#
|
|
60
|
+
# @return [Hash{String => CommandShell::Command}]
|
|
61
|
+
# The registered shell commands.
|
|
62
|
+
#
|
|
63
|
+
def self.commands
|
|
64
|
+
@commands ||= if superclass <= CommandShell
|
|
65
|
+
superclass.commands.dup
|
|
66
|
+
else
|
|
67
|
+
{}
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# Registers a shell command.
|
|
73
|
+
#
|
|
74
|
+
# @param [Symbol] name
|
|
75
|
+
# The name of the shell command.
|
|
76
|
+
#
|
|
77
|
+
# @param [Symbol] method_name
|
|
78
|
+
# Optional method name to use. Defaults to the name argument.
|
|
79
|
+
#
|
|
80
|
+
# @param [String, nil] usage
|
|
81
|
+
# A usage string indicating the shell command's options/arguments.
|
|
82
|
+
#
|
|
83
|
+
# @param [Array<String>, Symbol, nil] completions
|
|
84
|
+
# The possible tab completion values, or a method name, to complete
|
|
85
|
+
# the command's arguments.
|
|
86
|
+
#
|
|
87
|
+
# @param [String] summary
|
|
88
|
+
# A one-line summary of the shell command.
|
|
89
|
+
#
|
|
90
|
+
# @param [String] help
|
|
91
|
+
# Multi-line help output for the shell command.
|
|
92
|
+
#
|
|
93
|
+
def self.command(name, method_name: name,
|
|
94
|
+
usage: nil,
|
|
95
|
+
completions: nil,
|
|
96
|
+
summary: ,
|
|
97
|
+
help: summary)
|
|
98
|
+
commands[name.to_s] = Command.new(name, method_name: method_name,
|
|
99
|
+
usage: usage,
|
|
100
|
+
completions: completions,
|
|
101
|
+
summary: summary,
|
|
102
|
+
help: help.strip)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
#
|
|
106
|
+
# Parses a line of input.
|
|
107
|
+
#
|
|
108
|
+
# @param [String] line
|
|
109
|
+
# A line of input.
|
|
110
|
+
#
|
|
111
|
+
# @return [String, Array<String>]
|
|
112
|
+
# The command name and any additional arguments.
|
|
113
|
+
#
|
|
114
|
+
def self.parse_command(line)
|
|
115
|
+
Shellwords.shellsplit(line)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#
|
|
119
|
+
# The partially input being tab completed.
|
|
120
|
+
#
|
|
121
|
+
# @param [String] word
|
|
122
|
+
# The partial input being tab completed.
|
|
123
|
+
#
|
|
124
|
+
# @param [String] preposing
|
|
125
|
+
# The optional command name that preceeds the argument that's being
|
|
126
|
+
# tab completed.
|
|
127
|
+
#
|
|
128
|
+
# @return [Array<String>, nil]
|
|
129
|
+
# The possible completion values.
|
|
130
|
+
#
|
|
131
|
+
# @raise [NotImplementedError]
|
|
132
|
+
# The command defined a completion method name but the command shell
|
|
133
|
+
# does not define the complete method name.
|
|
134
|
+
#
|
|
135
|
+
def complete(word,preposing)
|
|
136
|
+
if preposing.empty?
|
|
137
|
+
self.class.commands.keys.select { |name| name.start_with?(word) }
|
|
138
|
+
else
|
|
139
|
+
name = preposing.split(/\s+/,2).first
|
|
140
|
+
|
|
141
|
+
if (command = self.class.commands[name])
|
|
142
|
+
completions = case command.completions
|
|
143
|
+
when Array then command.completions
|
|
144
|
+
when Symbol
|
|
145
|
+
unless respond_to?(command.completions)
|
|
146
|
+
raise(NotImplementedError,"#{self.class}##{command.completions} was not defined")
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
send(command.completions,word,preposing)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
if completions
|
|
153
|
+
completions.select { |arg| arg.start_with?(word) }
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
#
|
|
160
|
+
# Executes a command.
|
|
161
|
+
#
|
|
162
|
+
# @param [String] command
|
|
163
|
+
# The command to execute.
|
|
164
|
+
#
|
|
165
|
+
# @return [Boolean]
|
|
166
|
+
# Indicates whether the command was successfully executed.
|
|
167
|
+
#
|
|
168
|
+
def exec(command)
|
|
169
|
+
call(*self.class.parse_command(command))
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
#
|
|
173
|
+
# Invokes the command with the matching name.
|
|
174
|
+
#
|
|
175
|
+
# @param [String] name
|
|
176
|
+
# The command name.
|
|
177
|
+
#
|
|
178
|
+
# @param [Array<String>] args
|
|
179
|
+
# Additional arguments for the command.
|
|
180
|
+
#
|
|
181
|
+
# @return [Boolean]
|
|
182
|
+
# Indicates whether the command was successfully executed.
|
|
183
|
+
#
|
|
184
|
+
# @raise [NotImplementedError]
|
|
185
|
+
# The method for the command was not defined.
|
|
186
|
+
#
|
|
187
|
+
def call(name,*args)
|
|
188
|
+
unless (command = self.class.commands[name])
|
|
189
|
+
return command_missing(name,*args)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
method_name = command.method_name
|
|
193
|
+
|
|
194
|
+
unless respond_to?(method_name,false)
|
|
195
|
+
raise(NotImplementedError,"#{self.class}##{method_name} was not defined for the #{name.inspect} command")
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
unless method_arity_check(method_name,args)
|
|
199
|
+
return false
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
begin
|
|
203
|
+
send(method_name,*args)
|
|
204
|
+
rescue => error
|
|
205
|
+
print_exception(error)
|
|
206
|
+
print_error "an unhandled exception occurred in the #{name} command"
|
|
207
|
+
return false
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
return true
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
#
|
|
214
|
+
# Default method that is called when an unknown command is called.
|
|
215
|
+
#
|
|
216
|
+
# @param [String] name
|
|
217
|
+
#
|
|
218
|
+
# @param [Array<String>] args
|
|
219
|
+
#
|
|
220
|
+
def command_missing(name,*args)
|
|
221
|
+
command_not_found(name)
|
|
222
|
+
return false
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
#
|
|
226
|
+
# Prints an error message when an unknown command is given.
|
|
227
|
+
#
|
|
228
|
+
# @param [String] name
|
|
229
|
+
#
|
|
230
|
+
def command_not_found(name)
|
|
231
|
+
print_error "unknown command: #{name}"
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
command :help, usage: '[COMMAND]',
|
|
235
|
+
summary: 'Prints the list of commands or additional help'
|
|
236
|
+
|
|
237
|
+
#
|
|
238
|
+
# Prints all commands or help information for the given command.
|
|
239
|
+
#
|
|
240
|
+
# @param [String, nil] command
|
|
241
|
+
# Optional command name to print help information for.
|
|
242
|
+
#
|
|
243
|
+
def help(command=nil)
|
|
244
|
+
if command then help_command(command)
|
|
245
|
+
else help_commands
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
private
|
|
250
|
+
|
|
251
|
+
#
|
|
252
|
+
# Prints a list of all registered commands.
|
|
253
|
+
#
|
|
254
|
+
def help_commands
|
|
255
|
+
command_table = self.class.commands.map do |name,command|
|
|
256
|
+
[command.to_s, command.summary]
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
max_command_string = command_table.map { |command_string,summary|
|
|
260
|
+
command_string.length
|
|
261
|
+
}.max
|
|
262
|
+
|
|
263
|
+
command_table.each do |command_string,summary|
|
|
264
|
+
puts " #{command_string.ljust(max_command_string)}\t#{summary}"
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
#
|
|
269
|
+
# Prints help information about a specific command.
|
|
270
|
+
#
|
|
271
|
+
# @param [String] name
|
|
272
|
+
# The given command name.
|
|
273
|
+
#
|
|
274
|
+
def help_command(name)
|
|
275
|
+
unless (command = self.class.commands[name])
|
|
276
|
+
print_error "help: unknown command: #{name}"
|
|
277
|
+
return
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
puts "usage: #{command}"
|
|
281
|
+
|
|
282
|
+
if command.help
|
|
283
|
+
puts
|
|
284
|
+
puts command.help
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
#
|
|
289
|
+
# Calculates the minimum and maximum number of arguments for a given
|
|
290
|
+
# command method.
|
|
291
|
+
#
|
|
292
|
+
# @param [String] name
|
|
293
|
+
# The method name.
|
|
294
|
+
#
|
|
295
|
+
# @return [(Integer, Integer)]
|
|
296
|
+
# The minimum and maximum number of arguments for the method.
|
|
297
|
+
#
|
|
298
|
+
def minimum_maximum_args(name)
|
|
299
|
+
minimum = maximum = 0
|
|
300
|
+
|
|
301
|
+
method(name).parameters.each do |(type,arg)|
|
|
302
|
+
case type
|
|
303
|
+
when :req
|
|
304
|
+
minimum += 1
|
|
305
|
+
maximum += 1
|
|
306
|
+
when :opt then maximum += 1
|
|
307
|
+
when :rest then maximum = Float::INFINITY
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
return minimum, maximum
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
#
|
|
315
|
+
# Performs an arity check between the method's number of arguments and
|
|
316
|
+
# the number of arguments given.
|
|
317
|
+
#
|
|
318
|
+
# @param [String] name
|
|
319
|
+
# The method name to lookup.
|
|
320
|
+
#
|
|
321
|
+
# @param [Array<String>] args
|
|
322
|
+
# The given arguments.
|
|
323
|
+
#
|
|
324
|
+
# @return [Boolean]
|
|
325
|
+
# Indicates whether the method can accept the given number of
|
|
326
|
+
# arguments.
|
|
327
|
+
#
|
|
328
|
+
def method_arity_check(name,args)
|
|
329
|
+
minimum_args, maximum_args = minimum_maximum_args(name)
|
|
330
|
+
|
|
331
|
+
if args.length > maximum_args
|
|
332
|
+
print_error "#{name}: too many arguments given"
|
|
333
|
+
return false
|
|
334
|
+
elsif args.length < minimum_args
|
|
335
|
+
print_error "#{name}: too few arguments given"
|
|
336
|
+
return false
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
return true
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
4
|
+
#
|
|
5
|
+
# ronin-core is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published
|
|
7
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# ronin-core is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require 'ronin/core/git'
|
|
20
|
+
|
|
21
|
+
module Ronin
|
|
22
|
+
module Core
|
|
23
|
+
module CLI
|
|
24
|
+
module Generator
|
|
25
|
+
module Options
|
|
26
|
+
#
|
|
27
|
+
# Adds the `-a,--author NAME` and `-e,--author-email EMAIL` options
|
|
28
|
+
# for the generator command.
|
|
29
|
+
#
|
|
30
|
+
module Author
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# The default author name.
|
|
34
|
+
#
|
|
35
|
+
# @return [String, nil]
|
|
36
|
+
#
|
|
37
|
+
def self.default_name
|
|
38
|
+
Core::Git.user_name || ENV['USERNAME']
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# The default author email.
|
|
43
|
+
#
|
|
44
|
+
# @return [String, nil]
|
|
45
|
+
#
|
|
46
|
+
def self.default_email
|
|
47
|
+
Core::Git.user_email
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# Defines the `-a,--author NAME` and `-e,--author-email EMAIL`
|
|
52
|
+
# options.
|
|
53
|
+
#
|
|
54
|
+
# @param [Class<Comand>] command
|
|
55
|
+
# The command class including {Author}.
|
|
56
|
+
#
|
|
57
|
+
def self.included(command)
|
|
58
|
+
command.option :author, short: '-a',
|
|
59
|
+
value: {
|
|
60
|
+
type: String,
|
|
61
|
+
usage: 'NAME',
|
|
62
|
+
default: ->{ default_name }
|
|
63
|
+
},
|
|
64
|
+
desc: 'The name of the author' do |author|
|
|
65
|
+
@author_name = author
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
command.option :author_email, short: '-e',
|
|
69
|
+
value: {
|
|
70
|
+
type: String,
|
|
71
|
+
usage: 'EMAIL',
|
|
72
|
+
default: ->{ default_email }
|
|
73
|
+
},
|
|
74
|
+
desc: 'The email address of the author' do |email|
|
|
75
|
+
@author_email = email
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The author name.
|
|
80
|
+
#
|
|
81
|
+
# @return [String]
|
|
82
|
+
attr_reader :author_name
|
|
83
|
+
|
|
84
|
+
# The author email.
|
|
85
|
+
#
|
|
86
|
+
# @return [String]
|
|
87
|
+
attr_reader :author_email
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Initializes {#author_name} and {#author_email}.
|
|
91
|
+
#
|
|
92
|
+
# @param [Hash{Symbol => Object}] kwargs
|
|
93
|
+
# Additional keyword arguments.
|
|
94
|
+
#
|
|
95
|
+
def initialize(**kwargs)
|
|
96
|
+
super(**kwargs)
|
|
97
|
+
|
|
98
|
+
@author_name = Author.default_name
|
|
99
|
+
@author_email = Author.default_email
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
4
|
+
#
|
|
5
|
+
# ronin-core is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published
|
|
7
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# ronin-core is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Ronin
|
|
20
|
+
module Core
|
|
21
|
+
module CLI
|
|
22
|
+
module Generator
|
|
23
|
+
module Options
|
|
24
|
+
#
|
|
25
|
+
# Adds the `-D,--description TEXT` option to the generator command.
|
|
26
|
+
#
|
|
27
|
+
module Description
|
|
28
|
+
#
|
|
29
|
+
# Defines the `-D,--description TEXT` option.
|
|
30
|
+
#
|
|
31
|
+
# @param [Class<Comand>] command
|
|
32
|
+
# The command class including {Description}.
|
|
33
|
+
#
|
|
34
|
+
def self.included(command)
|
|
35
|
+
command.option :description, short: '-D',
|
|
36
|
+
value: {
|
|
37
|
+
type: String,
|
|
38
|
+
usage: 'TEXT'
|
|
39
|
+
},
|
|
40
|
+
desc: 'A longer description' do |text|
|
|
41
|
+
@description = text
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# The description text to output.
|
|
46
|
+
#
|
|
47
|
+
# @return [String, nil]
|
|
48
|
+
attr_reader :description
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
4
|
+
#
|
|
5
|
+
# ronin-core is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published
|
|
7
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# ronin-core is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
# along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Ronin
|
|
20
|
+
module Core
|
|
21
|
+
module CLI
|
|
22
|
+
module Generator
|
|
23
|
+
module Options
|
|
24
|
+
#
|
|
25
|
+
# Adds the `-R,--reference URL` option to the generator command.
|
|
26
|
+
#
|
|
27
|
+
module Reference
|
|
28
|
+
def self.included(command)
|
|
29
|
+
command.option :reference, short: '-R',
|
|
30
|
+
value: {
|
|
31
|
+
type: String,
|
|
32
|
+
usage: 'URL'
|
|
33
|
+
},
|
|
34
|
+
desc: 'Adds a reference URL' do |url|
|
|
35
|
+
@references << url
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# The reference URLs to output.
|
|
40
|
+
#
|
|
41
|
+
# @return [Array<String>]
|
|
42
|
+
attr_reader :references
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
# Initializes {#references}.
|
|
46
|
+
#
|
|
47
|
+
# @param [Hash{Symbol => Object}] kwargs
|
|
48
|
+
# Additional keyword arguments.
|
|
49
|
+
#
|
|
50
|
+
def initialize(**kwargs)
|
|
51
|
+
super(**kwargs)
|
|
52
|
+
|
|
53
|
+
@references = []
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|