xoptparse 0.2.0 → 0.6.2

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: ed8ba0e138b8c1d6e68ca65d8e022ef51f3456647121207904074ffa8d53ac9f
4
- data.tar.gz: e3ffc6e2caa748fadeb8b9a6f3129491d2997c8edf89780689bc6eac02c07489
3
+ metadata.gz: 0fec1922d2cc3feb99ef500264fabd725220b8cd6fc4763a65e76314a2524900
4
+ data.tar.gz: 8625af6499870c233f0b0f9a46be9e3b04fee65aa4d5f10172e4b0f400cd867a
5
5
  SHA512:
6
- metadata.gz: f160dfefb34a43a2b9f60ec775679e810613665edba3138857836467285eb5d8ce58c664687bd823322c619ea32a8c84ddab328b7e6a432c5f784dfffdff9727
7
- data.tar.gz: '0950deea41a448199bc90aa1fb65365940fee26c3e3dd994c27d62e8e5677aaaf160e2234a91e24539ae36ecbc498f17aded45674e50e694c1ce4599c45ed1d5'
6
+ metadata.gz: 2a6d1ccfbbbf79867f826c18b8548b786dd3792d02c30d317685931716ee204175e28f6b1e31bd7fbaa959d226459ba78153212ca56aea0cd91644d312e85d29
7
+ data.tar.gz: 292a0fa1c8e5e62c0809ae1df4fab5bd865d0b0921d513c2bcac94dfdbcbc6acd35838bd605df2e261674c0b9cd571f2f83a0044b01a0e551764420c6e1028ef
@@ -12,6 +12,9 @@ Metrics/AbcSize:
12
12
  Exclude:
13
13
  - test/**/*
14
14
 
15
+ Metrics/BlockLength:
16
+ Enabled: false
17
+
15
18
  Metrics/ClassLength:
16
19
  Enabled: false
