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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +41 -0
  4. data/.gitignore +12 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +160 -0
  7. data/.ruby-version +1 -0
  8. data/.yardopts +1 -0
  9. data/COPYING.txt +165 -0
  10. data/ChangeLog.md +11 -0
  11. data/Gemfile +30 -0
  12. data/README.md +299 -0
  13. data/Rakefile +34 -0
  14. data/examples/ruby_shell.rb +11 -0
  15. data/gemspec.yml +28 -0
  16. data/lib/ronin/core/class_registry.rb +246 -0
  17. data/lib/ronin/core/cli/command.rb +87 -0
  18. data/lib/ronin/core/cli/command_shell/command.rb +110 -0
  19. data/lib/ronin/core/cli/command_shell.rb +345 -0
  20. data/lib/ronin/core/cli/generator/options/author.rb +106 -0
  21. data/lib/ronin/core/cli/generator/options/description.rb +54 -0
  22. data/lib/ronin/core/cli/generator/options/reference.rb +60 -0
  23. data/lib/ronin/core/cli/generator/options/summary.rb +54 -0
  24. data/lib/ronin/core/cli/generator.rb +238 -0
  25. data/lib/ronin/core/cli/logging.rb +59 -0
  26. data/lib/ronin/core/cli/options/param.rb +68 -0
  27. data/lib/ronin/core/cli/options/values/arches.rb +45 -0
  28. data/lib/ronin/core/cli/options/values/oses.rb +32 -0
  29. data/lib/ronin/core/cli/printing/arch.rb +71 -0
  30. data/lib/ronin/core/cli/printing/metadata.rb +113 -0
  31. data/lib/ronin/core/cli/printing/os.rb +54 -0
  32. data/lib/ronin/core/cli/printing/params.rb +69 -0
  33. data/lib/ronin/core/cli/ruby_shell.rb +131 -0
  34. data/lib/ronin/core/cli/shell.rb +186 -0
  35. data/lib/ronin/core/git.rb +73 -0
  36. data/lib/ronin/core/home.rb +86 -0
  37. data/lib/ronin/core/metadata/authors/author.rb +241 -0
  38. data/lib/ronin/core/metadata/authors.rb +120 -0
  39. data/lib/ronin/core/metadata/description.rb +100 -0
  40. data/lib/ronin/core/metadata/id.rb +88 -0
  41. data/lib/ronin/core/metadata/references.rb +87 -0
  42. data/lib/ronin/core/metadata/summary.rb +78 -0
  43. data/lib/ronin/core/metadata/version.rb +74 -0
  44. data/lib/ronin/core/params/exceptions.rb +38 -0
  45. data/lib/ronin/core/params/mixin.rb +317 -0
  46. data/lib/ronin/core/params/param.rb +137 -0
  47. data/lib/ronin/core/params/types/boolean.rb +64 -0
  48. data/lib/ronin/core/params/types/enum.rb +107 -0
  49. data/lib/ronin/core/params/types/float.rb +68 -0
  50. data/lib/ronin/core/params/types/integer.rb +100 -0
  51. data/lib/ronin/core/params/types/numeric.rb +106 -0
  52. data/lib/ronin/core/params/types/regexp.rb +67 -0
  53. data/lib/ronin/core/params/types/string.rb +118 -0
  54. data/lib/ronin/core/params/types/type.rb +54 -0
  55. data/lib/ronin/core/params/types/uri.rb +72 -0
  56. data/lib/ronin/core/params/types.rb +62 -0
  57. data/lib/ronin/core/params.rb +19 -0
  58. data/lib/ronin/core/version.rb +24 -0
  59. data/ronin-core.gemspec +59 -0
  60. data/spec/class_registry_spec.rb +224 -0
  61. data/spec/cli/command_shell/command_spec.rb +113 -0
  62. data/spec/cli/command_shell_spec.rb +1114 -0
  63. data/spec/cli/command_spec.rb +16 -0
  64. data/spec/cli/fixtures/irb_command +8 -0
  65. data/spec/cli/fixtures/template/dir/file1.txt +1 -0
  66. data/spec/cli/fixtures/template/dir/file2.txt +1 -0
  67. data/spec/cli/fixtures/template/file.erb +1 -0
  68. data/spec/cli/fixtures/template/file.txt +1 -0
  69. data/spec/cli/generator/options/author_spec.rb +121 -0
  70. data/spec/cli/generator/options/description_spec.rb +45 -0
  71. data/spec/cli/generator/options/reference_spec.rb +53 -0
  72. data/spec/cli/generator/options/summary_spec.rb +45 -0
  73. data/spec/cli/generator_spec.rb +244 -0
  74. data/spec/cli/logging_spec.rb +95 -0
  75. data/spec/cli/options/param_spec.rb +67 -0
  76. data/spec/cli/options/values/arches_spec.rb +62 -0
  77. data/spec/cli/printing/arch_spec.rb +130 -0
  78. data/spec/cli/printing/metadata_spec.rb +211 -0
  79. data/spec/cli/printing/os_spec.rb +64 -0
  80. data/spec/cli/printing/params_spec.rb +63 -0
  81. data/spec/cli/ruby_shell.rb +99 -0
  82. data/spec/cli/shell_spec.rb +211 -0
  83. data/spec/fixtures/example_class_registry/base_class.rb +9 -0
  84. data/spec/fixtures/example_class_registry/classes/loaded_class.rb +9 -0
  85. data/spec/fixtures/example_class_registry/classes/name_mismatch.rb +9 -0
  86. data/spec/fixtures/example_class_registry/classes/no_module.rb +4 -0
  87. data/spec/fixtures/example_class_registry.rb +8 -0
  88. data/spec/git_spec.rb +58 -0
  89. data/spec/home_spec.rb +64 -0
  90. data/spec/metadata/authors/author_spec.rb +335 -0
  91. data/spec/metadata/authors_spec.rb +126 -0
  92. data/spec/metadata/description_spec.rb +74 -0
  93. data/spec/metadata/id_spec.rb +92 -0
  94. data/spec/metadata/references_spec.rb +100 -0
  95. data/spec/metadata/summary_spec.rb +74 -0
  96. data/spec/metadata/version_spec.rb +72 -0
  97. data/spec/params/mixin_spec.rb +484 -0
  98. data/spec/params/param_spec.rb +164 -0
  99. data/spec/params/types/boolean_spec.rb +56 -0
  100. data/spec/params/types/enum_spec.rb +94 -0
  101. data/spec/params/types/float_spec.rb +107 -0
  102. data/spec/params/types/integer_spec.rb +155 -0
  103. data/spec/params/types/numeric_spec.rb +138 -0
  104. data/spec/params/types/regexp_spec.rb +64 -0
  105. data/spec/params/types/string_spec.rb +174 -0
  106. data/spec/params/types/type_spec.rb +14 -0
  107. data/spec/params/types/uri_spec.rb +62 -0
  108. data/spec/spec_helper.rb +11 -0
  109. 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