shellopts 0.9.1 → 0.9.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f97bd1dadffdc1a8e5eab5635bdb186ddb925bafc2fe60b478c84d3b9590fb63
4
- data.tar.gz: 9909d8069a937593e7a583d6fd8db1989f7eb8e321d9c655e2d0f376caeffd24
3
+ metadata.gz: 943b9d0c44ba0291937be24cbc79d0155dfc22ac788c69a76639850d78af3303
4
+ data.tar.gz: f38e038f613c577b06e9d2facc6096b39eb18f28266ba8c58a8280adcf75fe47
5
5
  SHA512:
6
- metadata.gz: 161c50d8cb2dc9abaa91164c3898f57942a6d51fcaadcb83bfd52cb96115548772be5d244d7e620f71751b523fdd5db0ab8a8a8bc76624be40a94d0341ac53c3
7
- data.tar.gz: abaa5c58dfc5aaa98a553b4cb582c738a4bcd3649e5681c034a32b550bb583d106e4b0240cb0c5225dc0c8f58b3a32af2bd314d5894209b39b72e26446c6f4e3
6
+ metadata.gz: 42cc6102c0c66dcffda0b03f9c584c32abc0e62a65dbe79e1389753b74af11f189e27a456e79fb2cb082595622ddbce0840dd22419204e276a48134ac8afd610
7
+ data.tar.gz: 6a3b2e35718a5ee1f52e5d56a50ea067da90fef35a4ac3322738e24d5ba80f4aba4ac4a692caace4bb094ccfb84432e9211fef2b15dfef2e194a95569ca80686
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  /.yardoc
3
3
  /_yardoc/
4
4
  /doc/
5
+ /rdoc/
5
6
  /pkg/
6
7
  /spec/reports/
7
8
  /tmp/
data/README.md CHANGED
@@ -1,20 +1,20 @@
1
1
  # Shellopts
2
2
 
3
- `ShellOpts` is a simple command line parsing libray that covers most modern use
3
+ `ShellOpts` is a simple Linux command line parsing libray that covers most modern use
4
4
  cases incl. sub-commands. Options and commands are specified using a
5
5
  getopt(1)-like string that is interpreted by the library to process the command
6
6
  line
7
7
 
8
8
  ## Usage
9
9
 
10
- The following program accepts `-a` and `--all` that are aliases
11
- for the same option, `--count` that may be given an integer argument but
12
- defaults to 42, `--file` that has a mandatory argument, and `-v` and
13
- `--verbose` that can be repeated to increase the verbosity level
10
+ Program that accepts the options -a or --all, --count, --file, and -v or
11
+ --verbose. The usage definition expects `--count` to have an optional integer
12
+ argument, `--file` to have a mandatory argument, and allows `-v` and
13
+ `--verbose` to be repeated:
14
14
 
15
- ```ruby
16
- require 'shellopts'
17
15
 
16
+ ```ruby
17
+
18
18
  # Define options
19
19
  USAGE = "a,all count=#? file= +v,verbose -- FILE..."
20
20
 
@@ -36,7 +36,7 @@ args = ShellOpts.process(USAGE, ARGV) do |opt, arg|
36
36
  end
37
37
  end
38
38
 
39
- # Process remaining arguments
39
+ # Process remaining command line arguments
40
40
  args.each { |arg| ... }
41
41
  ```
42
42
 
@@ -50,10 +50,10 @@ error
50
50
 
51
51
  ## Processing
52
52
 
53
- `ShellOpts.process` compiles a usage definition string into a grammar and use that to
54
- parse the command line. If given a block, the block is called with a name/value
55
- pair for each option or command and return a list of the remaining non-option
56
- arguments
53
+ `ShellOpts.process` compiles a usage definition string into a grammar and use
54
+ that to parse the command line. If given a block, the block is called with a
55
+ name/value pair for each option or command and return a list of the remaining
56
+ non-option arguments
57
57
 
58
58
  ```ruby
59
59
  args = ShellOpts.process(USAGE, ARGV) do |opt, arg|
@@ -101,6 +101,18 @@ An option is defined by a list of comma-separated names optionally prefixed by a
101
101
  [ "+" ] name-list [ "=" [ "#" | "$" ] [ label ] [ "?" ] ]