17
20
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- xoptparse (0.2.0)
4
+ xoptparse (0.6.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -52,7 +52,7 @@ DEPENDENCIES
52
52
  minitest-power_assert
53
53
  minitest-reporters
54
54
  rake (~> 12.3.3)
55
- rubocop (= 0.84.0)
55
+ rubocop
56
56
  simplecov
57
57
  xoptparse!
58
58
 
@@ -55,130 +55,201 @@ class XOptionParser < ::OptionParser
55
55
  end
56
56
  private :search_arg_switch_atype
57
57
 
58
- def fix_arg_switch(sw0)
59
- pattern, conv = search_arg_switch_atype(sw0)
60
- Switch::SimpleArgument.new(pattern, conv, nil, nil, sw0.desc[0], sw0.desc[1..], sw0.block)
58
+ def fix_arg_switch(sw0) # rubocop:disable Metrics/AbcSize
59
+ if !(sw0.short || sw0.long)
60
+ pattern, conv = search_arg_switch_atype(sw0)
61
+ Switch::SimpleArgument.new(pattern, conv, nil, nil, sw0.desc[0], sw0.desc[1..], sw0.block)
62
+ elsif sw0.is_a?(Switch::PlacedArgument) && sw0.long.size == 1 && /^--\[no-\]/ =~ sw0.long.first
63
+ args = [sw0.pattern, sw0.conv, sw0.short, sw0.long, sw0.arg, sw0.desc, sw0.block]
64
+ Switch::FlagArgument.new(*args)
65
+ else
66
+ sw0
67
+ end
61
68
  end
62
69
  private :fix_arg_switch
63
70
 
64
71
  def make_switch(opts, block = nil)
65
72
  sw = super(opts, block || proc {})
66
- sw0 = sw[0]
73
+ sw0 = sw[0] = fix_arg_switch(sw[0])
67
74
  return sw if sw0.short || sw0.long
68
75
 
69
- sw0 = fix_arg_switch(sw0)
70
- long = sw0.arg.scan(/(?:\[\s*(.*?)\s*\]|(\S+))/).flatten.compact
76
+ long = sw0.arg_parameters.map(&:first)
71
77
  [sw0, nil, long]
72
78
  end
73
79
 
74
- def parse_arguments(argv) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
75
- arg_sws = select { |sw| sw.is_a?(Switch::SimpleArgument) }
80
+ def parse_arguments(argv, setter = nil, opts = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
81
+ arg_sws = select { |sw| sw.is_a?(Switch::SummarizeArgument) && !opts.include?(sw.switch_name) }
76
82
  return argv if arg_sws.empty?
77
83
 
78
84
  sws_ranges = arg_sws.map(&:ranges).flatten(1)
79
85
  req_count = sws_ranges.sum(&:begin)
80
- raise MissingArgument, argv.join(' ') if argv.size < req_count
81
-
82
86
  opt_count = sws_ranges.sum(&:size) - sws_ranges.size
83
87
  opt_index = argv[req_count...].index { |arg| @commands.include?(arg) } unless @commands.empty?
84
88
  opt_count = [opt_count, opt_index || Float::INFINITY, argv.size - req_count].min
85
89
 
86
- arg_sws.each do |sw|
87
- conv = proc { |v| sw.send(:conv_arg, *sw.send(:parse_arg, v))[2] }
88
- a = sw.ranges.map do |r|
89
- if r.end.nil?
90
- rest_size = r.begin + opt_count
91
- req_count -= r.begin
92
- opt_count = 0
93
- argv.slice!(0...rest_size).map(&conv)
94
- elsif r.begin.zero?
95
- next conv.call(nil) if opt_count.zero?
96
-
97
- opt_count -= 1
98
- conv.call(argv.shift)
99
- else
100
- req_count -= 1
101
- conv.call(argv.shift)
90
+ arg_sws.each_with_index do |sw, i|
91
+ if sw.is_a?(Switch::SimpleArgument)
92
+ callable = false
93
+ conv = proc do |v|
94
+ callable = true
95
+ sw.send(:conv_arg, *sw.send(:parse_arg, v))[2]
96
+ end
97
+ a = sw.ranges.map do |r|
98
+ raise MissingArgument if r.begin.positive? && argv.empty?
99
+
100
+ if r.end.nil?
101
+ rest_size = r.begin + opt_count
102
+ req_count -= r.begin
103
+ opt_count = 0
104
+ argv.slice!(0...rest_size).map(&conv)
105
+ elsif r.begin.positive?
106
+ req_count -= 1
107
+ conv.call(argv.shift)
108
+ elsif opt_count.positive?
109
+ opt_count -= 1
110
+ conv.call(argv.shift)
111
+ end
102
112
  end
113
+ if callable
114
+ val = sw.block.call(*a)
115
+ setter&.call(sw.switch_name, val)
116
+ end
117
+ elsif sw.pattern =~ argv.first
118
+ argv.shift
119
+ @command_switch = sw
120
+ break
121
+ elsif !argv.empty? && i == arg_sws.size - 1
122
+ raise MissingArgument
103
123
  end
104
- sw.block.call(*a)
105
124
  end
106
125
 
107
126
  argv
108
127
  end
109
128
  private :parse_arguments
110
129
 
111
- def parse_in_order(*args, &nonopt)
112
- argv = []
130
+ def parse_in_order(argv = default_argv, setter = nil, &nonopt)
131
+ nonopts = []
132
+ opts = {}
133
+ opts_setter = proc do |name, val|
134
+ opts[name] = true
135
+ setter&.call(name, val)
136
+ end
113
137
  rest = if nonopt
114
- super(*args, &argv.method(:<<))
138
+ super(argv, opts_setter, &nonopts.method(:<<))
115
139
  else
116
- argv = super(*args)
140
+ nonopts = super(argv, opts_setter)
117
141
  end
118
- parse_arguments(argv).map(&nonopt)
142
+ parse_arguments(nonopts, setter, opts).map(&nonopt)
119
143
  rest
120
144
  end
121
145
  private :parse_in_order
122
146
 
123
- def order!(*args, **kwargs)
124
- return super(*args, **kwargs) if @commands.empty?
125
-
126
- argv = super(*args, **kwargs, &nil)
127
- return argv if argv.empty?
147
+ def order!(*args, into: nil, **kwargs)
148
+ return super(*args, into: into, **kwargs) if @commands.empty?
128
149
 
129
- name = argv.shift
130
- sw = @commands[name]
131
- return sw.block.call.send(block_given? ? :permute! : :order!, *args, **kwargs) if sw
150
+ @command_switch = nil
151
+ argv = super(*args, into: into, **kwargs, &nil)
152
+ return argv unless @command_switch
132
153
 
133
- puts "#{program_name}:" \
134
- "'#{name}' is not a #{program_name} command. See '#{program_name} --help'."
135
- exit
154
+ into = into[@command_switch.arg.to_sym] = {} if into
155
+ @command_switch.block.call.send(block_given? ? :permute! : :order!, *args, into: into, **kwargs)
136
156
  end
137
157
 
138
158
  def command(name, desc = nil, *args, &block)
139
- sw0 = Switch::SummarizeArgument.new(nil, nil, nil, nil, name.to_s, desc ? [desc] : [], nil) do
159
+ name = name.to_s
160
+ pattern = /^#{name.gsub('_', '[-_]?')}$/i
161
+ sw0 = Switch::SummarizeArgument.new(pattern, nil, nil, nil, name, desc ? [desc] : [], nil) do
140
162
  self.class.new(desc, *args) do |opt|
141
163
  opt.program_name = "#{program_name} #{name}"
142
164
  block&.call(opt)
143
165
  end
144
166
  end
145
167
  top.append(sw0, nil, [sw0.arg])
146
- @commands[name.to_s] = sw0
168
+ @commands[name] = sw0
147
169
  nil
148
170
  end
149
171
 
150
172
  class Switch < ::OptionParser::Switch
151
- class SummarizeArgument < NoArgument
173
+ class SummarizeArgument < self
152
174
  undef_method :add_banner
153
175
 
154
- def summarize(*args)
176
+ attr_reader :ranges
177
+ attr_reader :arg_parameters
178
+
179
+ def initialize(*)
180
+ super
181
+ @ranges = []
182
+ @arg_parameters = arg.scan(/\[\s*(.*?)\s*\]|(\S+)/).map do |opt, req|
183
+ name = opt || req
184
+ [name.sub(/\s*\.\.\.$/, ''), opt ? :opt : :req, name.end_with?('...') ? :rest : nil]
185
+ end
186
+ end
187
+
188
+ def summarize(*)
155
189
  original_arg = arg
156
- @short = arg.scan(/\[\s*.*?\s*\]|\S+/)
190
+ @short = arg_parameters.map do |name, type, rest|
191
+ var = "#{name}#{rest ? '...' : ''}"
192
+ type == :req ? var : "[#{var}]"
193
+ end
157
194
  @arg = nil
158
- res = super(*args)
195
+ res = super
159
196
  @arg = original_arg
160
197
  @short = nil
161
198
  res
162
199
  end
163
200
 
164
- def match_nonswitch?(*args)
165
- super(*args) if @pattern.is_a?(Regexp)
201
+ def match_nonswitch?(*)
202
+ nil
203
+ end
204
+
205
+ def switch_name
206
+ arg_parameters.first.first
207
+ end
208
+
209
+ def parse(_arg, _argv)
210
+ raise XOptionParser::InvalidOption
166
211
  end
167
212
  end
168
213
 
169
214
  class SimpleArgument < SummarizeArgument
170
- attr_reader :ranges
171
-
172
- def initialize(*args)
173
- super(*args)
174
- @ranges = arg.scan(/\[\s*(.*?)\s*\]|(\S+)/).map do |opt, req|
175
- (opt ? 0 : 1)..((opt || req).end_with?('...') ? nil : 1)
215
+ def initialize(*)
216
+ super
217
+ @ranges = arg_parameters.map do |_name, type, rest|
218
+ (type == :req ? 1 : 0)..(rest == :rest ? nil : 1)
176
219
  end
177
220
  end
178
221
 
179
222
  def add_banner(to)
180
223
  to << " #{arg}"
181
224
  end
225
+
226
+ def parse(arg, argv) # rubocop:disable Metrics/CyclomaticComplexity
227
+ case ranges.size
228
+ when 0
229
+ yield(NeedlessArgument, arg) if arg
230
+ conv_arg(arg)
231
+ when 1
232
+ unless arg
233
+ raise XOptionParser::MissingArgument if argv.empty?
234
+
235
+ arg = argv.shift
236
+ end
237
+ arg = [arg] if ranges.first.end.nil?
238
+ conv_arg(*parse_arg(arg, &method(:raise)))
239
+ else
240
+ super(arg, argv)
241
+ end
242
+ end
243
+ end
244
+
245
+ class FlagArgument < PlacedArgument
246
+ def parse(arg, argv, &error)
247
+ super(arg, argv, &error).tap do |val|
248
+ raise OptionParser::InvalidArgument if val[0].nil? && val[2].nil?
249
+ end
250
+ rescue OptionParser::InvalidArgument
251
+ conv_arg(arg)
252
+ end
182
253
  end
183
254
  end
184
255
  end
@@ -3,5 +3,5 @@
3
3
  require 'optparse'
4
4
 
5
5
  class XOptionParser < ::OptionParser
6
- VERSION = '0.2.0'
6
+ VERSION = '0.6.2'
7
7
  end
@@ -29,6 +29,6 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency 'minitest-power_assert'
30
30
  spec.add_development_dependency 'minitest-reporters'
31
31
  spec.add_development_dependency 'rake', '~> 12.3.3'
32
- spec.add_development_dependency 'rubocop', '0.84.0'
32
+ spec.add_development_dependency 'rubocop'
33
33
  spec.add_development_dependency 'simplecov'
34
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xoptparse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ofk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-12 00:00:00.000000000 Z
11
+ date: 2020-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 0.84.0
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: 0.84.0
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement