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, fs, &b) ⇒ OptionParser

Returns a new instance of OptionParser.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rvc/option_parser.rb', line 36

def initialize cmd, fs, &b
  @cmd = cmd
  @fs = fs
  @summary = nil
  @args = []
  @has_options = false
  @seen_not_required = false
  @seen_multi = false
  @applicable = Set.new
  super() do
    instance_eval &b
    opt :help, "Show this message", :short => 'h'
  end
end

Instance Attribute Details

#applicableObject (readonly)

Returns the value of attribute applicable.



34
35
36
# File 'lib/rvc/option_parser.rb', line 34

def applicable
  @applicable
end

Instance Method Details

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



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/rvc/option_parser.rb', line 72

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



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/rvc/option_parser.rb', line 152

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)


68
69
70
# File 'lib/rvc/option_parser.rb', line 68

def has_options?
  @has_options
end

#opt(name, *a) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/rvc/option_parser.rb', line 60

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

#parse(argv) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/rvc/option_parser.rb', line 97

def parse argv
  opts = super argv

  @specs.each do |name,spec|
    next unless klass = spec[:lookup] and path = opts[name]
    opts[name] = @fs.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

#parse_date_parameter(param, arg) ⇒ Object



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

def parse_date_parameter param, arg
  if RVC::HAVE_CHRONIC
    Chronic.parse(param)
  else
    Time.parse param
  end
rescue
  raise ::Trollop::CommandlineError, "option '#{arg}' needs a time"
end

#postprocess_arg(x, spec) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/rvc/option_parser.rb', line 139

def postprocess_arg x, spec
  if spec[:lookup]
    @fs.lookup!(x, spec[:lookup]).
      tap { |a| RVC::Util.err "no matches for #{x.inspect}" if a.empty? }
  elsif spec[:lookup_parent]
    @fs.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



51
52
53
54
# File 'lib/rvc/option_parser.rb', line 51

def summary str
  @summary = str
  text str
end

#summary?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/rvc/option_parser.rb', line 56

def summary?
  @summary
end