Class: ShellOpts::ShellOpts
- Inherits:
-
Object
- Object
- ShellOpts::ShellOpts
- Defined in:
- lib/shellopts.rb
Instance Attribute Summary collapse
-
#args ⇒ Object
readonly
Array of remaining arguments.
-
#argv ⇒ Object
readonly
Array of arguments.
-
#debug ⇒ Object
readonly
Automatically add a --debug option if true.
-
#exception ⇒ Object
Use exceptions instead of ShellOpts's error methods.
-
#file ⇒ Object
readonly
Executable.
-
#float ⇒ Object
Floating options.
-
#grammar ⇒ Object
(also: #ast)
readonly
Grammar.
-
#help(subject = nil) ⇒ Object
readonly
Print help for the given subject or the full documentation if
subjectis nil. -
#name ⇒ Object
readonly
Name of program.
-
#quiet ⇒ Object
readonly
Automatically add a -q and a --quiet option if true.
-
#silent ⇒ Object
readonly
Automatically add a -s and a --silent option if true.
-
#spec ⇒ Object
readonly
Specification (String).
-
#tokens ⇒ Object
readonly
Debug: Internal variables made public.
-
#verbose ⇒ Object
readonly
Automatically add a -v and a --verbose option if true.
-
#version ⇒ Object
readonly
Version of client program.
-
#version_number ⇒ Object
readonly
Version number (this is usually detected dynamically).
Class Method Summary collapse
- .brief ⇒ Object
- .compare_lines(text, spec) ⇒ Object
-
.find_spec_in_text(text, spec, oneline) ⇒ Object
Find line and char index of spec in text.
- .help(subject = nil) ⇒ Object
-
.process(spec, argv, **opts) ⇒ Object
Create a ShellOpts object and sets the global instance, then process the spec and arguments.
- .usage ⇒ Object
Instance Method Summary collapse
-
#brief ⇒ Object
Print brief help.
-
#compile(spec) ⇒ Object
Compile source and return grammar object.
-
#error(message, exit: 1) ⇒ Object
Write short usage and error message to standard error and terminate program with status 1.
-
#failure(message, exit: 1) ⇒ Object
Write error message to standard error and terminate program with status 1.
- #find_spec_in_file ⇒ Object
- #find_subject(obj) ⇒ Object
-
#initialize(name: nil, file: $PROGRAM_NAME, help: true, version: true, silent: nil, quiet: nil, verbose: nil, debug: nil, version_number: nil, float: true, exception: ::ShellOpts.exception) ⇒ ShellOpts
constructor
A new instance of ShellOpts.
-
#interpret(argv) ⇒ Object
Use grammar to interpret arguments.
- #lookup(name) ⇒ Object
-
#process(spec, argv) ⇒ Object
Compile
specand interpretargv. -
#program ⇒ Object
Resulting ShellOpts::Program object containing options and optional subcommand.
-
#usage ⇒ Object
Print usage.
Constructor Details
#initialize(name: nil, file: $PROGRAM_NAME, help: true, version: true, silent: nil, quiet: nil, verbose: nil, debug: nil, version_number: nil, float: true, exception: ::ShellOpts.exception) ⇒ ShellOpts
Returns a new instance of ShellOpts.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/shellopts.rb', line 146 def initialize(name: nil, file: $PROGRAM_NAME, # Options help: true, version: true, silent: nil, quiet: nil, verbose: nil, debug: nil, # Version number (auto-detected for gem packages) version_number: nil, # Floating options float: true, exception: ::ShellOpts.exception ) @name = name || File.basename(file) @file = file @help = help @version_number = version_number || (version && find_version_number) @version = !@version_number.nil? && version @silent = silent @quiet = quiet @verbose = verbose @debug = debug @float = float @exception = exception @clear_screen = true end |
Instance Attribute Details
#args ⇒ Object (readonly)
Array of remaining arguments. Initialized by #interpret
111 112 113 |
# File 'lib/shellopts.rb', line 111 def args @args end |
#argv ⇒ Object (readonly)
Array of arguments. Initialized by #interpret
101 102 103 |
# File 'lib/shellopts.rb', line 101 def argv @argv end |
#debug ⇒ Object (readonly)
Automatically add a --debug option if true
129 130 131 |
# File 'lib/shellopts.rb', line 129 def debug @debug end |
#exception ⇒ Object
Use exceptions instead of ShellOpts's error methods. Default is ShellOpts.exception that itself defalts to false. Mostly used for debug when you want a stack trace instead of a user-readable error message
140 141 142 |
# File 'lib/shellopts.rb', line 140 def exception @exception end |
#file ⇒ Object (readonly)
Executable. Default $PROGRAM_NAME
95 96 97 |
# File 'lib/shellopts.rb', line 95 def file @file end |
#float ⇒ Object
Floating options
135 136 137 |
# File 'lib/shellopts.rb', line 135 def float @float end |
#grammar ⇒ Object (readonly) Also known as: ast
Grammar. Grammar::Program object. Initialized by #compile
104 105 106 |
# File 'lib/shellopts.rb', line 104 def grammar @grammar end |
#help(subject = nil) ⇒ Object (readonly)
Print help for the given subject or the full documentation if subject
is nil. Clears the screen beforehand if #clear_screen is true
114 115 116 |
# File 'lib/shellopts.rb', line 114 def help @help end |
#name ⇒ Object (readonly)
Name of program. Defaults to the name of the executable
92 93 94 |
# File 'lib/shellopts.rb', line 92 def name @name end |
#quiet ⇒ Object (readonly)
Automatically add a -q and a --quiet option if true
123 124 125 |
# File 'lib/shellopts.rb', line 123 def quiet @quiet end |
#silent ⇒ Object (readonly)
Automatically add a -s and a --silent option if true
120 121 122 |
# File 'lib/shellopts.rb', line 120 def silent @silent end |
#spec ⇒ Object (readonly)
Specification (String). Initialized by #compile
98 99 100 |
# File 'lib/shellopts.rb', line 98 def spec @spec end |
#tokens ⇒ Object (readonly)
Debug: Internal variables made public
143 144 145 |
# File 'lib/shellopts.rb', line 143 def tokens @tokens end |
#verbose ⇒ Object (readonly)
Automatically add a -v and a --verbose option if true
126 127 128 |
# File 'lib/shellopts.rb', line 126 def verbose @verbose end |
#version ⇒ Object (readonly)
Version of client program. If not nil, a --version option is added to the program
117 118 119 |
# File 'lib/shellopts.rb', line 117 def version @version end |
#version_number ⇒ Object (readonly)
Version number (this is usually detected dynamically)
132 133 134 |
# File 'lib/shellopts.rb', line 132 def version_number @version_number end |
Class Method Details
.brief ⇒ Object
313 |
# File 'lib/shellopts.rb', line 313 def self.brief() ::ShellOpts.instance.brief end |
.compare_lines(text, spec) ⇒ Object
359 360 361 362 363 |
# File 'lib/shellopts.rb', line 359 def self.compare_lines(text, spec) return true if text == spec return true if text =~ /[#\$\\]/ false end |
.find_spec_in_text(text, spec, oneline) ⇒ Object
Find line and char index of spec in text. Returns [nil, nil] if not found
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/shellopts.rb', line 367 def self.find_spec_in_text(text, spec, oneline) text_lines = text.split("\n") spec_lines = spec.split("\n") spec_lines.pop_while { |line| line =~ /^\s*$/ } if oneline line_i = nil char_i = nil char_z = 0 (0 ... text_lines.size).each { |text_i| curr_char_i, curr_char_z = LCS.find_longest_common_substring_index(text_lines[text_i], spec_lines.first.strip) if curr_char_z > char_z line_i = text_i char_i = curr_char_i char_z = curr_char_z end } line_i ? [line_i, char_i] : [nil, nil] else spec_string = spec_lines.first.strip line_i = (0 ... text_lines.size - spec_lines.size + 1).find { |text_i| (0 ... spec_lines.size).all? { |spec_i| compare_lines(text_lines[text_i + spec_i], spec_lines[spec_i]) } } or return [nil, nil] char_i, char_z = LCS.find_longest_common_substring_index(text_lines[line_i], spec_lines.first.strip) [line_i, char_i || 0] end end |
.help(subject = nil) ⇒ Object
314 |
# File 'lib/shellopts.rb', line 314 def self.help(subject = nil) ::ShellOpts.instance.help(subject) end |
.process(spec, argv, **opts) ⇒ Object
Create a ShellOpts object and sets the global instance, then process the spec and arguments. Returns a tuple of a ShellOpts::Program with the options and subcommands and a ShellOpts::Args object with the remaining arguments
262 263 264 265 266 |
# File 'lib/shellopts.rb', line 262 def self.process(spec, argv, **opts) ::ShellOpts.instance = shellopts = ShellOpts.new(**opts) shellopts.process(spec, argv) [shellopts.program, shellopts.args] end |
Instance Method Details
#brief ⇒ Object
Print brief help
301 |
# File 'lib/shellopts.rb', line 301 def brief() Formatter.brief(@grammar) end |
#compile(spec) ⇒ Object
Compile source and return grammar object. Also sets #spec and #grammar. Returns the grammar
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/shellopts.rb', line 180 def compile(spec) handle_exceptions { @oneline = spec.index("\n").nil? @spec = spec.sub(/^\s*\n/, "") @tokens = Lexer.lex(name, @spec, @oneline) ast = Parser.parse(tokens) help_spec = (@help == true ? "-h,help" : @help) version_spec = (@version == true ? "--version" : @version) silent_spec = (@silent == true ? "--silent" : @silent) quiet_spec = (@quiet == true ? "-q,quiet" : @quiet) verbose_spec = (@verbose == true ? "+v,verbose" : @verbose) debug_spec = (@debug == true ? "--debug" : @debug) @silent_option = ast.inject_option(silent_spec, "Silent", "Do not write anything to standard output/error") if @silent @quiet_option = ast.inject_option(quiet_spec, "Quiet", "Do not write anything to standard output") if @quiet @verbose_option = ast.inject_option(verbose_spec, "Increase verbosity", "Write verbose output") if @verbose @debug_option = ast.inject_option(debug_spec, "Write debug information") if @debug @help_option = ast.inject_option(help_spec, "Write short or long help") { |option| short_option = option.short_names.first long_option = option.long_names.first [ short_option && "#{short_option} prints a brief help text", long_option && "#{long_option} prints a longer man-style description of the command" ].compact.join(", ") } if @help @version_option = ast.inject_option(version_spec, "Write version number and exit") if @version @grammar = Analyzer.analyze(ast) } self end |
#error(message, exit: 1) ⇒ Object
Write short usage and error message to standard error and terminate program with status 1
#error is supposed to be used when the user made an error and the usage is written to help correcting the error
273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/shellopts.rb', line 273 def error(, exit: 1) raise ShellOpts::Error.new() if ::ShellOpts.exception $stderr.puts "#{name}: #{}" saved = $stdout begin $stdout = $stderr Formatter.usage(grammar) ::ShellOpts.handle_exit(exit) ensure $stdout = saved end end |
#failure(message, exit: 1) ⇒ Object
Write error message to standard error and terminate program with status 1
#failure doesn't print the program usage because is supposed to be used when the user specified the correct arguments but something else went wrong during processing
291 292 293 294 295 |
# File 'lib/shellopts.rb', line 291 def failure(, exit: 1) raise ShellOpts::Failure.new() if ::ShellOpts.exception $stderr.puts "#{name}: #{}" ::ShellOpts.handle_exit(exit) end |
#find_spec_in_file ⇒ Object
400 401 402 |
# File 'lib/shellopts.rb', line 400 def find_spec_in_file self.class.find_spec_in_text(IO.read(@file), @spec, @oneline).map { |i| (i || 0) + 1 } end |
#find_subject(obj) ⇒ Object
413 414 415 416 417 418 419 420 421 422 |
# File 'lib/shellopts.rb', line 413 def find_subject(obj) case obj when String; lookup(obj) when Ast::Command; Command.grammar(obj) # FIXME when Grammar::Command; obj when NilClass; grammar else raise Internal, "Illegal object: #{obj.class}" end end |
#interpret(argv) ⇒ Object
Use grammar to interpret arguments. Return a ShellOpts::Program and ShellOpts::Args tuple
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/shellopts.rb', line 222 def interpret(argv) handle_exceptions { @argv = argv.dup @program, @args = Interpreter.interpret(grammar, argv, float: float, exception: exception) # Process standard options that may have been renamed or be deactivated if @help && @program.__send__(:"#{@help_option.ident}?") if @program[:help].name =~ /^--/ ShellOpts.help else ShellOpts.brief end exit elsif @version && @program.__send__(:"#{@version_option.ident}?") puts version_number exit else # Assign standard options. The targets doesn't change if the option is renamed @program.__silent__ = @program.__send__(:"#{@silent_option.ident}?") if @silent @program.__quiet__ = @program.__send__(:"#{@quiet_option.ident}?") if @quiet @program.__verbose__ = @program.__send__(:"#{@verbose_option.ident}") if @verbose @program.__debug__ = @program.__send__(:"#{@debug_option.ident}?") if @debug end } self end |
#lookup(name) ⇒ Object
404 405 406 407 408 409 410 411 |
# File 'lib/shellopts.rb', line 404 def lookup(name) a = name.split(".") cmd = grammar while element = a.shift cmd = cmd.commands[element] end cmd end |
#process(spec, argv) ⇒ Object
Compile spec and interpret argv. Returns a ShellOpts object
251 252 253 254 255 |
# File 'lib/shellopts.rb', line 251 def process(spec, argv) compile(spec) interpret(argv) self end |
#program ⇒ Object
Resulting ShellOpts::Program object containing options and optional subcommand. Initialized by #interpret
108 |
# File 'lib/shellopts.rb', line 108 def program() @program end |