Class: Ing::Task

Inherits:
Object
  • Object
show all
Defined in:
lib/ing/task.rb

Overview

A base class to simplify typical task use-cases. Adds some class methods and state to allow inherited options/flexibly- ordered option specification. Note that options are inherited to subclasses, but description and usage lines are not.

Direct Known Subclasses

Generator

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Task

Returns a new instance of Task.



130
131
132
# File 'lib/ing/task.rb', line 130

def initialize(options)
  self.options = initial_options(options)
end

Class Attribute Details

.inherited_optionsObject



15
# File 'lib/ing/task.rb', line 15

def inherited_options; @inherited_options ||= {}; end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



129
130
131
# File 'lib/ing/task.rb', line 129

def options
  @options
end

#shellObject

Returns the value of attribute shell.



129
130
131
# File 'lib/ing/task.rb', line 129

def shell
  @shell
end

Class Method Details

.all_optionsObject

Options merged into inherited options.



117
118
119
# File 'lib/ing/task.rb', line 117

def all_options
  (inherited_options || {}).merge(options)
end

.default(name, val) ⇒ Object

Modify the default for option name to val. Option will be created if it doesn’t exist.



51
52
53
# File 'lib/ing/task.rb', line 51

def default(name, val)
  modify_option name, {:default => val}
end

.desc(line = "") ⇒ Object Also known as: description

Add a description line



56
57
58
# File 'lib/ing/task.rb', line 56

def desc(line="")
  desc_lines << line
end

.desc_linesObject

Description lines



101
102
103
# File 'lib/ing/task.rb', line 101

def desc_lines
  @desc_lines ||= []
end

.inherited(subclass) ⇒ Object

On subclassing, deep copy the merge of current options into inherited options



19
20
21
# File 'lib/ing/task.rb', line 19

def inherited(subclass)
  subclass.inherited_options = Marshal.load(Marshal.dump(self.all_options))
end

.inherited_option?(name) ⇒ Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/ing/task.rb', line 23

def inherited_option?(name)
  inherited_options.has_key?(name)
end

.modify_option(name, specs) ⇒ Object

Modify the option named name according to specs (Hash). Option will be created if it doesn’t exist.

Example:

modify_option :file, :required => true


38
39
40
41
42
43
44
45
46
# File 'lib/ing/task.rb', line 38

def modify_option(name, specs)
  if inherited_option?(name)
    inherited_options[name].opts.merge!(specs)
  elsif option?(name)
    options[name].opts.merge!(specs)
  else
    opt(name, '', specs)
  end
end

.opt(name, desc = "", settings = {}) ⇒ Object Also known as: option

Add an option. Note the syntax is identical to Trollop::Parser#opt



67
68
69
# File 'lib/ing/task.rb', line 67

def opt(name, desc="", settings={})
  options[name] = Option.new(name, desc, settings)
end

.option?(name) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/ing/task.rb', line 27

def option?(name)
  options.has_key?(name)
end

.optionsObject

Options hash. Note that in a subclass, options are copied down from superclass into inherited_options.



112
113
114
# File 'lib/ing/task.rb', line 112

def options
  @options ||= {}
end

.specify_options(parser) ⇒ Object

Build option parser based on desc, usage, and options (including inherited options). This method is called by ‘Ing::Command`. Note that this assumes the syntax of the Trollop parser.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/ing/task.rb', line 76

def specify_options(parser)
  desc_lines.each do |line|
    parser.text line
  end
  unless usage_lines.empty?
    parser.text "\nUsage:"
    usage_lines.each do |line|
      parser.text line
    end
  end
  unless options.empty?
    parser.text "\nOptions:"
    options.each do |name, opt|
      parser.opt *opt.to_args
    end
  end
  unless inherited_options.empty?
    parser.text "\nCommon Options:"
    inherited_options.each do |name, opt|
      parser.opt *opt.to_args
    end
  end
end

.usage(line = "") ⇒ Object

Add a usage line



62
63
64
# File 'lib/ing/task.rb', line 62

def usage(line="")
  usage_lines << line
end

.usage_linesObject

Usage lines



106
107
108
# File 'lib/ing/task.rb', line 106

def usage_lines
  @usage_lines ||= []
end

Instance Method Details

#ask_unless_given(*opts) ⇒ Object

Build a hash of options that weren’t given from command line via ask (i.e., $stdin.gets).

Note it currently does not cast options to appropriate types. Also note because the shell is not available until after initialization, this must be called from command method(s), e.g. #call



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ing/task.rb', line 146

def ask_unless_given(*opts)
  opts.inject({}) do |memo, opt|
    raise ArgumentError, "No option `#{opt}` for `#{self.class}`" \
      unless self.class.all_options.has_key?(opt)
    next memo if options[:"#{opt}_given"]
    msg = self.class.all_options[opt].desc + "?"
    df  = self.class.all_options[opt].default
    memo[opt] = shell.ask(msg, :default => df)
    memo
  end
end

#ask_unless_given!(*opts) ⇒ Object

Shortcut for:

options.merge! ask_unless_given :opt1, :opt2


162
163
164
# File 'lib/ing/task.rb', line 162

def ask_unless_given!(*opts)
  self.options.merge! ask_unless_given(*opts)
end

#initial_options(given) ⇒ Object

Override in subclass for adjusting given options on initialization



135
136
137
# File 'lib/ing/task.rb', line 135

def initial_options(given)
  given
end

#validate_option(opt, desc = opt, msg = nil) ⇒ Object

Use in initialization for option validation (post-parsing).

Example:

validate_option(:color, "Color must be :black or :white") do |actual|
  [:black, :white].include?(actual)
end


174
175
176
177
# File 'lib/ing/task.rb', line 174

def validate_option(opt, desc=opt, msg=nil)
  msg ||= "Error in option #{desc} for `#{self.class}`."
  !!yield(self.options[opt]) or raise ArgumentError, msg
end

#validate_option_exists(opt, desc = opt) ⇒ Object

Validate that the option was passed or otherwise defaulted to something truthy. Note that in most cases, instead you should set :required => true on the option and let Trollop catch the error – rather than catching it post-parsing.

Note validate_option_exists will raise an error if the option is passed but false or nil, unlike the Trollop parser.



186
187
188
189
190
191
# File 'lib/ing/task.rb', line 186

def validate_option_exists(opt, desc=opt)
  msg = "No #{desc} specified for #{self.class}. You must either " +
        "specify a `--#{opt}` option or set a default in #{self.class} or " +
        "in its superclass(es)."
  validate_option(opt, desc, msg) {|val| val }
end