Class: UserChoices::ChoicesBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/user-choices/builder.rb

Overview

This class accepts a series of source and choice descriptions and then builds a hash-like object that describes all the choices a user has made before (or while) invoking a script.

Instance Method Summary collapse

Constructor Details

#initializeChoicesBuilder

Returns a new instance of ChoicesBuilder.



15
16
17
18
19
# File 'lib/user-choices/builder.rb', line 15

def initialize
  @defaults = {}
  @conversions = {}
  @sources = []
end

Instance Method Details

#add_choice(choice, args = {}, &block) ⇒ Object

Add the choice named choice, a symbol. args is a keyword argument:

  • :default takes a value that is the default value of the choice.
  • :type can be given an array of valid string values. These are checked.
  • :type can also be given :integer. The value is cast into an integer. If that's impossible, an exception is raised.
  • :type can also be given :boolean. The value is converted into true or false (or an exception is raised).
  • :type can also be given [:string]. The value will be an array of strings. For example, "--value a,b,c" will produce ['a', 'b', 'c'].

You might also give :length => 5 or :length => 3..4. (In this case, a :type of [:string] is assumed.)

The block is passed a CommandLineSource object. It's used to describe the command line.



39
40
41
42
43
44
45
46
47
48
# File 'lib/user-choices/builder.rb', line 39

def add_choice(choice, args={}, &block)
  # TODO: does the has_key? actually make a difference?
  @defaults[choice] = args[:default] if args.has_key?(:default)
  @conversions[choice] = []
  Conversion.record_for(args[:type], @conversions[choice])
  if args.has_key?(:length)
    Conversion.record_for({:length => args[:length]}, @conversions[choice])
  end
  block.call(ArgForwarder.new(@command_line_source, choice)) if block
end

#add_help_line(string) ⇒ Object

Add a single line composed of string to the current position in the help output.



62
63
64
65
66
67
# File 'lib/user-choices/builder.rb', line 62

def add_help_line(string)
  user_claims(@command_line_source) {
    "Can't use 'add_help_string' when there's no command line source."
  }
  @command_line_source.add_help_line(string)
end

#add_source(source_class, *messages_and_args) ⇒ Object

This adds a source of choices. The source is a class like CommandLineSource. The messages_and_args are sent to a new object of that class.



53
54
55
56
57
58
# File 'lib/user-choices/builder.rb', line 53

def add_source(source_class, *messages_and_args)
  source = source_class.new
  message_sends(messages_and_args).each { | send_me | source.send(*send_me) }
  @sources << source
  @command_line_source = source if source_class <= CommandLineSource
end

#buildObject

Once sources and choices have been described, this builds and returns a hash-like object indexed by the choices.



91
92
93
94
95
96
97
98
99
# File 'lib/user-choices/builder.rb', line 91

def build
  retval = {}
  @sources << DefaultSource.new.use_hash(@defaults)
  @sources.each { |s| s.fill }
  @sources.each { |s| s.apply(@conversions) }
  @sources.reverse.each { |s| retval.merge!(s) }
  @sources.each { |s| s.adjust(retval) }
  retval
end

#message_sends(messages_and_args) ⇒ Object

Public for testing.



103
104
105
106
107
108
109
# File 'lib/user-choices/builder.rb', line 103

def message_sends(messages_and_args)  # :nodoc: 
  where_at = symbol_indices(messages_and_args)
  where_end = where_at[1..-1] + [messages_and_args.length]
  where_at.to_enum(:each_with_index).collect do |start, where_end_index |
    messages_and_args[start...where_end[where_end_index]]
  end
end

#section(description) ⇒ Object

Demarcate a section of help text. It begins with the description, ends with a dashed line.



71
72
73
74
75
76
# File 'lib/user-choices/builder.rb', line 71

def section(description)
  add_help_line("... " + description + ":")
  yield
  add_help_line("---------------------------------")
  add_help_line('')
end

#section_specific_to_scriptObject

In groups of related commands, there are often choices that apply to all commands and choices that apply only to this particular command. Use this to define the latter.



81
82
83
84
85
# File 'lib/user-choices/builder.rb', line 81

def section_specific_to_script
  section("specific to this script") do
    yield
  end
end

#symbol_indices(array) ⇒ Object

:nodoc:



111
112
113
114
115
# File 'lib/user-choices/builder.rb', line 111

def symbol_indices(array) # :nodoc: 
  array.to_enum(:each_with_index).collect do |obj, index|
    index if obj.is_a?(Symbol)
  end.compact
end