lib/cmdparse.rb in cmdparse-2.0.1 vs lib/cmdparse.rb in cmdparse-2.0.2

- old
+ new

@@ -1,9 +1,9 @@ # #-- # -# $Id: cmdparse.rb 398 2006-04-05 14:13:43Z thomas $ +# $Id: cmdparse.rb 416 2006-06-17 19:32:55Z thomas $ # # cmdparse: advanced command line parser supporting commands # Copyright (C) 2004 Thomas Leitner # # This program is free software; you can redistribute it and/or modify it under the terms of the GNU @@ -23,11 +23,11 @@ # Namespace module for cmdparse. module CmdParse # The version of this cmdparse implemention - VERSION = [2, 0, 1] + VERSION = [2, 0, 2] # Base class for all cmdparse errors. class ParseError < RuntimeError @@ -101,11 +101,23 @@ end # Require default option parser wrapper require 'cmdparse/wrappers/optparse' + # Command Hash - will return partial key matches as well if there is a single + # non-ambigous matching key + class CommandHash < Hash + def []( cmd_name ) + super or begin + possible = keys.select {|key| key =~ /^#{cmd_name}.*/ } + fetch( possible[0] ) if possible.size == 1 + end + end + + end + # Base class for the commands. This class implements all needed methods so that it can be used by # the +CommandParser+ class. class Command # The name of the command @@ -129,19 +141,27 @@ # Returns the list of commands for this command. attr_reader :commands # Initializes the command called +name+. The parameter +has_commands+ specifies if this command - # takes other commands as argument. - def initialize( name, has_commands ) + # takes other commands as argument. The optional argument +partial_commands+ specifies, if + # partial command matching should be used. + def initialize( name, has_commands, partial_commands = false ) @name = name @options = ParserWrapper.new @has_commands = has_commands - @commands = {} + @commands = Hash.new @default_command = nil + use_partial_commands( partial_commands ) end + def use_partial_commands( use_partial ) + temp = ( use_partial ? CommandHash.new : Hash.new ) + temp.update( @commands ) + @commands = temp + end + # Returns +true+ if this command supports sub commands. def has_commands? @has_commands end @@ -270,11 +290,11 @@ def execute( args ) if args.length > 0 cmd = commandparser.main_command arg = args.shift - while !arg.nil? && cmd.commands.keys.include?( arg ) + while !arg.nil? && cmd.commands[ arg ] cmd = cmd.commands[arg] arg = args.shift end if arg.nil? cmd.show_help @@ -290,10 +310,11 @@ ####### private ####### def show_program_help + puts commandparser.banner + "\n" if commandparser.banner puts "Usage: #{commandparser.program_name} [options] COMMAND [options] [COMMAND [options] ...] [args]" puts "" list_commands( 1, commandparser.main_command ) puts "" puts commandparser.main_command.options.summarize @@ -329,20 +350,24 @@ end def execute( args ) version = commandparser.program_version version = version.join( '.' ) if version.instance_of?( Array ) + puts commandparser.banner + "\n" if commandparser.banner puts version exit end end # The main class for creating a command based CLI program. class CommandParser + # A standard banner for help & version screens + attr_accessor :banner + # The top level command representing the program itself. attr_reader :main_command # The name of the program. attr_accessor :program_name @@ -352,14 +377,16 @@ # Are Exceptions be handled gracefully? I.e. by printing error message and the help screen? attr_reader :handle_exceptions # Create a new CommandParser object. The optional argument +handleExceptions+ specifies if the - # object should handle exceptions gracefully. - def initialize( handleExceptions = false ) + # object should handle exceptions gracefully. Set +partial_commands+ to +true+, if you want + # partial command matching for the top level commands. + def initialize( handleExceptions = false, partial_commands = false ) @main_command = Command.new( 'mainCommand', true ) @main_command.super_command = self + @main_command.use_partial_commands( partial_commands ) @program_name = $0 @program_version = "0.0.0" @handle_exceptions = handleExceptions end @@ -400,10 +427,10 @@ raise NoCommandGivenError else cmdName = command.default_command end else - raise InvalidCommandError.new( cmdName ) unless command.commands.include?( cmdName ) + raise InvalidCommandError.new( cmdName ) unless command.commands[ cmdName ] end command = command.commands[cmdName] level += 1 else