Class: Clive::Arguments

Inherits:
Array
  • Object
show all
Defined in:
lib/clive/arguments.rb,
lib/clive/arguments/parser.rb

Overview

An Array of Argument instances.

Defined Under Namespace

Classes: Parser

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create(opts) ⇒ Object

Examples:


ArgumentList.create :args => '<a> [<b>]', :as => [Integer, String]
#=> #<ArgumentList ...>


10
11
12
# File 'lib/clive/arguments.rb', line 10

def self.create(opts)
  new Parser.new(opts).to_args
end

Instance Method Details

#[](idx) ⇒ Object

If the last item is infinite returns that item for any indexes greater than the actual length of the Arguments list.

Parameters:

  • idx (Integer)

    Index of item to return



93
94
95
96
97
98
99
# File 'lib/clive/arguments.rb', line 93

def [](idx)
  if size <= idx && idx < max
    last
  else
    super
  end
end

#create_valid(list) ⇒ Array

Will fill spaces in list with default values, then coerces all arguments to the correct types.

Returns:

  • (Array)


157
158
159
160
161
162
163
164
165
# File 'lib/clive/arguments.rb', line 157

def create_valid(list)
  zip(list).map do |a,r| 
    if a.infinite?
      r.map {|i| r ? a.coerce(i) : a.coerce(i.default) }
    else
      r ? a.coerce(r) : a.coerce(a.default) 
    end
  end
end

#maxInteger

Returns The maximum number of arguments that can be given.

Returns:

  • (Integer)

    The maximum number of arguments that can be given.



81
82
83
84
85
86
87
# File 'lib/clive/arguments.rb', line 81

def max
  if last && last.infinite?
    1.0/0.0
  else
    size
  end
end

#minInteger

Returns The minimum number of arguments that must be given.

Returns:

  • (Integer)

    The minimum number of arguments that must be given.



76
77
78
# File 'lib/clive/arguments.rb', line 76

def min
  reject {|i| i.optional? }.size
end

#possible?(list) ⇒ Boolean

Whether the list of found arguments could possibly be the arguments for this option. This does not need to check the minimum length as the list may not be completely built, this just checks it hasn’t failed completely.

Parameters:

  • list (Array<Object>)

Returns:

  • (Boolean)


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/clive/arguments.rb', line 106

def possible?(list)
  return true if list.empty?
  i = 0
  optionals = []

  list.each do |item|
    break if i >= max

    # Either, +item+ is self[i]
    if self[i].possible?(item)
      i += 1

    # Or, the argument is optional and there is another argument to move to
    # meaning it can be skipped
    elsif self[i].optional? && (i < max - 1)
      i += 1
      optionals << item

    # Or, an optional argument has been skipped and this could be it so bring
    # it back from the dead and check, if it is remove it and move on
    elsif optionals.size > 0 && self[i].possible?(optionals.first)
      i += 1
      optionals.shift

    # Problem
    else
      return false
    end
  end

  list.size <= max
end

#to_sString

Returns:



71
72
73
# File 'lib/clive/arguments.rb', line 71

def to_s
  map {|i| i.to_s }.join(' ').gsub('] [', ' ')
end

#valid?(list) ⇒ Boolean

Whether the list of found arguments is valid to be the arguments for this option. Here length is checked as we need to make sure enough arguments are present.

It is important that when the arguments are put in the correct place that we check for missing arguments (which have been added as nils) so compact the list then check the size.

Parameters:

  • list (Array<Object>)

Returns:

  • (Boolean)


148
149
150
151
# File 'lib/clive/arguments.rb', line 148

def valid?(list)
  l = zip(list).map {|a,i| a.optional? ? nil : i }
  l.flatten.compact.size >= min && possible?(list)
end

#zip(other) ⇒ Array<Argument,String>

Zips a list of found arguments to this ArgumentList, but it also takes account of whether the found argument is possible and makes sure that optional Arguments are correctly handled.

Examples:


a = Argument.new(:a, type: Integer, constraint: :even?, optional: true)
b = Argument.new(:b, type: Integer, constraint: :odd?)
c = Argument.new(:c, type: Integer, constraint: :even?)
d = Argument.new(:d, type: Integer, constraint: :odd?, optional: true)

list = ArgumentList.new([a, b, c, d])
found_args = %w(1 2 3)

list.zip(found_args).map {|i| [i[0].to_s, i[1]] }
#=> [['[<a>]', nil], ['<b>', 1], ['<c>', 2], ['[<d>]', 3]]

Parameters:

  • other (Array<String>)

    Found list of arguments.

Returns:



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/clive/arguments.rb', line 35

def zip(other)
  other = other.dup.compact
  # Find the number of 'spares'
  diff = other.size - find_all {|i| !i.optional? }.size

  r = map do |arg|
    if arg.possible?(other.first)
      if arg.optional?
        if diff > 0
          [arg, other.shift]
        else
          [arg, nil]
        end
      else
        [arg, other.shift]
      end
    else
      [arg, nil]
    end
  end
  
  # If last arg is infinite may still have some left over so add now
  if other != [] && last.respond_to?(:infinite?) && last.infinite?
    r += other.map {|i| [last, i] }
  end
  
  if last.respond_to?(:infinite?) && last.infinite?
    infinites = []
    r = r.reject! {|i| i.first.infinite? ? infinites << i : false }
    r << [infinites[0].first, infinites.map {|i| i.last }]
  end

  r
end