1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 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 71 72 73 74 75 76 77 78 79 80 81 82 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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
module Fission
class CommandLineParser
# Internal: Creates a new Fission::CommandLineParser object.
#
# args - The command line arguments to parse. This is expected to be in the
# same format of ARGV (Array) (default: ARGV).
#
# Examples:
#
# CommandLineParser.new ['foo', 'bar']
#
# CommandLineParser.new
#
# Returns a Fission::CommandLineParser object.
def initialize(args=ARGV)
@args = args
gather_commands_and_summaries
setup_options_parser
end
# Internal: Parses the command line arguments. If the arguments are
# invalid, the appropriate help will be output and then will exit. If the
# arguments are valid, then the @command variable will be set to a new
# instance of the determined command class.
#
# Examples:
#
# @command_line_parser.parse
#
# Returns nothing.
def parse
@options_parser.order! @args
determine_command_provided
self
rescue OptionParser::InvalidOption => e
ui.output e
show_all_help
exit 1
end
# Internal: Accessor for an instance of the determined command. This is set
# by running the parse method.
#
# Examples:
#
# @command_line_parser.command
#
# Returns an instance of the determined command if the arguments are valid.
# Returns nil if the parse command has not yet been run.
def command
@command
end
private
# Internal: Sets up the base option parser.
#
# Examples:
#
# @cli.setup_option_parser
#
# Returns nothing. This will set the @option_parser instance variable.
def setup_options_parser
@options_parser = OptionParser.new do |opts|
opts.banner = "\nUsage: fission [options] COMMAND [arguments]"
opts.on_head('-v', '--version', 'Output the version of fission') do
ui.output VERSION
exit 0
end
opts.on_head('-h', '--help', 'Displays this message') do
show_all_help
exit 0
end
end
end
# Internal: Provides the help of all of the known commands.
#
# Examples
#
# @cli.commands_help
#
# Outputs the summary text for all known commands.
def commands_help
longest_cmd = @commands.inject do |longest, cmd_name|
longest.length > cmd_name.length ? longest : cmd_name
end
ui.output "\nCommands:"
Hash[@command_names_and_summaries.sort].each_pair do |name, summary|
ui.output_printf "%-#{longest_cmd.length}s %s\n", name, summary
end
end
# Internal: Determines all of the available commands and their summaries.
#
# Examples
#
# @cli.command_names_and_summaries
# # => { 'clone' => 'Clones a VM', 'stop' => 'Stops a VM' }
#
# Returns nothing. This will set the @command_names_and_summaries instance
# variable with the result.
def gather_commands_and_summaries
@command_names_and_summaries = Command.descendants.inject({}) do |result, klass|
cmd = klass.new
result[cmd.command_name] = cmd.summary
result
end
@commands = @command_names_and_summaries.keys.sort
end
# Internal: Determines the command that has been provided. If it is
# determined that an invalid command is provided, then the help/usage will
# be displayed and it will exit.
#
# Examples:
#
# @cli.determine_command_to_execute
#
# Returns nothing. This will set the @command instance variable to an instance
# of the appropriate command class (assuming it is valid).
def determine_command_provided
if @commands.include? @args.first
@command = Command.const_get(@args.first.capitalize).new @args.drop 1
elsif is_snapshot_command?
klass = @args.take(2).map {|c| c.capitalize}.join('')
@command = Command.const_get(klass).new @args.drop 2
else
show_all_help
exit 1
end
end
# Internal: Determines if the provided command is a snapshot related
# command. This will use the @args instance variable to make the
# determination.
#
# Examples
#
# @cli.is_snapshot_command? ['foo', 'bar']
# # => false
#
# @cli.is_snapshot_command? ['snapshot', 'list']
# # => true
#
# Returns a Boolean of whether a snapshot command was given or not.
def is_snapshot_command?
@args.first == 'snapshot' &&
@args.count > 1 &&
@commands.include?(@args.take(2).join(' '))
end
# Internal: Outputs the usage as well as the known commands and their
# summaries.
#
# Examples
#
# @cli.show_all_help
# # => 'fission options command arguments ....'
#
# Returns nothing.
def show_all_help
ui.output @options_parser
commands_help
end
# Internal: Helper method for outputting text to the ui
#
# Examples
#
# @cli.ui.output 'foo'
#
# Returns a UI instance.
def ui
@ui ||= UI.new
end
end
end
|