shellopts 2.0.4 → 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0170d9ce5144afcf716b90a3904250c0afa5d769b7a64f39db0b8084e77b4fb7
4
- data.tar.gz: 81495a3802c472c65812594d847c43b0f59849ea0ebe093c74c2fb7d3e822658
3
+ metadata.gz: 6e8933ca7084aea3e51858cd679eec2a6b34b2fc7ae9a55ccce131947ccc7375
4
+ data.tar.gz: 125309b75338e9205fb05c5c556fca54cbc1cc77ef890a4ca2d6992c69eff302
5
5
  SHA512:
6
- metadata.gz: 195801ea89b22920fca88216ed4bd7ac426b3370e482b61547dac085d1c7d9f1bd0a2d0edc7c3368bf126cd5f4da815dd882ee3149cd291549ff631d6302e93a
7
- data.tar.gz: 6dcd50871438db9f5b0520e4f670f6df6ad04756685838d309874a9601770ee79a7370ebc11b0469d19a9f2be89868c7cfd12cfe028c0c01719b4d8d0593fc59
6
+ metadata.gz: 123b17ded3c4943267612959f3b8ab56a37249e38ea9c338c577ad254ebc1c7c9c305ca9a7a3ee2661d9474e905ddd193c5da8e7a5adc3e711c236349095a636
7
+ data.tar.gz: a3115c875274fccf6628d4c839e3eac36804157f7c56e90b599e8201c1bf8f1070b5b92b7e22cbe2c6615e20b81f4de8b81233227aaccdb873f1016e129d99ae
data/TODO CHANGED
@@ -1,4 +1,5 @@
1
1
 
