Class: Hiiro::Options::Args

Inherits:
Object
  • Object
show all
Defined in:
lib/hiiro/options.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(definitions, raw_args, mutex_groups: []) ⇒ Args

Returns a new instance of Args.



109
110
111
112
113
114
115
116
# File 'lib/hiiro/options.rb', line 109

def initialize(definitions, raw_args, mutex_groups: [])
  @definitions = definitions
  @mutex_groups = mutex_groups
  @original_args = raw_args.dup.freeze
  @values = {}
  @remaining_args = []
  do_parse(raw_args.dup)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



153
154
155
156
157
158
159
160
161
162
# File 'lib/hiiro/options.rb', line 153

def method_missing(name, *args, &block)
  name_str = name.to_s
  if name_str.end_with?('?')
    key = name_str.chomp('?').to_sym
    return !!@values[key] if @definitions.key?(key)
  else
    return @values[name] if @definitions.key?(name)
  end
  super
end

Instance Attribute Details

#original_argsObject (readonly)

Returns the value of attribute original_args.



106
107
108
# File 'lib/hiiro/options.rb', line 106

def original_args
  @original_args
end

#remaining_argsObject (readonly) Also known as: args

Returns the value of attribute remaining_args.



106
107
108
# File 'lib/hiiro/options.rb', line 106

def remaining_args
  @remaining_args
end

Instance Method Details

#[](name) ⇒ Object



118
119
120
# File 'lib/hiiro/options.rb', line 118

def [](name)
  @values[name.to_sym]
end

#do_parse(args) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/hiiro/options.rb', line 169

def do_parse(args)
  @definitions.each do |name, defn|
    @values[name] = defn.multi ? [] : defn.default
  end

  while args.any?
    arg = args.shift

    if arg == '--'
      @remaining_args.concat(args)
      break
    elsif arg.start_with?('--')
      parse_long_option(arg, args)
    elsif arg.start_with?('-') && arg.length > 1
      parse_short_options(arg, args)
    else
      @remaining_args << arg
    end
  end
end

#fetch(name, default = nil) ⇒ Object



122
123
124
125
126
127
# File 'lib/hiiro/options.rb', line 122

def fetch(name, default = nil)
  key = name.to_sym
  return @values[key] if @values.key?(key)
  return yield if block_given?
  default
end

#help?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/hiiro/options.rb', line 135

def help?
  @values[:help]
end

#help_textObject



139
140
141
142
143
144
145
146
147
# File 'lib/hiiro/options.rb', line 139

def help_text
  lines = []
  @definitions.each do |name, defn|
    next if name == :help
    lines << defn.usage_line
  end
  lines << @definitions[:help].usage_line
  lines.join("\n")
end

#parse_long_option(arg, args) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/hiiro/options.rb', line 190

def parse_long_option(arg, args)
  parts     = arg.split('=', 2)
  flag_part = parts[0]
  value     = parts[1]

  defn = @definitions.values.find { |d| d.long_form == flag_part }
  return unless defn

  if defn.flag? || defn.flag_active?(@values)
    set_flag(defn, !defn.default)
  else
    value ||= args.shift
    store_value(defn, value)
  end
end

#parse_short_options(arg, args) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/hiiro/options.rb', line 206

def parse_short_options(arg, args)
  chars = arg.sub(/^-/, '').chars

  unless chars.any? { |c| @definitions.values.find { |d| d.short == c } }
    @remaining_args << arg
    return
  end

  chars.each_with_index do |char, idx|
    defn = @definitions.values.find { |d| d.short == char }
    next unless defn

    if defn.flag? || defn.flag_active?(@values)
      set_flag(defn, !defn.default)
    elsif idx == chars.length - 1
      store_value(defn, args.shift)
    else
      store_value(defn, chars[(idx + 1)..].join)
      break
    end
  end
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


164
165
166
167
# File 'lib/hiiro/options.rb', line 164

def respond_to_missing?(name, include_private = false)
  key = name.to_s.chomp('?').to_sym
  @definitions.key?(key) || super
end

#set_flag(defn, value) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/hiiro/options.rb', line 229

def set_flag(defn, value)
  # Star topology: group[0] is the hub.
  #   Setting the hub   → clears all spokes (group[1..])
  #   Setting a spoke   → clears only the hub (group[0])
  # This lets spokes coexist with each other (e.g. --red --drafts is fine)
  # while still preventing any spoke from combining with the hub (--all).
  @mutex_groups.each do |group|
    next unless group.include?(defn.name)
    hub, *spokes = group
    if defn.name == hub
      spokes.each do |spoke|
        spoke_defn = @definitions[spoke]
        @values[spoke] = spoke_defn.default if spoke_defn
      end
    else
      hub_defn = @definitions[hub]
      @values[hub] = hub_defn.default if hub_defn
    end
  end
  @values[defn.name] = value
end

#store_value(defn, value) ⇒ Object



251
252
253
254
255
256
257
258
# File 'lib/hiiro/options.rb', line 251

def store_value(defn, value)
  coerced = defn.coerce(value)
  if defn.multi
    @values[defn.name] << coerced
  else
    @values[defn.name] = coerced
  end
end

#to_hObject



149
150
151
# File 'lib/hiiro/options.rb', line 149

def to_h
  @values.dup
end

#uses_option?(name) ⇒ Boolean

Returns:

  • (Boolean)


129
130
131
132
133
# File 'lib/hiiro/options.rb', line 129

def uses_option?(name)
  key = name.to_sym
  return false unless @definitions.key?(key)
  @values[key] != @definitions[key].default
end