Class: Thor::Options
Overview
rubocop:disable ClassLength
Constant Summary collapse
- LONG_RE =
Constants
/^(--\w+(?:-\w+)*)$/- SHORT_RE =
/^(-[a-z])$/i- EQ_RE =
/^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i- SHORT_SQ_RE =
Matches “multiple short switches”, like ‘-xv`.
/^-([a-z]{2,})$/i- SHORT_NUM =
Matches things like ‘’-x123’‘.
/^(-[a-z])#{ Thor::Arguments::NUMERIC }$/i- OPTS_END =
The “bare double-dash” used to indicate that following arguments should not be parsed for options.
"--"
Constants inherited from Arguments
Class Method Summary collapse
-
.to_switches(options) ⇒ Object
Receives a hash and makes it switches.
Instance Method Summary collapse
- #check_unknown! ⇒ Object
-
#current_is_switch? ⇒ Boolean
protected
Check if the current value in peek is a registered switch.
- #current_is_switch_formatted? ⇒ Boolean protected
-
#initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false) ⇒ Options
constructor
Takes a hash of Thor::Option and a hash with defaults.
-
#last? ⇒ Boolean
protected
.
-
#normalize_switch(raw_switch_arg) ⇒ String
protected
Check if the given argument is actually a shortcut.
-
#parse(args) ⇒ Object
rubocop:disable MethodLength.
-
#parse_boolean(switch) ⇒ Object
protected
Parse boolean values which can be given as –foo=true, –foo or –no-foo.
-
#parse_peek(switch, option) ⇒ Object
protected
Parse the value at the peek analyzing if it requires an input or not.
- #parsing_options? ⇒ Boolean protected
-
#peek ⇒ Object
What’s next?! I think.
-
#remaining ⇒ Object
Instance Methods ========================================================================.
- #switch?(arg) ⇒ Boolean protected
-
#switch_option(arg) ⇒ Thor::Option?
protected
Get the option for a switch arg.
Methods inherited from Arguments
Constructor Details
#initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false) ⇒ Options
Takes a hash of Thor::Option and a hash with defaults.
If stop_on_unknown is true, #parse will stop as soon as it encounters an unknown option or a regular argument.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/thor/parser/options.rb', line 68 def initialize = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false @stop_on_unknown = stop_on_unknown @disable_required_check = disable_required_check = .values super() # Add defaults defaults.each do |key, value| @assigns[key.to_s] = value @non_assigned_required.delete([key]) end @shorts = {} @switches = {} @extra = [] .each do |option| @switches[option.switch_name] = option option.aliases.each do |short| name = short.to_s.sub(/^(?!\-)/, "-") @shorts[name] ||= option.switch_name end end end |
Class Method Details
.to_switches(options) ⇒ Object
Receives a hash and makes it switches.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/thor/parser/options.rb', line 39 def self.to_switches() .map do |key, value| case value when true "--#{key}" when Array "--#{key} #{value.map(&:inspect).join(' ')}" when Hash "--#{key} #{value.map { |k, v| "#{k}:#{v}" }.join(' ')}" when nil, false nil else "--#{key} #{value.inspect}" end end.compact.join(" ") end |
Instance Method Details
#check_unknown! ⇒ Object
198 199 200 201 202 203 204 |
# File 'lib/thor/parser/options.rb', line 198 def check_unknown! # an unknown option starts with - or -- and has no more --'s afterward. unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ } unless unknown.empty? raise UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'" end end |
#current_is_switch? ⇒ Boolean (protected)
Check if the current value in peek is a registered switch.
Two booleans are returned. The first is true if the current value starts with a hyphen; the second is true if it is a registered switch.
218 219 220 221 222 223 224 225 226 227 |
# File 'lib/thor/parser/options.rb', line 218 def current_is_switch? case peek when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM [true, switch?($1)] when SHORT_SQ_RE [true, $1.split("").any? { |f| switch?("-#{f}") }] else [false, false] end end |
#current_is_switch_formatted? ⇒ Boolean (protected)
230 231 232 233 234 235 236 237 |
# File 'lib/thor/parser/options.rb', line 230 def current_is_switch_formatted? case peek when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE true else false end end |
#last? ⇒ Boolean (protected)
210 211 212 |
# File 'lib/thor/parser/options.rb', line 210 def last? super() || peek == OPTS_END end |
#normalize_switch(raw_switch_arg) ⇒ String (protected)
Check if the given argument is actually a shortcut.
Also normalizes ‘_’ to ‘-’.
278 279 280 |
# File 'lib/thor/parser/options.rb', line 278 def normalize_switch raw_switch_arg (@shorts[raw_switch_arg] || raw_switch_arg).tr("_", "-") end |
#parse(args) ⇒ Object
rubocop:disable MethodLength
142 143 144 145 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 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/thor/parser/options.rb', line 142 def parse args # rubocop:disable MethodLength logger.debug __method__.to_s, args: args @pile = args.dup = true while peek if match, is_switch = current_is_switch? shifted = shift if is_switch case shifted when SHORT_SQ_RE unshift($1.split("").map { |f| "-#{f}" }) next when EQ_RE, SHORT_NUM unshift $2 raw_switch_arg = $1 when LONG_RE, SHORT_RE raw_switch_arg = $1 end switch = normalize_switch raw_switch_arg option = switch_option switch @assigns[option.human_name] = parse_peek switch, option elsif @stop_on_unknown = false @extra << shifted @extra << shift while peek break elsif match @extra << shifted @extra << shift while peek && peek !~ /^-/ else @extra << shifted end else @extra << shift end end check_requirement! unless @disable_required_check assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns) assigns.freeze logger.debug "#{ __method__ } done", assigns: assigns, remaining: remaining assigns end |
#parse_boolean(switch) ⇒ Object (protected)
Parse boolean values which can be given as –foo=true, –foo or –no-foo.
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/thor/parser/options.rb', line 291 def parse_boolean(switch) if current_is_value? if ["true", "TRUE", "t", "T", true].include?(peek) shift true elsif ["false", "FALSE", "f", "F", false].include?(peek) shift false else !no_or_skip?(switch) end else @switches.key?(switch) || !no_or_skip?(switch) end end |
#parse_peek(switch, option) ⇒ Object (protected)
Parse the value at the peek analyzing if it requires an input or not.
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/thor/parser/options.rb', line 313 def parse_peek switch, option if current_is_switch_formatted? || last? if option.boolean? # No problem for boolean types elsif no_or_skip?(switch) return nil # User set value to nil elsif option.string? && !option.required? # Return the default if there is one, else the human name return option.lazy_default || option.default || option.human_name elsif option.lazy_default return option.lazy_default else raise MalformattedArgumentError, "No value provided for option '#{switch}'" end end @non_assigned_required.delete(option) send(:"parse_#{option.type}", switch) end |
#parsing_options? ⇒ Boolean (protected)
283 284 285 286 |
# File 'lib/thor/parser/options.rb', line 283 def peek end |
#peek ⇒ Object
This *used to* remove ‘–` separators (what OPTS_END is), but that was problematic with multiple nested subcommands ’cause Thor classes further down the chain wouldn’t know that it was there and would parse options that had been after it.
Maybe that’s how Thor was supposed to work (???), but it didn’t really jive with me… I’ve always felt like stuff after ‘–` meant **_stop parsing options - these are always args_** since I usually see it used when passing shell commands to other shell commands - which is how I was using it when I came across the issues.
And it ain’t like Thor has any documentation to straiten it out. Hell, this method had no doc when I showed up. The line that dropped the ‘–` has no comment. The Thor::Options class itself had no doc.
So, now it does mean that… ‘–` means “no option parsing after here”. For real.
What’s next?! I think.
127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/thor/parser/options.rb', line 127 def peek return super unless result = super if result == OPTS_END # Removed, see note above: # shift = false super else result end end |
#remaining ⇒ Object
Instance Methods
101 102 103 |
# File 'lib/thor/parser/options.rb', line 101 def remaining @extra end |
#switch?(arg) ⇒ Boolean (protected)
240 241 242 |
# File 'lib/thor/parser/options.rb', line 240 def switch?(arg) switch_option(normalize_switch(arg)) end |
#switch_option(arg) ⇒ Thor::Option? (protected)
Get the option for a switch arg.
Handles parsing ‘–no-<option>` and `–skip-<option>` styles as well.
258 259 260 261 262 263 264 |
# File 'lib/thor/parser/options.rb', line 258 def switch_option(arg) if match = no_or_skip?(arg) # rubocop:disable AssignmentInCondition @switches[arg] || @switches["--#{match}"] else @switches[arg] end end |