2
+ o Add brackets to optional option arguments: '--all=FILE?' -> '--all[=FILE]'
2
3
  o Ignore all text after ' # ' (doesn't conflict with option flag)
3
4
  o Command aliases
4
5
  o Add user-defined setions
@@ -2,18 +2,23 @@
2
2
  module ShellOpts
3
3
  # Specialization of Array for arguments lists. Args extends Array with a
4
4
  # #extract and an #expect method to extract elements from the array. The
5
- # methods raise a ShellOpts::UserError exception in case of errors
5
+ # methods raise a ShellOpts::Error exception in case of errors
6
6
  #
7
7
  class Args < Array
8
+ # :call-seq:
9
+ # extract(count, message = nil)
10
+ # extract(range, message = nil)
11
+ #
8
12
  # Remove and return elements from beginning of the array
9
13
  #
10
14
  # If +count_or_range+ is a number, that number of elements will be
11
15
  # returned. If the count is one, a simple value is returned instead of an
12
16
  # array. If the count is negative, the elements will be removed from the
13
17
  # end of the array. If +count_or_range+ is a range, the number of elements
14
- # returned will be in that range. The range can't contain negative numbers
18
+ # returned will be in that range. Note that the range can't contain
19
+ # negative numbers
15
20
  #
16
- # #extract raise a ShellOpts::UserError exception if there's is not enough
21
+ # #extract raise a ShellOpts::Error exception if there's is not enough
17
22
  # elements in the array to satisfy the request
18
23
  #
19
24
  def extract(count_or_range, message = nil)
@@ -30,16 +35,16 @@ module ShellOpts
30
35
  count.abs <= self.size or inoa(message)
31
36
  start = count >= 0 ? 0 : size + count
32
37
  r = slice!(start, count.abs)
33
- r.size <= 0 ? nil : (r.size == 1 ? r.first : r)
38
+ r.size == 1 ? r.first : r
34
39
  else
35
40
  raise ArgumentError
36
41
  end
37
42
  end
38
43
 
39
44
  # As #extract except it doesn't allow negative counts and that the array is
40
- # expect to be emptied by the operation
45
+ # expected to be emptied by the operation
41
46
  #
42
- # #expect raise a ShellOpts::UserError exception if the array is not emptied
47
+ # #expect raise a ShellOpts::Error exception if the array is not emptied
43
48
  # by the operation
44
49
  #
45
50
  def expect(count_or_range, message = nil)
@@ -55,7 +60,7 @@ module ShellOpts
55
60
 
56
61
  private
57
62
  def inoa(message = nil)
58
- raise ArgumentError, message || "Illegal number of arguments"
63
+ raise ShellOpts::Error, message || "Illegal number of arguments"
59
64
  end
60
65
  end
61
66
  end
@@ -38,16 +38,17 @@ module ShellOpts
38
38
  using Ext::Array::Wrap
39
39
 
40
40
  def puts_usage(bol: false)
41
+ width = [Formatter.rest, Formatter::USAGE_MAX_WIDTH].min
41
42
  if descrs.size == 0
42
43
  print (lead = Formatter.command_prefix || "")
43
44
  indent(lead.size, ' ', bol: bol && lead == "") {
44
- puts render(:multi, Formatter::USAGE_MAX_WIDTH)
45
+ puts render(:multi, width)
45
46
  }
46
47
  else
47
48
  lead = Formatter.command_prefix || ""
48
49
  descrs.each { |descr|
49
50
  print lead
50
- puts render(:single, Formatter::USAGE_MAX_WIDTH, args: [descr.text])
51
+ puts render(:single, width, args: [descr.text])
51
52
  }
52
53
  end
53
54
  end
@@ -199,8 +200,8 @@ module ShellOpts
199
200
  # Number of characters between columns in brief output
200
201
  BRIEF_COL_SEP = 2
201
202
 
202
- # Maximum width of first column in brief option and command lists
203
- BRIEF_COL1_MIN_WIDTH = 6
203
+ # Minimum width of first column in brief option and command lists
204
+ BRIEF_COL1_MIN_WIDTH = 20
204
205
 
205
206
  # Maximum width of first column in brief option and command lists
206
207
  BRIEF_COL1_MAX_WIDTH = 40
@@ -122,6 +122,22 @@ module ShellOpts
122
122
  def self.parse(token)
123
123
  super(nil, token)
124
124
  end
125
+
126
+ def add_stdopts
127
+ option_token = Token.new(:option, 1, 1, "--version")
128
+ brief_token = Token.new(:brief, 1, 1, "Write version number and exit")
129
+ group = OptionGroup.new(self, option_token)
130
+ option = Option.parse(group, option_token)
131
+ brief = Brief.parse(group, brief_token)
132
+
133
+ option_token = Token.new(:option, 1, 1, "-h,help")
134
+ brief_token = Token.new(:brief, 1, 1, "Write help text and exit")
135
+ paragraph_token = Token.new(:text, 1, 1, "-h prints a brief help text, --help prints a longer man-style description of the command")
136
+ group = OptionGroup.new(self, option_token)
137
+ option = Option.parse(group, option_token)
138
+ brief = Brief.parse(group, brief_token)
139
+ paragraph = Paragraph.parse(group, paragraph_token)
140
+ end
125
141
  end
126
142
 
127
143
  class ArgSpec
@@ -146,6 +162,14 @@ module ShellOpts
146
162
  @nodes = {}
147
163
  end
148
164
 
165
+ # def add_stdopts
166
+ # version_token = Token.new(:option, 1, 1, "--version")
167
+ # version_brief = Token.new(:brief, 1, 1, "Gryf gryf")
168
+ # group = Grammar::OptionGroup.new(@program, version_token)
169
+ # option = Grammar::Option.parse(group, version_token)
170
+ # brief = Grammr::Brief.parse(option, version_brief)
171
+ # end
172
+
149
173
  def parse()
150
174
  @program = Grammar::Program.parse(@tokens.shift)
151
175
  oneline = @tokens.first.lineno == @tokens.last.lineno
@@ -1,3 +1,3 @@
1
1
  module ShellOpts
2
- VERSION = "2.0.4"
2
+ VERSION = "2.0.7"
3
3
  end
data/lib/shellopts.rb CHANGED
@@ -102,6 +102,9 @@ module ShellOpts
102
102
  attr_accessor :stdopts
103
103
  attr_accessor :msgopts
104
104
 
105
+ # Version of client program. This is only used if +stdopts+ is true
106
+ attr_reader :version
107
+
105
108
  # Interpreter flags
106
109
  attr_accessor :float
107
110
 
@@ -116,9 +119,9 @@ module ShellOpts
116
119
  attr_reader :tokens
117
120
  alias_method :ast, :grammar # Oops - defined earlier FIXME
118
121
 
119
- def initialize(name: nil, stdopts: true, msgopts: false, float: true, exception: false)
122
+ def initialize(name: nil, stdopts: true, version: nil, msgopts: false, float: true, exception: false)
120
123
  @name = name || File.basename($PROGRAM_NAME)
121
- @stdopts, @msgopts, @float, @exception = stdopts, msgopts, float, exception
124
+ @stdopts, @version, @msgopts, @float, @exception = stdopts, version, msgopts, float, exception
122
125
  end
123
126
 
124
127
  # Compile source and return grammar object. Also sets #spec and #grammar.
@@ -130,7 +133,7 @@ module ShellOpts
130
133
  @file = find_caller_file
131
134
  @tokens = Lexer.lex(name, @spec, @oneline)
132
135
  ast = Parser.parse(tokens)
133
- # TODO: Add standard and message options and their handlers
136
+ ast.add_stdopts if stdopts
134
137
  @grammar = Analyzer.analyze(ast)
135
138
  }
136
139
  self
@@ -143,6 +146,20 @@ module ShellOpts
143
146
  handle_exceptions {
144
147
  @argv = argv.dup
145
148
  @program, @args = Interpreter.interpret(grammar, argv, float: float, exception: exception)
149
+ if stdopts
150
+ if @program.version?
151
+ version or raise ArgumentError, "Version not specified"
152
+ puts version
153
+ exit
154
+ elsif @program.help?
155
+ if @program[:help].name == "-h"
156
+ ShellOpts.brief
157
+ else
158
+ ShellOpts.help
159
+ end
160
+ exit
161
+ end
162
+ end
146
163
  }
147
164
  self
148
165
  end
@@ -177,7 +194,7 @@ module ShellOpts
177
194
  saved = $stdout
178
195
  $stdout = $stderr
179
196
  $stderr.puts "#{name}: #{message}"
180
- Formatter.usage(program)
197
+ Formatter.usage(grammar)
181
198
  exit 1
182
199
  ensure
183
200
  $stdout = saved
@@ -203,9 +220,10 @@ module ShellOpts
203
220
  # Print help for the given subject or the full documentation if +subject+
204
221
  # is nil. Clears the screen beforehand if :clear is true
205
222
  #
206
- def help(subject = nil, clear: false)
223
+ def help(subject = nil, clear: true)
207
224
  node = (subject ? @grammar[subject] : @grammar) or
208
225
  raise ArgumentError, "No such command: '#{subject&.sub(".", " ")}'"
226
+ print '' if clear
209
227
  Formatter.help(node)
210
228
  end
211
229
 
@@ -310,6 +328,7 @@ module ShellOpts
310
328
  def self.instance?() !@instance.nil? end
311
329
  def self.instance() @instance or raise Error, "ShellOpts is not initialized" end
312
330
  def self.instance=(instance) @instance = instance end
331
+ def self.shellopts() instance end
313
332
 
314
333
  forward_self_to :instance, :error, :failure
315
334
 
data/main CHANGED
@@ -7,18 +7,33 @@ require 'shellopts'
7
7
 
8
8
  include ShellOpts
9
9
 
10
+ VERSION = "1.2.3"
10
11
 
11
12
  SPEC = %(
12
- -a,alpha @ Brief comment for -a and --alpha options
13
- Longer and more elaborate description of the --alpha option
13
+ -a @ An option
14
+ )
15
+ opts, args = ShellOpts::process(SPEC, ARGV, version: VERSION)
16
+ #ShellOpts::ShellOpts.help
14
17
 
15
- -b,beta=ARG
16
- @ Alternative style of brief comment
17
18
 
18
- Longer and more elaborate description of the --beta option
19
- )
20
19
 
21
- opts, args = ShellOpts.process(SPEC, ARGV)
20
+
21
+
22
+
23
+ __END__
24
+
25
+
26
+ #SPEC = %(
27
+ # -a,alpha @ Brief comment for -a and --alpha options
28
+ # Longer and more elaborate description of the --alpha option
29
+ #
30
+ # -b,beta=ARG
31
+ # @ Alternative style of brief comment
32
+ #
33
+ # Longer and more elaborate description of the --beta option
34
+ #)
35
+ #
36
+ #opts, args = ShellOpts.process(SPEC, ARGV)
22
37
  #puts "opts.alpha?: #{opts.alpha?.inspect}"
23
38
  #puts "opts.alpha: #{opts.alpha.inspect}"
24
39
  #puts "opts.beta?: #{opts.beta?.inspect}"
@@ -266,8 +281,9 @@ SPEC4 = %(
266
281
 
267
282
  SPEC5 = "cmd! cmd!"
268
283
 
269
- shellopts = ShellOpts::ShellOpts.new(exception: false)
284
+ shellopts = ShellOpts::ShellOpts.new(exception: true)
270
285
  #shellopts.compile("cmd! cmd!")
286
+
271
287
  shellopts.compile(SPEC)
272
288
  #shellopts.compile(SPEC2)
273
289
  #shellopts.compile(SPEC3)
@@ -277,9 +293,9 @@ shellopts.compile(SPEC)
277
293
  #shellopts.tokens.each(&:dump)
278
294
  #exit
279
295
 
280
- shellopts.usage
296
+ #shellopts.usage
281
297
  #shellopts.brief
282
- #shellopts.help
298
+ shellopts.help
283
299
  #shellopts.help("cmd")
284
300
  #shellopts.help(ARGV.first)
285
301
 
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: 2.0.4
4
+ version: 2.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-01 00:00:00.000000000 Z
11
+ date: 2022-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forward_to