shellopts 2.0.0.pre.13 → 2.0.0.pre.14
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/TODO +15 -135
- data/lib/ext/algorithm.rb +14 -0
- data/lib/ext/ruby_env.rb +8 -0
- data/lib/shellopts.rb +90 -228
- data/lib/shellopts/args.rb +1 -1
- data/lib/shellopts/ast/command.rb +101 -30
- data/lib/shellopts/ast/dump.rb +28 -0
- data/lib/shellopts/ast/option.rb +8 -14
- data/lib/shellopts/ast/parser.rb +106 -0
- data/lib/shellopts/constants.rb +88 -0
- data/lib/shellopts/exceptions.rb +21 -0
- data/lib/shellopts/formatter.rb +125 -0
- data/lib/shellopts/grammar/analyzer.rb +76 -0
- data/lib/shellopts/grammar/command.rb +67 -60
- data/lib/shellopts/grammar/dump.rb +56 -0
- data/lib/shellopts/grammar/lexer.rb +56 -0
- data/lib/shellopts/grammar/option.rb +49 -60
- data/lib/shellopts/grammar/parser.rb +78 -0
- data/lib/shellopts/version.rb +2 -2
- data/shellopts.gemspec +1 -1
- metadata +13 -15
- data/lib/ext/array.rb +0 -9
- data/lib/main.rb +0 -1
- data/lib/shellopts/ast/node.rb +0 -37
- data/lib/shellopts/ast/program.rb +0 -14
- data/lib/shellopts/compiler.rb +0 -128
- data/lib/shellopts/generator.rb +0 -15
- data/lib/shellopts/grammar/node.rb +0 -33
- data/lib/shellopts/grammar/program.rb +0 -65
- data/lib/shellopts/idr.rb +0 -236
- data/lib/shellopts/main.rb +0 -10
- data/lib/shellopts/option_struct.rb +0 -148
- data/lib/shellopts/parser.rb +0 -106
- data/lib/shellopts/shellopts.rb +0 -123
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1e9e2f138c476cb6af3184dd5e43f8a0f82108d05e4170491c5c46dfb547627
|
4
|
+
data.tar.gz: 9990bee10ffe5c6c5db537a416f366ed70c4577a8a3a07658281d9485225d438
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a57589ccaf3b2f516727cd6e7b066044d13a49d2c5280a478de162e42574e1eca03c2b013133d9b0ce50b4ac037fef15d12a01f5893b32ec6132d03c121e08f
|
7
|
+
data.tar.gz: bc338066a99d6470bd434d26cf994159ec926c4eb7f3a7d1d8b358303d5850bcdf058b56447ebf6c581bb2295de2d5f57f5637db5ab82fbd47ba618b8988afe6
|
data/TODO
CHANGED
@@ -1,136 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
o subcommand vs. command consistency
|
17
|
-
o Implement ObjectStruct#key! and ObjectStruct#value! (?)
|
18
|
-
o Allow command_alias == nil to suppress the method
|
19
|
-
o Raise on non-existing names/keys. Only return nil for declared names/keys that are not present
|
20
|
-
o Use hash_tree
|
21
|
-
o Also allow assignment to usage string for ShellOpts::ShellOpts objects
|
22
|
-
o Create a ShellOpts.args method? It would be useful when processing commands:
|
23
|
-
case opt
|
24
|
-
when "command"
|
25
|
-
call_command_method(ShellOpts.args[1], ShellOpts.args[2])
|
26
|
-
end
|
27
|
-
ShellOpts.args would be a shorthand for ShellOpts.shellopts.args
|
28
|
-
Another option would be to create an argument-processing method:
|
29
|
-
shellopts.argv(2) -> call error if not exactly two arguments else return elements
|
30
|
-
o Add a ShellOpts.option method:
|
31
|
-
file = ShellOpts.option("--file")
|
32
|
-
This will only work for options on the outermost level... maybe:
|
33
|
-
file = ShellOpts.option("load! --file")
|
34
|
-
o Check on return value from #process block to see if all options was handled:
|
35
|
-
case opt
|
36
|
-
when '-v'; verbose = true # Return value 'true' is ok
|
37
|
-
# Unhandled option means return value is nil
|
38
|
-
end
|
39
|
-
o Consolidate some of the 3 variations of #error and #fail
|
40
|
-
o Add a option flag for solitary options (--help)
|
41
|
-
o Make a #to_yaml
|
42
|
-
o Make an official dump method for debug
|
43
|
-
o Make a note that all options are processed at once and not as-you-go
|
44
|
-
o Test that arguments with spaces work
|
45
|
-
o Long version usage strings (major release)
|
46
|
-
o Doc: Example of processing of sub-commands and sub-sub-commands
|
47
|
-
|
48
|
-
+ Add a 'mandatory' argument to #subcommand
|
49
|
-
+ More tests
|
50
|
-
+ More doc
|
51
|
-
+ Implement value-name-before-flags rule
|
52
|
-
+ Kill option array values
|
53
|
-
+ Kill key forms
|
54
|
-
+ Rename Option#opt to Option#name
|
55
|
-
+ Have all Ast objects to be on [key, name, value] form
|
56
|
-
+ Change #=>i, $=>f and introduce b (boolean)
|
57
|
-
+ Unshift program name to usage definition string before compiling
|
58
|
-
+ Rename to UsageCompiler and ArgvParser
|
59
|
-
+ Make usage-string handle commands
|
60
|
-
+ Change !cmd to cmd!
|
61
|
-
+ Clean-up terminology: Option-name is used for names with and without the prefixed dashes
|
62
|
-
+ Rename Option#has_argument? and #optional? to something else
|
63
|
-
+ Fix location reporting of compiler errors
|
64
|
-
+ Allow '--' in usage so that everything after can be used as USAGE in error messages
|
65
|
-
+ Handle pretty-printing of usage string in handling of ParserError
|
66
|
-
+ Compiler.new.compile(usage), Parser.new(compiled_program).parse(argv)
|
67
|
-
+ Check for duplicate option in the parser
|
68
|
-
+ Handle CompilerError
|
69
|
-
+ Use nil value as the name of the top 'command'
|
70
|
-
+ Refactor compilation to avoid having the Command objects throw CompilerErrors
|
71
|
-
+ Change to 'parser.parse' / 'parser.parse3'
|
72
|
-
+ Use first long option as symbolic key
|
73
|
-
+ Use full option names everywhere (eg. '--all' instead of 'all')
|
74
|
-
|
75
|
-
- Revert change from '#' -> 'i'
|
76
|
-
- Guard against reserved 'object_id' name in OpenStruct
|
77
|
-
- Default value ('=' -> ':')
|
78
|
-
Default values are better handled in the calling program
|
79
|
-
|
80
|
-
? More specialized exceptions: "MissingArgumentError" etc.
|
81
|
-
|
82
|
-
LATER
|
83
|
-
o Allow '-a' and '--aa' in usage
|
84
|
-
o Allow single-line comments
|
85
|
-
o Allow multi-line comments
|
86
|
-
o Regex as option value spec
|
87
|
-
o "FILE", "DIR", "NEWFILE", "NEWDIR" as keyword in option value spec
|
88
|
-
RFILE, RDIR
|
89
|
-
WFILE, WDIR
|
90
|
-
EFILE, EDIR
|
91
|
-
o Octal and hexadecimal integers
|
92
|
-
o Escape of separator in lists
|
93
|
-
o Handle output of subcommand usage like "cmd1 cmd1.cmd2 cmd2"
|
94
|
-
o Command-specific arguments: clone! o,opt ++ ARG1 ARG2...
|
95
|
-
o Hostname and email as basic types
|
96
|
-
|
97
|
-
ON TO_H BRANCH
|
98
|
-
ShellOpts.process(usage, argv) { |opt,val| ... } => args
|
99
|
-
ShellOpts.process(usage, argv) { |key,opt,val| ... } => args
|
100
|
-
|
101
|
-
opts = ShellOpts.new(usage, argv, defaults = {})
|
102
|
-
opts = ShellOpts.new(usage, argv, defaults = OpenStruct.new)
|
103
|
-
|
104
|
-
opts.args
|
105
|
-
opts.to_a
|
106
|
-
opts.to_h
|
107
|
-
opts.to_openstruct
|
108
|
-
|
109
|
-
opts.each { |opt,val| ... }
|
110
|
-
opts.each { |key,opt,val| ... }
|
111
|
-
|
112
|
-
LONG FORMAT
|
113
|
-
|
114
|
-
PROGRAM = File.basename(ARGV.first)
|
115
|
-
USAGE = "-a -f FILE -lvh FILE..."
|
116
|
-
DESCR = %(
|
117
|
-
Short description
|
118
|
-
|
119
|
-
Longer description
|
120
|
-
)
|
121
|
-
OPTIONS = %(
|
122
|
-
-a,--all
|
123
|
-
Process all files
|
124
|
-
|
125
|
-
-f, --file=FILE
|
126
|
-
Process file
|
127
|
-
|
128
|
-
!command
|
129
|
-
This is a command
|
130
|
-
|
131
|
-
--this-is-a-command-option
|
132
|
-
Options for commands are nested
|
133
|
-
|
134
|
-
...
|
135
|
-
)
|
1
|
+
o Somehow escape comments where a line starts with an option name
|
2
|
+
o 'help' should list commands in declaration order
|
3
|
+
o 'help' should use all levels by default
|
4
|
+
o 'help' should always include top-level options (try setting levels: 10 and
|
5
|
+
see top-level options are gone
|
6
|
+
o Special handling of --help arguments so that '--help command' is possible
|
7
|
+
o Support for paging of help:
|
8
|
+
begin
|
9
|
+
file = Tempfile.new("prick")
|
10
|
+
file.puts HELP.split("\n").map { |l| l.sub(/^ /, "") }
|
11
|
+
file.flush
|
12
|
+
system "less #{file.path}"
|
13
|
+
ensure
|
14
|
+
file.close
|
15
|
+
end
|
136
16
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
module Algorithm
|
3
|
+
def follow(object, sym = nil, &block)
|
4
|
+
sym.nil? == block_given? or raise "Can't use both symbol and block"
|
5
|
+
a = []
|
6
|
+
while object
|
7
|
+
a << object
|
8
|
+
object = block_given? ? yield(object) : object.send(sym)
|
9
|
+
end
|
10
|
+
a
|
11
|
+
end
|
12
|
+
|
13
|
+
module_function :follow
|
14
|
+
end
|
data/lib/ext/ruby_env.rb
ADDED
data/lib/shellopts.rb
CHANGED
@@ -1,257 +1,119 @@
|
|
1
1
|
require "shellopts/version"
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require 'shellopts/generator.rb'
|
6
|
-
require 'shellopts/option_struct.rb'
|
7
|
-
require 'shellopts/main.rb'
|
3
|
+
require "ext/algorithm.rb"
|
4
|
+
require "ext/ruby_env.rb"
|
8
5
|
|
9
|
-
|
10
|
-
|
6
|
+
require "shellopts/constants.rb"
|
7
|
+
require "shellopts/exceptions.rb"
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# object of many of its methods. This matches the typical use case where only
|
18
|
-
# one command line is ever processed and makes it possible to create class
|
19
|
-
# methods that knows about the command like #error and #fail
|
20
|
-
#
|
21
|
-
# For example; the following process and convert a command line into a struct
|
22
|
-
# representation and also sets ShellOpts.shellopts object so that the #error
|
23
|
-
# method can print a relevant spec string:
|
24
|
-
#
|
25
|
-
# USAGE = "a,all f,file=FILE -- ARG1 ARG2"
|
26
|
-
# opts, args = ShellOpts.as_struct(USAGE, ARGV)
|
27
|
-
# File.exist?(opts.file) or error "Can't find #{opts.file}"
|
28
|
-
#
|
29
|
-
# The command line is processed through one of the methods #process, #as_array,
|
30
|
-
# #as_hash, or #as_struct that returns a [data, args] tuple. The data type
|
31
|
-
# depends on the method: #process yields a Idr object that internally serves as
|
32
|
-
# the base for the #as_array and #as_hash and #as_struct that converts it into
|
33
|
-
# an Array, Hash, or ShellOpts::OptionStruct object. For example:
|
34
|
-
#
|
35
|
-
# USAGE = "..."
|
36
|
-
# ShellOpts.process(USAGE, ARGV)
|
37
|
-
# program, args = ShellOpts.as_program(USAGE, ARGV)
|
38
|
-
# array, args = ShellOpts.as_array(USAGE, ARGV)
|
39
|
-
# hash, args = ShellOpts.as_hash(USAGE, ARGV)
|
40
|
-
# struct, args = ShellOpts.as_struct(USAGE, ARGV)
|
41
|
-
#
|
42
|
-
# +args+ is a ShellOpts::Argv object containing the the remaning command line
|
43
|
-
# arguments. Argv is derived from Array
|
44
|
-
#
|
45
|
-
# ShellOpts can raise the exception CompilerError is there is an error in the
|
46
|
-
# USAGE string. If there is an error in the user supplied command line, #error
|
47
|
-
# is called instead and the program terminates with exit code 1. ShellOpts
|
48
|
-
# raises ConversionError is there is a name collision when converting to the
|
49
|
-
# hash or struct representations. Note that CompilerError and ConversionError
|
50
|
-
# are caused by misuse of the library and the problem should be corrected by
|
51
|
-
# the developer
|
52
|
-
#
|
53
|
-
# ShellOpts injects the constant PROGRAM into the global scope. It contains the
|
54
|
-
# name of the program
|
55
|
-
#
|
56
|
-
# INCLUDING SHELLOPTS
|
57
|
-
#
|
58
|
-
# ShellOpts can optionally be included in your shell application main file but
|
59
|
-
# it is not supposed to be included anywhere else
|
60
|
-
#
|
61
|
-
# Some behind the scenes magic happen if you include the ShellOpts module in your
|
62
|
-
# main exe file
|
63
|
-
#
|
64
|
-
module ShellOpts
|
65
|
-
def self.default_name()
|
66
|
-
@default_name || defined?(PROGRAM) ? PROGRAM : File.basename($0)
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.default_name=(name)
|
70
|
-
@default_name = name
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.default_usage()
|
74
|
-
@default_usage || defined?(USAGE) ? USAGE : nil
|
75
|
-
end
|
9
|
+
require "shellopts/grammar/analyzer.rb"
|
10
|
+
require "shellopts/grammar/lexer.rb"
|
11
|
+
require "shellopts/grammar/parser.rb"
|
12
|
+
require "shellopts/grammar/command.rb"
|
13
|
+
require "shellopts/grammar/option.rb"
|
76
14
|
|
77
|
-
|
78
|
-
|
79
|
-
|
15
|
+
require "shellopts/ast/parser.rb"
|
16
|
+
require "shellopts/ast/command.rb"
|
17
|
+
require "shellopts/ast/option.rb"
|
80
18
|
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
def self.default_key_type=(type)
|
86
|
-
@default_key_type = type
|
87
|
-
end
|
19
|
+
require "shellopts/args.rb"
|
20
|
+
require "shellopts/formatter.rb"
|
88
21
|
|
89
|
-
|
90
|
-
|
91
|
-
|
22
|
+
if RUBY_ENV == "development"
|
23
|
+
require "shellopts/grammar/dump.rb"
|
24
|
+
require "shellopts/ast/dump.rb"
|
25
|
+
end
|
92
26
|
|
93
|
-
|
94
|
-
|
27
|
+
$verb = nil
|
28
|
+
$quiet = nil
|
29
|
+
$shellopts = nil
|
95
30
|
|
96
|
-
|
97
|
-
class
|
98
|
-
|
99
|
-
|
100
|
-
|
31
|
+
module ShellOpts
|
32
|
+
class ShellOpts
|
33
|
+
attr_reader :name # Name of program. Defaults to the name of the executable
|
34
|
+
attr_reader :spec
|
35
|
+
attr_reader :argv
|
36
|
+
|
37
|
+
attr_reader :grammar
|
38
|
+
attr_reader :program
|
39
|
+
attr_reader :arguments
|
40
|
+
|
41
|
+
def initialize(spec, argv, name: nil)
|
42
|
+
@name = name || File.basename($PROGRAM_NAME)
|
43
|
+
@spec, @argv = spec, argv.dup
|
44
|
+
exprs = Grammar::Lexer.lex(@spec)
|
45
|
+
commands = Grammar::Parser.parse(@name, exprs)
|
46
|
+
@grammar = Grammar::Analyzer.analyze(commands)
|
47
|
+
|
48
|
+
begin
|
49
|
+
@program, @arguments = Ast::Parser.parse(@grammar, @argv)
|
50
|
+
rescue Error => ex
|
51
|
+
error(ex.subject, ex.message)
|
52
|
+
end
|
101
53
|
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Raised when an error is detected in the command line
|
105
|
-
class ParserError < Error; end
|
106
|
-
|
107
|
-
# Raised when the command line error is caused by the user. It is raised by
|
108
|
-
# the parser but can also be used by the application if the command line
|
109
|
-
# fails a semantic check
|
110
|
-
class UserError < ParserError; end
|
111
|
-
|
112
|
-
# Raised when the error is caused by a failed assumption about the system. It
|
113
|
-
# is not raised by the ShellOpts library as it only concerns itself with
|
114
|
-
# command line syntax but can be used by the application to report a failure
|
115
|
-
# through ShellOpts#fail method when the ShellOpts module is included
|
116
|
-
class SystemFail < Error; end
|
117
|
-
|
118
|
-
# Raised when an error is detected during conversion from the Idr to array,
|
119
|
-
# hash, or struct
|
120
|
-
class ConversionError < Error; end
|
121
|
-
|
122
|
-
# Raised when an internal error is detected
|
123
|
-
class InternalError < Error; end
|
124
|
-
|
125
|
-
# The current compilation object. It is set by #process
|
126
|
-
def self.shellopts() @shellopts end
|
127
54
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
def usage() shellopts!.spec end
|
134
|
-
def usage=(spec) shellopts!.spec = spec end
|
135
|
-
|
136
|
-
# Process command line, set current shellopts object, and return it.
|
137
|
-
# Remaining arguments from the command line can be accessed through
|
138
|
-
# +shellopts.args+
|
139
|
-
def self.process(spec, argv, name: ::ShellOpts.default_name, usage: ::ShellOpts.default_usage)
|
140
|
-
@shellopts.nil? or reset
|
141
|
-
@shellopts = ShellOpts.new(spec, argv, name: name, usage: usage)
|
142
|
-
@shellopts.process
|
143
|
-
end
|
55
|
+
def error(subject = nil, message)
|
56
|
+
$stderr.puts "#{name}: #{message}"
|
57
|
+
usage(subject, device: $stderr)
|
58
|
+
exit 1
|
59
|
+
end
|
144
60
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
Main.main.send(:include, ::ShellOpts) if caller.last =~ Main::CALLER_RE
|
150
|
-
process(spec, argv, name: name, usage: usage)
|
151
|
-
@opts = shellopts.idr
|
152
|
-
@args = shellopts.args
|
153
|
-
[@opts, @args]
|
154
|
-
end
|
61
|
+
def fail(message)
|
62
|
+
$stderr.puts "#{name}: #{message}"
|
63
|
+
exit 1
|
64
|
+
end
|
155
65
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
Main.main.send(:include, ::ShellOpts) if caller.last =~ Main::CALLER_RE
|
161
|
-
process(spec, argv, name: name, usage: usage)
|
162
|
-
@opts = shellopts.to_a
|
163
|
-
@args = shellopts.args
|
164
|
-
[@opts, @args]
|
165
|
-
end
|
66
|
+
def usage(subject = nil, device: $stdout, levels: 1, margin: "")
|
67
|
+
subject = find_subject(subject)
|
68
|
+
device.puts Formatter.usage_string(subject, levels: levels, margin: margin)
|
69
|
+
end
|
166
70
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
spec, argv,
|
172
|
-
name: ::ShellOpts.default_name, usage: ::ShellOpts.default_usage,
|
173
|
-
key_type: ::ShellOpts.default_key_type,
|
174
|
-
aliases: {})
|
175
|
-
Main.main.send(:include, ::ShellOpts) if caller.last =~ Main::CALLER_RE
|
176
|
-
process(spec, argv, name: name, usage: usage)
|
177
|
-
@opts = shellopts.to_h(key_type: key_type, aliases: aliases)
|
178
|
-
@args = shellopts.args
|
179
|
-
[@opts, @args]
|
180
|
-
end
|
71
|
+
def help(subject = nil, device: $stdout, levels: 10, margin: "", tab: " ")
|
72
|
+
subject = find_subject(subject)
|
73
|
+
device.puts Formatter.help_string(subject, levels: levels, margin: margin, tab: tab)
|
74
|
+
end
|
181
75
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
@opts = shellopts.to_struct(aliases: aliases)
|
192
|
-
@args = shellopts.args
|
193
|
-
[@opts, @args]
|
194
|
-
end
|
76
|
+
private
|
77
|
+
def lookup(name)
|
78
|
+
a = name.split(".")
|
79
|
+
cmd = grammar
|
80
|
+
while element = a.shift
|
81
|
+
cmd = cmd.commands[element]
|
82
|
+
end
|
83
|
+
cmd
|
84
|
+
end
|
195
85
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
shellopts.each(&block)
|
86
|
+
def find_subject(obj)
|
87
|
+
case obj
|
88
|
+
when String; lookup(obj)
|
89
|
+
when Ast::Command; Command.grammar(obj)
|
90
|
+
when Grammar::Command; obj
|
91
|
+
when NilClass; grammar
|
92
|
+
else
|
93
|
+
raise Internal, "Illegal object: #{obj.class}"
|
94
|
+
end
|
95
|
+
end
|
207
96
|
end
|
208
97
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
def self.error(*msgs, exit: true)
|
213
|
-
shellopts!.error(msgs, exit: exit)
|
98
|
+
def self.process(spec, argv, name: nil)
|
99
|
+
$shellopts = ShellOpts.new(spec, argv, name: name)
|
100
|
+
[$shellopts.program, $shellopts.arguments]
|
214
101
|
end
|
215
102
|
|
216
|
-
|
217
|
-
|
218
|
-
def self.fail(*msgs, exit: true)
|
219
|
-
shellopts!.fail(*msgs, exit: exit)
|
103
|
+
def self.error(subject = nil, message)
|
104
|
+
$shellopts.error(subject, message)
|
220
105
|
end
|
221
106
|
|
222
|
-
def self.
|
223
|
-
|
224
|
-
if !@is_included_in_main && base.equal?(Object)
|
225
|
-
@is_included_in_main = true
|
226
|
-
at_exit do
|
227
|
-
case $!
|
228
|
-
when ShellOpts::UserError
|
229
|
-
::ShellOpts.error($!.message, exit: false)
|
230
|
-
exit!(1)
|
231
|
-
when ShellOpts::SystemFail
|
232
|
-
::ShellOpts.fail($!.message)
|
233
|
-
exit!(1)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
super
|
107
|
+
def self.fail(message)
|
108
|
+
$shellopts.fail(message)
|
238
109
|
end
|
239
110
|
|
240
|
-
|
241
|
-
|
242
|
-
DEFAULT_KEY_TYPE = :name
|
243
|
-
|
244
|
-
# Reset state variables
|
245
|
-
def self.reset()
|
246
|
-
@shellopts = nil
|
111
|
+
def self.help(subject = nil, device: $stdout, levels: 10, margin: "", tab: " ")
|
112
|
+
$shellopts.help(subject, device: device, levels: levels, margin: margin, tab: tab)
|
247
113
|
end
|
248
114
|
|
249
|
-
|
250
|
-
|
251
|
-
::ShellOpts.shellopts or raise UserError, "No ShellOpts.shellopts object"
|
115
|
+
def self.usage(subject = nil, device: $stdout, levels: 1, margin: "")
|
116
|
+
$shellopts.usage(subject, device: device, levels: levels, margin: margin)
|
252
117
|
end
|
253
|
-
|
254
|
-
@shellopts = nil
|
255
|
-
@is_included_in_main = false
|
256
118
|
end
|
257
119
|
|