102
102
  ```
103
103
 
104
+ #### Flags
105
+
106
+ There are the following flags:
107
+
108
+ |Flag|Effect|
109
+ |---|---|
110
+ |+|Repeated option (prefix)|
111
+ |=|Argument. Mandatory unless `?` is also used|
112
+ |#|Integer argument|
113
+ |$|Floating point argument|
114
+ |?|Optional argument|
115
+
104
116
  #### Repeated options
105
117
 
106
118
  Options are unique by default and the user will get an error if an option is
@@ -257,8 +269,25 @@ system (eg. disk full) and omits the usage summary
257
269
  ```
258
270
 
259
271
  The methods are defined as instance methods on `ShellOpts::ShellOpts` and as
260
- class methods on `ShellOpts`. The class methods stores program name and usage
261
- string in global variables that are reset by `ShellOpts.reset`
272
+ class methods on `ShellOpts`. They can also be included in the global scope by
273
+ `include ShellOpts::Utils`
274
+
275
+ #### Usage string
276
+
277
+ The error handling methods prints a prettified version of the usage string
278
+ given to `ShellOpts.parse`. It can be overridden by assigning to
279
+ `ShellOpts.usage`. You'll often assign to the usage string when it needs to be
280
+ split over several lines:
281
+
282
+ ```ruby
283
+
284
+ USAGE="long-and-complex-usage-string"
285
+ ShellOpts.usage = %(
286
+ usage explanation
287
+ split over
288
+ multiple lines
289
+ )
290
+ ```
262
291
 
263
292
  ## Example
264
293
 
data/TODO CHANGED
@@ -1,5 +1,11 @@
1
1
 
2
2
  TODO
3
+ o Check on return value from #process block to see if all options was handled:
4
+ case opt
5
+ when '-v'; verbose = true # Return value 'true' is ok
6
+ # Unhandled option means return value is nil
7
+ end
8
+ o Consolidate some of the 3 variations of #error and #fail
3
9
  o Add a option flag for solitary options (--help)
4
10
  o Make a #to_yaml
5
11
  o Make an official dump method for debug
@@ -54,6 +60,7 @@ LATER
54
60
  o Escape of separator in lists
55
61
  o Handle output of subcommand usage like "cmd1 cmd1.cmd2 cmd2"
56
62
  o Command-specific arguments: clone! o,opt ++ ARG1 ARG2...
63
+ o Hostname and email as basic types
57
64
 
58
65
  ON TO_H BRANCH
59
66
  ShellOpts.process(usage, argv) { |opt,val| ... } => args
data/bin/mkdoc CHANGED
@@ -1,10 +1,15 @@
1
1
  #!/usr/bin/bash
2
2
 
3
- LINK='<link rel="stylesheet" type="text/css" href="stylesheet.css">'
3
+ set -e
4
4
 
5
- {
6
- echo $LINK
7
- pandoc README.md
8
- } >index.html
5
+ # Generate github-like page
6
+ (
7
+ cd doc
8
+ {
9
+ echo '<link rel="stylesheet" type="text/css" href="stylesheet.css">'
10
+ pandoc ../README.md
11
+ } >index.html
12
+ )
9
13
 
10
- rdoc lib
14
+ # Generate rdoc
15
+ rdoc --output=rdoc --force-output lib
@@ -2,12 +2,28 @@ require "shellopts/version"
2
2
 
3
3
  require 'shellopts/compiler.rb'
4
4
  require 'shellopts/parser.rb'
5
+ require 'shellopts/utils.rb'
5
6
 
6
7
  # ShellOpts is a library for parsing command line options and sub-commands. The
7
8
  # library API consists of the methods {ShellOpts.process}, {ShellOpts.error},
8
9
  # and {ShellOpts.fail} and the result class {ShellOpts::ShellOpts}
9
10
  #
11
+ # ShellOpts inject the constant PROGRAM into the global scope. It contains the
12
+ # name of the program
13
+ #
10
14
  module ShellOpts
