Permalink
Browse files

add pre/post/on_error and improved block handling

didn't need to be doing the whole action = Proc.new thing.
  • Loading branch information...
davetron5000 committed Feb 5, 2009
1 parent e045229 commit f9e53462848064befe3d41f64721609408087e91
Showing with 96 additions and 17 deletions.
  1. +17 −1 README.rdoc
  2. +17 −1 bin/gli
  3. +1 −1 gli.gemspec
  4. +41 −9 lib/gli.rb
  5. +4 −2 lib/gli/command.rb
  6. +1 −1 lib/support/scaffold.rb
  7. +14 −1 test/tc_command.rb
  8. +1 −1 test/tc_parsing.rb
View
@@ -57,14 +57,30 @@ Here we specify the actual actions to take when the command is executed. We def
will be given the global options (as a Hash), the command-specific options (as a hash) and the command
line arguments
- c.action = Proc.new do |g,o,args|
+ c.action do |global_options,options,args|
if args.length < 1
raise(MissingArgumentException,'You must specify the name of your project')
end
Scaffold.create_scaffold(g[:r],!o[:notest],o[:e],args[0],args[1..-1],o[:force],g[:n])
end
end
+You can also specify some global code to run before, after and on errors:
+
+ pre do |global_options,command,options,args|
+ puts "After parsing, but before #{command.name} is run"
+ end
+
+ post do |global_options,command,options,args|
+ puts "After successful execution of #{command.name}"
+ end
+
+ on_error do |global_options,command,options,args|
+ puts "We go an error"
+ return true # does the standard error handling code
+ # return false # this would skip standard error handling code
+ end
+
Now, we run the program using the arguments the user provided on the command line
run(ARGV)
View
18 bin/gli
@@ -5,6 +5,9 @@ require 'gli'
require 'support/scaffold'
include GLI
+desc 'Be verbose'
+switch :v
+
desc 'Dry run; don\'t change the disk'
switch :n
@@ -25,12 +28,25 @@ command [:init,:scaffold] do |c|
c.desc 'Overwrite/ignore existing files and directories'
c.switch [:force]
- c.action = Proc.new do |g,o,args|
+ c.action do |g,o,args|
if args.length < 1
raise(MissingArgumentException,'You must specify the name of your project')
end
Scaffold.create_scaffold(g[:r],!o[:notest],o[:e],args[0],args[1..-1],o[:force],g[:n])
end
end
+pre do |global,command,options,args|
+ puts "Executing #{command.name}" if global[:v]
+end
+
+post do |global,command,options,args|
+ puts "Executed #{command.name}" if global[:v]
+end
+
+on_error do |global,command,options,args|
+ puts "Got an error" if global[:v]
+ true
+end
+
run(ARGV)
View
@@ -1,6 +1,6 @@
spec = Gem::Specification.new do |s|
s.name = 'gli'
- s.version = '0.1.1'
+ s.version = '0.1.2'
s.author = 'David Copeland'
s.email = 'davidcopeland@naildrivin5.com'
s.homepage = 'http://davetron5000.github.com/gli'
View
@@ -11,6 +11,9 @@ module GLI
extend self
@@program_name = $0.split(/\//)[-1]
+ @@post_block = nil
+ @@pre_block = nil
+ @@error_block = nil
# Reset the GLI module internal data structures; mostly for testing
def reset
@@ -49,21 +52,48 @@ def command(names)
clear_nexts
end
+ # Define a block to run after command line arguments are parsed
+ # but before any command is run. If this block raises an exception
+ # the command specified will not be executed.
+ # The block will receive the global-options,command,options, and arguments
+ def pre(&a_proc)
+ @@pre_block = a_proc
+ end
+
+ # Define a block to run after command hase been executed, only
+ # if there was not an error.
+ # The block will receive the global-options,command,options, and arguments
+ def post(&a_proc)
+ @@post_block = a_proc
+ end
+
+ # Define a block to run if an error occurs.
+ # The block will receive the global-options,command,options, and arguments
+ def on_error(&a_proc)
+ @@error_block = a_proc
+ end
+
# Runs whatever command is needed based on the arguments.
def run(args)
commands[:help] = DefaultHelpCommand.new if !commands[:help]
begin
global_options,command,options,arguments = parse_options(args)
- if command
- command.execute(global_options,options,arguments)
- else
- raise UnknownCommandException
- end
+ @@pre_block.call(global_options,command,options,arguments) if @@pre_block
+ command = commands[:help] if !command
+ command.execute(global_options,options,arguments)
+ @@post_block.call(global_options,command,options,arguments) if @@post_block
rescue UnknownCommandException, UnknownArgumentException, MissingArgumentException => ex
- puts "error: #{ex}"
- puts
- help = commands[:help]
- help.execute({},{},[])
+ regular_error_handling = true
+ if @@error_block
+ regular_error_handling = @@error_block.call(global_options,command,options,arguments,ex)
+ end
+
+ if regular_error_handling
+ puts "error: #{ex}"
+ puts
+ help = commands[:help]
+ help.execute({},{},[])
+ end
end
end
@@ -216,12 +246,14 @@ def find_command(name)
nil
end
+ # Raise this if you get an argument you were not expecting
class UnknownArgumentException < Exception
end
class UnknownCommandException < Exception
end
+ # Raise this if your command doesn't get the number of arguments you were expecting
class MissingArgumentException < Exception
end
end
View
@@ -4,8 +4,6 @@ module GLI
# A command to be run, in context of global flags and switches
class Command < CommandLineToken
- attr_writer :action
-
# Create a new command
#
# [names] the name or names of this command (symbol or Array of symbols)
@@ -52,6 +50,10 @@ def switch(names)
clear_nexts
end
+ def action(&block)
+ @action = block
+ end
+
def self.name_as_string(name)
name.to_s
end
View
@@ -49,7 +49,7 @@ def self.mk_binfile(root_dir,create_ext_dir,force,dry_run,project_name,commands)
c.default_value 'default'
c.flag :s
- c.action = Proc.new do |global_options,options,args|
+ c.action do |global_options,options,args|
# Your command logic here
end
end
View
@@ -11,6 +11,12 @@ def setup
GLI.switch :g
GLI.switch :blah
GLI.flag [:y,:yes]
+ @pre_called = false
+ @post_called = false
+ @error_called = false
+ GLI.pre { |g,c,o,a| @pre_called = true }
+ GLI.post { |g,c,o,a| @post_called = true }
+ GLI.on_error { |g,c,o,a| @error_called = true }
@glob = nil
@verbose = nil
@glob_verbose = nil
@@ -24,7 +30,7 @@ def setup
c.desc 'configure something or other, in some way that requires a lot of verbose text and whatnot'
c.default_value 'crud'
c.flag [:c,:configure]
- c.action = Proc.new do |global_options,options,arguments|
+ c.action do |global_options,options,arguments|
@glob = global_options[:g] ? 'true' : 'false'
@verbose = options[:v] ? 'true' : 'false'
@glob_verbose = global_options[:v] ? 'true' : 'false'
@@ -43,6 +49,9 @@ def test_basic_command
assert_equal('false',@glob_verbose)
assert_equal('foo',@configure)
assert_equal(%w(bar baz quux),@args)
+ assert(@pre_called)
+ assert(@post_called)
+ assert(!@error_called)
end
end
@@ -73,6 +82,8 @@ def test_no_arguments
def test_unknown_command
args = %w(blah -v)
GLI.run(args)
+ assert(!@post_called)
+ assert(@error_called)
end
def test_help
@@ -81,8 +92,10 @@ def test_help
end
def test_help_no_command
+ GLI.program_name 'cruddo'
args = %w(help foo)
GLI.run(args)
+ assert_equal('cruddo',GLI.program_name)
end
def test_command_create
View
@@ -176,7 +176,7 @@ def test_case_that_busted
c.switch :v
c.desc 'configure something'
c.flag [:c,:configure]
- c.action = Proc.new do |global_options,options,arguments|
+ c.action do |global_options,options,arguments|
glob = global_options[:g] ? 'true' : 'false'
verbose = options[:v] ? 'true' : 'false'
glob_verbose = global_options[:v] ? 'true' : 'false'

0 comments on commit f9e5346

Please sign in to comment.