opt_parse_builder 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +35 -0
- data/LICENSE +23 -0
- data/README.md +434 -0
- data/Rakefile +13 -0
- data/examples/hello_world.rb +20 -0
- data/lib/opt_parse_builder.rb +156 -0
- data/lib/opt_parse_builder/argument.rb +62 -0
- data/lib/opt_parse_builder/argument_builder.rb +193 -0
- data/lib/opt_parse_builder/argument_bundle.rb +30 -0
- data/lib/opt_parse_builder/argument_bundle_builder.rb +34 -0
- data/lib/opt_parse_builder/argument_values.rb +60 -0
- data/lib/opt_parse_builder/banner_argument.rb +11 -0
- data/lib/opt_parse_builder/constant_argument.rb +16 -0
- data/lib/opt_parse_builder/errors.rb +10 -0
- data/lib/opt_parse_builder/formats_operand_name.rb +9 -0
- data/lib/opt_parse_builder/has_value.rb +21 -0
- data/lib/opt_parse_builder/null_argument.rb +4 -0
- data/lib/opt_parse_builder/option_argument.rb +33 -0
- data/lib/opt_parse_builder/optional_operand_argument.rb +29 -0
- data/lib/opt_parse_builder/parser.rb +345 -0
- data/lib/opt_parse_builder/parser_builder.rb +17 -0
- data/lib/opt_parse_builder/required_operand_argument.rb +32 -0
- data/lib/opt_parse_builder/separator_argument.rb +11 -0
- data/lib/opt_parse_builder/splat_operand_argument.rb +22 -0
- data/lib/opt_parse_builder/stable_sort.rb +13 -0
- data/lib/opt_parse_builder/version.rb +6 -0
- data/opt_parse_builder.gemspec +35 -0
- data/rake/bundler.rake +1 -0
- data/rake/default.rake +1 -0
- data/rake/rdoc.rake +7 -0
- data/rake/spec.rake +3 -0
- data/rake/test.rake +2 -0
- metadata +126 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
module OptParseBuilder
|
2
|
+
|
3
|
+
# Yielded by OptParseBuilder.bundle_arguments to create an
|
4
|
+
# ArgumentBundle, a collection of arguments that can be treated as
|
5
|
+
# through it is one argument.
|
6
|
+
class ArgumentBundleBuilder
|
7
|
+
|
8
|
+
def initialize # :nodoc:
|
9
|
+
@argument_bundle = ArgumentBundle.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add an argument to the bundle. Takes either the argument to
|
13
|
+
# add, or yields an ArgumentBuilder which builds a new argument
|
14
|
+
# and adds it.
|
15
|
+
#
|
16
|
+
# If adding an existing argument, that argument may itself be an
|
17
|
+
# ArgumentBundle.
|
18
|
+
def add(argument = nil, &block)
|
19
|
+
unless argument.nil? ^ block.nil?
|
20
|
+
raise BuildError, "Need exactly 1 of arg and block"
|
21
|
+
end
|
22
|
+
if argument
|
23
|
+
@argument_bundle << argument
|
24
|
+
else
|
25
|
+
@argument_bundle << OptParseBuilder.build_argument(&block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def argument # :nodoc:
|
30
|
+
@argument_bundle.simplify
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module OptParseBuilder
|
2
|
+
|
3
|
+
# Like OpenStruct, in that it allows access as through either a Hash
|
4
|
+
# or a Struct, but raises an error if you try to read a value that
|
5
|
+
# has not been set.
|
6
|
+
#
|
7
|
+
# Strings and symbols may be interchanged freely for hash access.
|
8
|
+
#
|
9
|
+
# A value may only by set using hash syntax:
|
10
|
+
#
|
11
|
+
# arg_values = ArgumentValues.new
|
12
|
+
# arg_values[:one] = 1
|
13
|
+
# arg_values["two"] = 2
|
14
|
+
#
|
15
|
+
# But may be retrieved using hash syntax:
|
16
|
+
#
|
17
|
+
# arg_values["one"] # => 1
|
18
|
+
# arg_values[:two] # => 2
|
19
|
+
#
|
20
|
+
# or struct syntax:
|
21
|
+
#
|
22
|
+
# arg_values.one # => 1
|
23
|
+
# arg_values.two # => 2
|
24
|
+
class ArgumentValues
|
25
|
+
|
26
|
+
# Create an empty instance.
|
27
|
+
def initialize
|
28
|
+
@h = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return true if the collection is empty.
|
32
|
+
def empty?
|
33
|
+
@h.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return true if the collection contains the key, which may be
|
37
|
+
# either a symbol or a string.
|
38
|
+
def has_key?(key)
|
39
|
+
@h.has_key?(key.to_sym)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set a key to a value. The key may be either a string or a
|
43
|
+
# symbol.
|
44
|
+
def []=(key, value)
|
45
|
+
@h[key.to_sym] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get a value. The key may be either a string or a symbol.
|
49
|
+
# Raises KeyError if the collection does not have that key.
|
50
|
+
def [](key)
|
51
|
+
@h.fetch(key.to_sym)
|
52
|
+
end
|
53
|
+
|
54
|
+
def method_missing(method, *args) # :nodoc:
|
55
|
+
return super unless has_key?(method)
|
56
|
+
self[method]
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module OptParseBuilder
|
2
|
+
class ConstantArgument < Argument # :nodoc:
|
3
|
+
|
4
|
+
attr_reader :key
|
5
|
+
attr_reader :value
|
6
|
+
|
7
|
+
def initialize(key, value)
|
8
|
+
unless key
|
9
|
+
raise BuildError, "default requires a key"
|
10
|
+
end
|
11
|
+
@key = key
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module OptParseBuilder
|
2
|
+
|
3
|
+
# The base class for all exceptions directly raised by this library.
|
4
|
+
class Error < StandardError ; end
|
5
|
+
|
6
|
+
# Exception raised for an error when building a parser, argument or
|
7
|
+
# argument bundle.
|
8
|
+
class BuildError < Error ; end
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module OptParseBuilder
|
2
|
+
module HasValue # :nodoc:
|
3
|
+
|
4
|
+
attr_reader :key
|
5
|
+
attr_accessor :value
|
6
|
+
|
7
|
+
def init_value(key, default)
|
8
|
+
unless key
|
9
|
+
raise BuildError, "argument with value requires a key"
|
10
|
+
end
|
11
|
+
@key = key
|
12
|
+
@default = default
|
13
|
+
reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
@value = @default
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module OptParseBuilder
|
2
|
+
class OptionArgument < Argument # :nodoc:
|
3
|
+
|
4
|
+
include HasValue
|
5
|
+
|
6
|
+
DEFAULT_HANDLER = ->(argument, value) { argument.value = value }
|
7
|
+
|
8
|
+
def initialize(key, default, on, handler)
|
9
|
+
init_value(key, default)
|
10
|
+
@on = on
|
11
|
+
@handler = handler || DEFAULT_HANDLER
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply_option(op)
|
15
|
+
op.on(*edited_on) do |value|
|
16
|
+
@handler.call(self, value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def edited_on
|
23
|
+
@on.map do |s|
|
24
|
+
if s.respond_to?(:gsub!)
|
25
|
+
s.gsub(/_DEFAULT_/, @default.to_s)
|
26
|
+
else
|
27
|
+
s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module OptParseBuilder
|
2
|
+
class OptionalOperandArgument < Argument # :nodoc:
|
3
|
+
|
4
|
+
include FormatsOperandName
|
5
|
+
include HasValue
|
6
|
+
|
7
|
+
def initialize(key, default, help_name)
|
8
|
+
init_value(key, default)
|
9
|
+
@help_name = help_name || key
|
10
|
+
end
|
11
|
+
|
12
|
+
def operand_notation
|
13
|
+
"[<#{format_operand_name(@help_name)}>]"
|
14
|
+
end
|
15
|
+
|
16
|
+
def shift_operand(argv)
|
17
|
+
@value = argv.shift
|
18
|
+
end
|
19
|
+
|
20
|
+
def optional
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def required
|
25
|
+
RequiredOperandArgument.new(@key, @default, @help_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,345 @@
|
|
1
|
+
require "optparse"
|
2
|
+
|
3
|
+
require_relative "stable_sort"
|
4
|
+
|
5
|
+
module OptParseBuilder
|
6
|
+
|
7
|
+
# A command-line parser. Create an instance of this by calling
|
8
|
+
# OptParseBuilder.build_parser.
|
9
|
+
#
|
10
|
+
# Note: The constructor for this class is not part of the public
|
11
|
+
# API.
|
12
|
+
class Parser
|
13
|
+
|
14
|
+
include StableSort
|
15
|
+
|
16
|
+
# Controls whether unparsed arguments are an error.
|
17
|
+
#
|
18
|
+
# If `false` (the default), then unparsed arguments cause an
|
19
|
+
# error:
|
20
|
+
#
|
21
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
22
|
+
# args.allow_unparsed_operands = false
|
23
|
+
# args.add do |arg|
|
24
|
+
# arg.key :quiet
|
25
|
+
# arg.on "-q", "--quiet", "Suppress normal output"
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# ARGV = ["-q", "/tmp/file1", "/tmp/file2"]
|
30
|
+
# arg_values = arg_parser.parse!
|
31
|
+
# # aborts with "needless argument: /tmp/file1"
|
32
|
+
#
|
33
|
+
# If `true`, then unparsed operands are not considered an error, and
|
34
|
+
# they remain unconsumed. Use this setting when you want unparsed
|
35
|
+
# operands to remain in `ARGV` so that they can be used by, for
|
36
|
+
# example, `ARGF`:
|
37
|
+
#
|
38
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
39
|
+
# args.allow_unparsed_operands = true
|
40
|
+
# args.add do |arg|
|
41
|
+
# arg.key :quiet
|
42
|
+
# arg.on "-q", "--quiet", "Suppress normal output"
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# ARGV = ["-q", "/tmp/file1", "/tmp/file2"]
|
47
|
+
# arg_values = arg_parser.parse!
|
48
|
+
# # ARGV now equals ["/tmp/file1", "/tmp/file2"]
|
49
|
+
# ARGF.each_line do |line|
|
50
|
+
# puts line unless arg_values.quiet
|
51
|
+
# end
|
52
|
+
attr_accessor :allow_unparsed_operands
|
53
|
+
|
54
|
+
def initialize # :nodoc:
|
55
|
+
@arguments = []
|
56
|
+
@allow_unparsed_operands = false
|
57
|
+
end
|
58
|
+
|
59
|
+
# Reset to the state after construction, before #parse! was called.
|
60
|
+
# Each argument is set to its default value. An argument with no
|
61
|
+
# explicit default is set to `nil`.
|
62
|
+
#
|
63
|
+
# This is called implicitly when you call #parse!, so there's seldom
|
64
|
+
# any need for it to be called explicitly.
|
65
|
+
def reset
|
66
|
+
@arguments.each(&:reset)
|
67
|
+
sort_arguments
|
68
|
+
end
|
69
|
+
|
70
|
+
# Parse arguments, consuming them from the array.
|
71
|
+
#
|
72
|
+
# After parsing, there are numerous ways to access the value of the arguments:
|
73
|
+
#
|
74
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
75
|
+
# args.add do |arg|
|
76
|
+
# arg.key :num
|
77
|
+
# arg.on "--num=N", Integer, "A number"
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
# arg_values = arg_parser.parse!(["--num=123"])
|
81
|
+
# p arg_parser[:num] # => 123
|
82
|
+
# p arg_parser["num"] # => 123
|
83
|
+
# p arg_values[:num] # => 123
|
84
|
+
# p arg_values["num"] # => 123
|
85
|
+
# p arg_values.num # => 123
|
86
|
+
#
|
87
|
+
# If there are operands (positional arguments) in the array that are
|
88
|
+
# not consumed, an error normally results. This behavior can be
|
89
|
+
# changed using #allow_unparsed_operands.
|
90
|
+
#
|
91
|
+
# The #parse! method defaults to parsing `ARGV`, which is what is
|
92
|
+
# usually wanted, but you can pass in any array of strings, as the
|
93
|
+
# above example does.
|
94
|
+
#
|
95
|
+
# Design note: A method that modifies its argument _and_ modifies
|
96
|
+
# its object _and_ returns a value is not the best design, violating
|
97
|
+
# the good principle of command-query separation. However, that
|
98
|
+
# violation is more useful in this case than it is sinful, and it's
|
99
|
+
# the only place in this library that violates that principle.
|
100
|
+
def parse!(argv = ARGV)
|
101
|
+
reset
|
102
|
+
begin
|
103
|
+
op = optparse
|
104
|
+
op.parse!(argv)
|
105
|
+
@arguments.each do |arg|
|
106
|
+
arg.shift_operand(argv)
|
107
|
+
end
|
108
|
+
unless @allow_unparsed_operands || argv.empty?
|
109
|
+
raise OptionParser::NeedlessArgument, argv.first
|
110
|
+
end
|
111
|
+
values
|
112
|
+
rescue OptionParser::ParseError => e
|
113
|
+
abort e.message
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Add a line to the banner. The banner is text that appears at the
|
118
|
+
# top of the help text.
|
119
|
+
#
|
120
|
+
# A new-line will automatically be added to the end of the line.
|
121
|
+
# Although it's called a "line," you can embed new-lines in it so
|
122
|
+
# that it is actually more than one line.
|
123
|
+
#
|
124
|
+
# This example:
|
125
|
+
#
|
126
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
127
|
+
# args.banner "This is my program"
|
128
|
+
# args.banner <<~BANNER
|
129
|
+
# There are many programs like it,
|
130
|
+
# but this program is mine.
|
131
|
+
# BANNER
|
132
|
+
# end
|
133
|
+
# arg_parser.parse!(["--help"])
|
134
|
+
#
|
135
|
+
# Results in `--help` output like this:
|
136
|
+
#
|
137
|
+
# This is my program
|
138
|
+
# There are many programs like it,
|
139
|
+
# but this program is mine.
|
140
|
+
# Usage: example [options] <path>
|
141
|
+
def banner(line)
|
142
|
+
add do |arg|
|
143
|
+
arg.banner(line)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Add a line to the separator. The separator is text that appears
|
148
|
+
# at the bottom of the help text.
|
149
|
+
#
|
150
|
+
# A new-line will automatically be added to the end of the line.
|
151
|
+
# Although it's called a "line," you can embed new-lines in it so
|
152
|
+
# that it is actually more than one line.
|
153
|
+
#
|
154
|
+
# This example:
|
155
|
+
#
|
156
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
157
|
+
# args.separator "Here I explain more about my program"
|
158
|
+
# args.separator <<~SEPARATOR
|
159
|
+
# For such a small program,
|
160
|
+
# it has a lot of text at the end.
|
161
|
+
# SEPARATOR
|
162
|
+
# end
|
163
|
+
# arg_parser.parse!(["--help"])
|
164
|
+
#
|
165
|
+
# Results in `--help` output like this:
|
166
|
+
#
|
167
|
+
# Usage: example [options] <path>
|
168
|
+
# Here I explain more about my program
|
169
|
+
# For such a small program,
|
170
|
+
# it has a lot of text at the end.
|
171
|
+
def separator(line)
|
172
|
+
add do |arg|
|
173
|
+
arg.separator(line)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Add an argument. Must be passed either the argument to add, or
|
178
|
+
# given a block. If given a block, yields an ArgumentBuilder.
|
179
|
+
#
|
180
|
+
# Example using a pre-built argument:
|
181
|
+
#
|
182
|
+
# DRY_RUN = OptParseBuilder.build_argument do |arg|
|
183
|
+
# arg.key :dry_run
|
184
|
+
# arg.on "-d", "--dry-run", "Make no changes"
|
185
|
+
# end
|
186
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
187
|
+
# args.add DRY_RUN
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
# Example using a block to build the argument in-place:
|
191
|
+
#
|
192
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
193
|
+
# args.add do |arg|
|
194
|
+
# arg.key :dry_run
|
195
|
+
# arg.on "-d", "--dry-run", "Make no changes"
|
196
|
+
# end
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# This is equivalent to:
|
200
|
+
#
|
201
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
202
|
+
# args.add OptParseBuilder.build_argument do |arg|
|
203
|
+
# arg.key :dry_run
|
204
|
+
# arg.on "-d", "--dry-run", "Make no changes"
|
205
|
+
# end
|
206
|
+
# end
|
207
|
+
#
|
208
|
+
# See the README for details of the different options available
|
209
|
+
# for an argument.
|
210
|
+
#
|
211
|
+
# Raises BuildError if the argument cannot be built or added.
|
212
|
+
def add(argument = nil, &block)
|
213
|
+
unless argument.nil? ^ block.nil?
|
214
|
+
raise BuildError, "Need exactly 1 of arg and block"
|
215
|
+
end
|
216
|
+
if argument
|
217
|
+
add_argument(argument)
|
218
|
+
else
|
219
|
+
add_argument(OptParseBuilder.build_argument(&block))
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Returns the value of an argument, given either a symbol or a
|
224
|
+
# string with its name. If the key does not exist, raises KeyError.
|
225
|
+
#
|
226
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
227
|
+
# args.add do |arg|
|
228
|
+
# arg.key :x
|
229
|
+
# arg.default 123
|
230
|
+
# end
|
231
|
+
# end
|
232
|
+
# arg_parser[:x] # => 123
|
233
|
+
# arg_parser["x"] # => 123
|
234
|
+
# arg_parser[:y] # KeyError (key not found :y)
|
235
|
+
#
|
236
|
+
# See also:
|
237
|
+
#
|
238
|
+
# * method #values - returns a collection of all argument values
|
239
|
+
# * method #has_key? - find out if the parser knows about a key
|
240
|
+
def [](key)
|
241
|
+
find_argument!(key).value
|
242
|
+
end
|
243
|
+
|
244
|
+
# Return a collection with all of the argument values. The
|
245
|
+
# collection can be accessed in several ways:
|
246
|
+
#
|
247
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
248
|
+
# args.add do |arg|
|
249
|
+
# arg.key :num
|
250
|
+
# arg.on "--num=N", Integer, "A number"
|
251
|
+
# end
|
252
|
+
# end
|
253
|
+
# arg_parser.parse!(["--num=123"])
|
254
|
+
# arg_values = arg_parser.values
|
255
|
+
# p arg_values[:num] # => 123
|
256
|
+
# p arg_values["num"] # => 123
|
257
|
+
# p arg_values.num # => 123
|
258
|
+
def values
|
259
|
+
av = ArgumentValues.new
|
260
|
+
@arguments.each do |arg|
|
261
|
+
av[arg.key] = arg.value if arg.key
|
262
|
+
end
|
263
|
+
av
|
264
|
+
end
|
265
|
+
|
266
|
+
# Return true if the parser has the named key, which may be either a
|
267
|
+
# string or a symbol.
|
268
|
+
#
|
269
|
+
# arg_parser = OptParseBuilder.build_parser do |args|
|
270
|
+
# args.add do |arg|
|
271
|
+
# arg.key :quiet
|
272
|
+
# end
|
273
|
+
# end
|
274
|
+
# arg_parser.has_key?(:quiet) # => true
|
275
|
+
# arg_parser.has_key?("quiet") # => true
|
276
|
+
# arg_parser.has_key?(:verbose) # => false
|
277
|
+
def has_key?(key)
|
278
|
+
!!find_argument(key)
|
279
|
+
end
|
280
|
+
|
281
|
+
private
|
282
|
+
|
283
|
+
def sort_arguments
|
284
|
+
stable_sort_by!(@arguments) do |arg|
|
285
|
+
case arg
|
286
|
+
when RequiredOperandArgument
|
287
|
+
1
|
288
|
+
when OptionalOperandArgument
|
289
|
+
2
|
290
|
+
when SplatOperandArgument
|
291
|
+
3
|
292
|
+
else
|
293
|
+
0
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def find_argument!(key)
|
299
|
+
argument = find_argument(key)
|
300
|
+
unless argument
|
301
|
+
raise Key, "key not found #{key.inspect}"
|
302
|
+
end
|
303
|
+
argument
|
304
|
+
end
|
305
|
+
|
306
|
+
def find_argument(key)
|
307
|
+
key = key.to_sym
|
308
|
+
@arguments.find do |arg|
|
309
|
+
arg.key == key
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def optparse
|
314
|
+
op = OptParse.new
|
315
|
+
op.banner = banner_prefix + op.banner + banner_suffix
|
316
|
+
@arguments.each { |arg| arg.apply_option(op) }
|
317
|
+
@arguments.each do |argument|
|
318
|
+
argument.separator_lines.each do |line|
|
319
|
+
op.separator(line)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
op
|
323
|
+
end
|
324
|
+
|
325
|
+
def add_argument(argument)
|
326
|
+
if argument.key && has_key?(argument.key)
|
327
|
+
raise BuildError, "duplicate key #{argument.key}"
|
328
|
+
end
|
329
|
+
@arguments.concat(argument.to_a.map(&:dup))
|
330
|
+
end
|
331
|
+
|
332
|
+
def banner_prefix
|
333
|
+
@arguments.flat_map(&:banner_lines).map do |line|
|
334
|
+
line + "\n"
|
335
|
+
end.join
|
336
|
+
end
|
337
|
+
|
338
|
+
def banner_suffix
|
339
|
+
suffix = @arguments.map(&:operand_notation).compact.join(" ")
|
340
|
+
suffix = " " + suffix unless suffix.empty?
|
341
|
+
suffix
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
end
|