Class: RVC::OptionParser

Inherits:
Trollop::Parser
  • Object
show all
Defined in:
lib/rvc/option_parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cmd, &b) ⇒ OptionParser

Returns a new instance of OptionParser.



28
29
30
31
32
33
34
35
36
37
# File 'lib/rvc/option_parser.rb', line 28

def initialize cmd, &b
  @cmd = cmd
  @summary = nil
  @args = []
  @has_options = false
  @seen_not_required = false
  @seen_multi = false
  @applicable = Set.new
  super &b
end

Instance Attribute Details

#applicableObject (readonly)

Returns the value of attribute applicable.



26
27
28
# File 'lib/rvc/option_parser.rb', line 26

def applicable
  @applicable
end

Instance Method Details

#arg(name, description, spec = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rvc/option_parser.rb', line 58

def arg name, description, spec={}
  spec = {
    :description => description,
    :required => true,
    :default => nil,
    :multi => false,
  }.merge spec
  spec[:default] = [] if spec[:multi] and spec[:default].nil?
  fail "Multi argument must be the last one" if @seen_multi
  fail "Can't have required argument after optional ones" if spec[:required] and @seen_not_required
  fail "lookup and lookup_parent are mutually exclusive" if spec[:lookup] and spec[:lookup_parent]
  [:lookup, :lookup_parent].each do |sym|
    if spec[sym].is_a? Enumerable
      spec[sym].each { |x| @applicable << x }
    elsif spec[sym]
      @applicable << spec[sym]
    end
  end
  @args << [name,spec]
  description = "Path to a" if description == nil and spec[:lookup]
  description = "Child of a" if description == nil and spec[:lookup_parent]
  lookups = [spec[:lookup], spec[:lookup_parent]].flatten.compact
  text "  #{name}: " + [description, lookups*' or '].compact.join(' ')
end

#educateObject



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/rvc/option_parser.rb', line 128

def educate
  arg_texts = @args.map do |name,spec|
    text = name
    text = "[#{text}]" if not spec[:required]
    text = "#{text}..." if spec[:multi]
    text
  end
  arg_texts.unshift "[opts]" if has_options?
  puts "usage: #{@cmd} #{arg_texts*' '}"
  super
end

#has_options?Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/rvc/option_parser.rb', line 54

def has_options?
  @has_options
end

#opt(name, *a) ⇒ Object



48
49
50
51
52
# File 'lib/rvc/option_parser.rb', line 48

def opt name, *a
  super
  @applicable << @specs[name][:lookup] if @specs[name][:lookup]
  @has_options = true unless name == :help
end

#parse(argv) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rvc/option_parser.rb', line 83

def parse argv
  opts = super argv

  @specs.each do |name,spec|
    next unless klass = spec[:lookup] and path = opts[name]
    opts[name] = RVC::Util.lookup_single! path, klass
  end

  argv = leftovers
  args = []
  @args.each do |name,spec|
    if spec[:multi]
      RVC::Util.err "missing argument '#{name}'" if spec[:required] and argv.empty?
      a = (argv.empty? ? spec[:default] : argv.dup)
      a = a.map { |x| postprocess_arg x, spec }.inject([], :+)
      RVC::Util.err "no matches for '#{name}'" if spec[:required] and a.empty?
      args << a
      argv.clear
    else
      x = argv.shift
      RVC::Util.err "missing argument '#{name}'" if spec[:required] and x.nil?
      x = spec[:default] if x.nil?
      a = x.nil? ? [] : postprocess_arg(x, spec)
      RVC::Util.err "more than one match for #{name}" if a.size > 1
      RVC::Util.err "no match for '#{name}'" if spec[:required] and a.empty?
      args << a.first
    end
  end
  RVC::Util.err "too many arguments" unless argv.empty?
  return args, opts
end

#postprocess_arg(x, spec) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rvc/option_parser.rb', line 115

def postprocess_arg x, spec
  if spec[:lookup]
    RVC::Util.lookup!(x, spec[:lookup]).
      tap { |a| RVC::Util.err "no matches for #{x.inspect}" if a.empty? }
  elsif spec[:lookup_parent]
    RVC::Util.lookup!(File.dirname(x), spec[:lookup_parent]).
      map { |y| [y, File.basename(x)] }.
      tap { |a| RVC::Util.err "no matches for #{File.dirname(x).inspect}" if a.empty? }
  else
    [x]
  end
end

#summary(str) ⇒ Object



39
40
41
42
# File 'lib/rvc/option_parser.rb', line 39

def summary str
  @summary = str
  text str
end

#summary?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/rvc/option_parser.rb', line 44

def summary?
  @summary
end