Class: Consoler::Application

Inherits:
Object
  • Object
show all
Defined in:
lib/consoler/application.rb

Overview

Consoler application

Examples:

A simple application

# create a application
app = Consoler::Application.new description: 'A simple app'

# define a command
app.build 'target [--clean]' do |target, clean|
  # clean contains a boolean
  clean_up if clean

  # target contains a string
  build_project target
end
app.run(['build', 'production', '--clean'])

# this does not match, nothing is executed and the usage message is printed
app.run(['deploy', 'production'])

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Application

Create a consoler application

Options Hash (options):

  • :description (String)

    The description for the application (optional)


32
33
34
35
# File 'lib/consoler/application.rb', line 32

def initialize(options={})
  @description = options[:description]
  @commands = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(command_name, input = nil) {|...| ... } ⇒ nil

Register a command for this app

Yields:

  • (...)

    Executed when the action is matched with parameters based on your options


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
69
70
# File 'lib/consoler/application.rb', line 43

def method_missing(command_name, input = nil, &block)
  action = nil
  options_def = ''

  unless block.nil? then
    action = block
    options_def = input

    if not options_def.nil? and not options_def.instance_of? String then
      raise 'Invalid options'
    end
  end

  if input.instance_of? Consoler::Application then
    action = input
    options_def = ''
  end

  if action.nil? then
    raise 'Invalid subapp/block'
  end

  command = command_name.to_s

  _add_command(command, options_def, action)

  return nil
end

Instance Method Details

#_add_command(command, options_def, action) ⇒ Consoler::Application (private)

Add a command


167
168
169
170
171
172
173
174
175
# File 'lib/consoler/application.rb', line 167

def _add_command(command, options_def, action)
  @commands.push(Consoler::Command.new(
    command: command,
    options: Consoler::Options.new(options_def),
    action: action,
  ))

  self
end

#_commands_usage(prefix = '') ⇒ Consoler::Application (protected)

Print the usage message for this command


136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/consoler/application.rb', line 136

def _commands_usage(prefix='')
  @commands.each do |command|
    # print the usage message of a subapp with a prefix from the current command
    if command.action.instance_of? Consoler::Application then
      command.action._commands_usage "#{prefix} #{command.command}"
    else
      print "  #{prefix} #{command.command}"

      if command.options.size then
        print " #{command.options.to_definition}"
      end

      unless command.options.description.nil? then
        print "  -- #{command.options.description}"
      end

      print "\n"
    end
  end

  self
end

#_dispatch(action, match) ⇒ Object (private)

Execute an action with argument match info


181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/consoler/application.rb', line 181

def _dispatch(action, match)
  # match parameter names to indices of match information
  arguments = action.parameters.map do |parameter|
    parameter_name = parameter[1].to_s

    if match.has_key? parameter_name then
      match[parameter_name]
    else
      # check for the normalized name of every match to see
      # if it fits the parameter name
      match.each do |name, value|
        normalized_name = _normalize name

        if parameter_name == normalized_name then
          return value
        end
      end
    end
  end

  action.call(*arguments)
end

#_normalize(name) ⇒ String (private)

Normalize a name to be used as a variable name


208
209
210
211
212
213
214
215
216
# File 'lib/consoler/application.rb', line 208

def _normalize(name)
  # maybe do something more, maybe not.. ruby does allow for
  # some weird stuff to be used as a variable name. the user
  # should use some common sense. and, other things might
  # also be an syntax error, like starting with a number.
  # this normalization is more of a comvenience than anything
  # else
  name.gsub('-', '_')
end

#_run(args) ⇒ (mixed, Boolean) (protected)

Run the app


105
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
# File 'lib/consoler/application.rb', line 105

def _run(args)
  arg = args.shift
  arguments = Consoler::Arguments.new args

  @commands.each do |command|
    if command.command == arg then
      # the matched command contains a subapp, run subapp with the same
      # arguments (excluding the arg that matched this command)
      if command.action.instance_of? Consoler::Application then
        result, matched = command.action._run(args)

        if matched then
          return result, true
        end
      else
        match = arguments.match command.options

        next if match.nil?

        return _dispatch(command.action, match), true
      end
    end
  end

  return nil, false
end

#run(args = ARGV, disable_usage_message = false) ⇒ mixed

Run the application with a list of arguments


77
78
79
80
81
82
83
84
85
86
87
# File 'lib/consoler/application.rb', line 77

def run(args = ARGV, disable_usage_message = false)
  # TODO signal handling of some kind?

  result, matched = _run(args.dup)

  if not matched and not disable_usage_message
    usage
  end

  return result
end

#usageObject

Show the usage message

Contains all commands and options, including subapps


92
93
94
95
96
97
# File 'lib/consoler/application.rb', line 92

def usage
  puts "#{@description}\n\n" unless @description.nil?
  puts 'Usage:'

  _commands_usage $0
end