15
+ # Return the hidden +ShellOpts::ShellOpts+ object (see .process)
16
+ def self.shellopts()
17
+ @shellopts
18
+ end
19
+
20
+ # Prettified usage string used by #error and #fail. Default is +usage+ of
21
+ # the current +ShellOpts::ShellOpts+ object
22
+ def self.usage() @usage ||= @shellopts&.usage end
23
+
24
+ # Set the usage string
25
+ def self.usage=(usage) @usage = usage end
26
+
11
27
  # Process command line options and arguments. #process takes a usage string
12
28
  # defining the options and the array of command line arguments to be parsed
13
29
  # as arguments
@@ -68,15 +84,17 @@ module ShellOpts
68
84
  # #process saves a hidden {ShellOpts::ShellOpts} class variable used by the
69
85
  # class methods #error and #fail. Call #reset to clear the global object if
70
86
  # you really need to parse more than one command line. Alternatively you can
71
- # create +ShellOpts::ShellOpts+ objects yourself and use the object methods
72
- # #error and #fail instead:
87
+ # create +ShellOpts::ShellOpts+ objects yourself and also use the object methods
88
+ # #error and #fail:
73
89
  #
74
90
  # shellopts = ShellOpts::ShellOpts.new(USAGE, ARGS)
75
91
  # shellopts.each { |name, value| ... }
76
92
  # shellopts.args.each { |arg| ... }
77
93
  # shellopts.error("Something went wrong")
78
94
  #
79
- def self.process(usage, argv, program_name: File.basename($0), &block)
95
+ # Use #shellopts to get the hidden +ShellOpts::ShellOpts+ object
96
+ #
97
+ def self.process(usage, argv, program_name: PROGRAM, &block)
80
98
  if !block_given?
81
99
  ShellOpts.new(usage, argv, program_name: program_name)
82
100
  else
@@ -91,17 +109,28 @@ module ShellOpts
91
109
  # another command line
92
110
  def self.reset()
93
111
  @shellopts = nil
112
+ @usage = nil
94
113
  end
95
114
 
96
- # Print error message and usage string and exit with status 1. Can only be
97
- # called after #process. Forwards to {::ShellOpts#error}
115
+ # Print error message and usage string and exit with status 1. It use the
116
+ # current ShellOpts object if defined. This method should be called in
117
+ # response to user-errors (eg. specifying an illegal option)
118
+ #
119
+ # If there is no current ShellOpts object +error+ will look for USAGE to make
120
+ # it possible to use +error+ before the command line is processed and also as
121
+ # a stand-alone error reporting method
98
122
  def self.error(*msgs)
99
- @shellopts&.error(*msgs) or raise InternalError, "ShellOpts class variable not initialized"
123
+ program = @shellopts&.program_name || PROGRAM
124
+ usage_string = usage || (defined?(USAGE) && USAGE ? Grammar.compile(PROGRAM, USAGE).usage : nil)
125
+ emit_and_exit(program, usage_string, *msgs)
100
126
  end
101
127
 
102
- # Print error message and exit with status 1. Forwards to {::ShellOpts#fail}
128
+ # Print error message and exit with status 1. It use the current ShellOpts
129
+ # object if defined. This method should not be called in response to
130
+ # user-errors but system errors (like disk full)
103
131
  def self.fail(*msgs)
104
- @shellopts&.fail(*msgs) or raise InternalError, "ShellOpts class variable not initialized"
132
+ program = @shellopts&.program_name || PROGRAM
133
+ emit_and_exit(program, nil, *msgs)
105
134
  end
106
135
 
107
136
  # The compilation object
@@ -109,7 +138,7 @@ module ShellOpts
109
138
  # Name of program
110
139
  attr_reader :program_name
111
140
 
112
- # Usage string. Shorthand for +grammar.usage+
141
+ # Prettified usage string used by #error and #fail. Shorthand for +grammar.usage+
113
142
  def usage() @grammar.usage end
114
143
 
115
144
  # The grammar compiled from the usage string. If #ast is defined, it's
@@ -162,16 +191,13 @@ module ShellOpts
162
191
  # should be called in response to user-errors (eg. specifying an illegal
163
192
  # option)
164
193
  def error(*msgs)
165
- $stderr.puts "#{program_name}: #{msgs.join}"
166
- $stderr.puts "Usage: #{program_name} #{usage}"
167
- exit 1
194
+ ::ShellOpts.emit_and_exit(program_name, usage, msgs)
168
195
  end
169
196
 
170
197
  # Print error message and exit with status 1. This method should not be
171
198
  # called in response to user-errors but system errors (like disk full)
172
199
  def fail(*msgs)
173
- $stderr.puts "#{program_name}: #{msgs.join}"
174
- exit 1
200
+ ::ShellOpts.emit_and_exit(program_name, nil, msgs)
175
201
  end
176
202
  end
177
203
 
@@ -191,5 +217,12 @@ module ShellOpts
191
217
 
192
218
  private
193
219
  @shellopts = nil
220
+
221
+ def self.emit_and_exit(program, usage, *msgs)
222
+ $stderr.puts "#{program}: #{msgs.join}"
223
+ $stderr.puts "Usage: #{program} #{usage}" if usage
224
+ exit 1
225
+ end
194
226
  end
195
227
 
228
+ PROGRAM = File.basename($PROGRAM_NAME)
@@ -27,7 +27,7 @@ module ShellOpts
27
27
 
28
28
  # Initialize a Compiler object. source is the option definition string
29
29
  def initialize(program_name, source)
30
- @program_name, @tokens = program_name, source.split(/\s+/)
30
+ @program_name, @tokens = program_name, source.split(/\s+/).reject(&:empty?)
31
31
 
32
32
  # @commands_by_path is an hash from command-path to Command or Program
33
33
  # object. The top level Program object has nil as its path.
@@ -19,7 +19,6 @@ module ShellOpts
19
19
  attr_reader :commands
20
20
 
21
21
  # List of options in declaration order
22
- # order
23
22
  attr_reader :option_list
24
23
 
25
24
  # List of commands in declaration order
@@ -0,0 +1,16 @@
1
+
2
+ module ShellOpts
3
+ # Use `include ShellOpts::Utils` to include ShellOpts utility methods in the
4
+ # global namespace
5
+ module Utils
6
+ # Forwards to `ShellOpts.error`
7
+ def error(*msgs)
8
+ ::ShellOpts.error(*msgs)
9
+ end
10
+
11
+ # Forwards to `ShellOpts.fail`
12
+ def fail(*msgs)
13
+ ::ShellOpts.fail(*msgs)
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,3 @@
1
1
  module Shellopts
2
- VERSION = "0.9.1"
2
+ VERSION = "0.9.6"
3
3
  end
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.require_paths = ["lib"]
34
34
 
35
35
  spec.add_development_dependency "bundler", "~> 1.16"
36
- spec.add_development_dependency "rake", "~> 10.0"
36
+ spec.add_development_dependency "rake", ">= 12.3.3"
37
37
  spec.add_development_dependency "rspec", "~> 3.0"
38
38
  spec.add_development_dependency "indented_io"
39
39
  spec.add_development_dependency "simplecov"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shellopts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-20 00:00:00.000000000 Z
11
+ date: 2020-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 12.3.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 12.3.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -103,6 +103,7 @@ files:
103
103
  - bin/console
104
104
  - bin/mkdoc
105
105
  - bin/setup
106
+ - doc/stylesheet.css
106
107
  - lib/ext/array.rb
107
108
  - lib/shellopts.rb
108
109
  - lib/shellopts/ast/command.rb
@@ -115,6 +116,7 @@ files:
115
116
  - lib/shellopts/grammar/option.rb
116
117
  - lib/shellopts/grammar/program.rb
117
118
  - lib/shellopts/parser.rb
119
+ - lib/shellopts/utils.rb
118
120
  - lib/shellopts/version.rb
119
121
  - shellopts.gemspec
120
122
  homepage: http://github.com/clrgit/shellopts
@@ -136,8 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
138
  - !ruby/object:Gem::Version
137
139
  version: '0'
138
140
  requirements: []
139
- rubyforge_project:
140
- rubygems_version: 2.7.6
141
+ rubygems_version: 3.0.8
141
142
  signing_key:
142
143
  specification_version: 4
143
144
  summary: Parse command line options and arguments