visionmedia-commander 2.5.7 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +30 -0
- data/Manifest +6 -5
- data/README.rdoc +7 -20
- data/Todo.rdoc +24 -19
- data/bin/commander +30 -29
- data/commander.gemspec +4 -4
- data/lib/commander.rb +3 -14
- data/lib/commander/command.rb +105 -120
- data/lib/commander/core_ext.rb +0 -1
- data/lib/commander/core_ext/array.rb +9 -4
- data/lib/commander/core_ext/object.rb +37 -2
- data/lib/commander/core_ext/string.rb +2 -14
- data/lib/commander/help_formatters.rb +4 -2
- data/lib/commander/help_formatters/base.rb +3 -23
- data/lib/commander/help_formatters/terminal.rb +1 -8
- data/lib/commander/help_formatters/terminal/command_help.erb +8 -8
- data/lib/commander/help_formatters/terminal/help.erb +4 -4
- data/lib/commander/runner.rb +83 -83
- data/lib/commander/user_interaction.rb +36 -42
- data/lib/commander/version.rb +1 -1
- data/spec/command_spec.rb +128 -0
- data/spec/core_ext/array_spec.rb +20 -0
- data/spec/{import_spec.rb → core_ext/object_spec.rb} +10 -3
- data/spec/help_formatter_spec.rb +15 -15
- data/spec/runner_spec.rb +168 -0
- data/spec/spec_helper.rb +19 -4
- metadata +8 -10
- data/lib/commander/core_ext/kernel.rb +0 -12
- data/lib/commander/fileutils.rb +0 -30
- data/lib/commander/import.rb +0 -31
- data/spec/commander_spec.rb +0 -241
data/History.rdoc
CHANGED
@@ -1,4 +1,34 @@
|
|
1
1
|
|
2
|
+
=== 3.0.0 / 2009-03-12
|
3
|
+
|
4
|
+
* Added sub command help support when using the --help switch
|
5
|
+
* #delete_switches is now mutative
|
6
|
+
* Added #valid_command_names_from
|
7
|
+
* #when_called now raises argument error when neither a block, object, or class is passed
|
8
|
+
* Added options#default method and specs
|
9
|
+
* Added support for multi-word list parsing in Array#parse
|
10
|
+
* Added summary to commander template
|
11
|
+
* Added optional block param for #new_command_runner spec helper
|
12
|
+
* Added .re (metadata for visionmedia-release gem)
|
13
|
+
* Moved delgation of Kernel methods to Object
|
14
|
+
* Refactored multi-word command name specs
|
15
|
+
* Refactored Object#method_missing; using call chain to implement
|
16
|
+
* Refactored all specs
|
17
|
+
* Change #color calls in formatters to $terminal#color for now
|
18
|
+
* Using highlines $terminal.output for IO stream with the progressbar
|
19
|
+
* Replaced #ensure_program_key_set with #require_program, taking an array of keys
|
20
|
+
* Renamed #args_without_command to #args_without_command_name
|
21
|
+
* Renamed #populate_options_to_when_called to #option_proc
|
22
|
+
* Renamed #sym_from_switch to #switch_to_sym
|
23
|
+
* Removed #get_command, use #command without supplying a block
|
24
|
+
* Removed Command#inspect
|
25
|
+
* Removed command description aliases of short_description, long_description. Use description / summary
|
26
|
+
* Removed VerboseFileUtils
|
27
|
+
* Removed String#camelcase as its not really needed (was only used in commander's executable for creating templates)
|
28
|
+
* Removed commander/import for now
|
29
|
+
* Removed LOG_FORMAT
|
30
|
+
* Removed Kernel ext which only had #color
|
31
|
+
|
2
32
|
=== 2.5.7 / 2009-03-11
|
3
33
|
|
4
34
|
* Fixed paren warnings in import spec
|
data/Manifest
CHANGED
@@ -3,17 +3,14 @@ commander.gemspec
|
|
3
3
|
History.rdoc
|
4
4
|
lib/commander/command.rb
|
5
5
|
lib/commander/core_ext/array.rb
|
6
|
-
lib/commander/core_ext/kernel.rb
|
7
6
|
lib/commander/core_ext/object.rb
|
8
7
|
lib/commander/core_ext/string.rb
|
9
8
|
lib/commander/core_ext.rb
|
10
|
-
lib/commander/fileutils.rb
|
11
9
|
lib/commander/help_formatters/base.rb
|
12
10
|
lib/commander/help_formatters/terminal/command_help.erb
|
13
11
|
lib/commander/help_formatters/terminal/help.erb
|
14
12
|
lib/commander/help_formatters/terminal.rb
|
15
13
|
lib/commander/help_formatters.rb
|
16
|
-
lib/commander/import.rb
|
17
14
|
lib/commander/runner.rb
|
18
15
|
lib/commander/user_interaction.rb
|
19
16
|
lib/commander/version.rb
|
@@ -21,12 +18,16 @@ lib/commander.rb
|
|
21
18
|
Manifest
|
22
19
|
Rakefile
|
23
20
|
README.rdoc
|
24
|
-
spec/
|
21
|
+
spec/command_spec.rb
|
22
|
+
spec/core_ext/array_spec.rb
|
23
|
+
spec/core_ext/object_spec.rb
|
25
24
|
spec/core_ext/string_spec.rb
|
26
25
|
spec/help_formatter_spec.rb
|
27
|
-
spec/
|
26
|
+
spec/runner_spec.rb
|
28
27
|
spec/spec_helper.rb
|
29
28
|
tasks/docs.rake
|
30
29
|
tasks/gemspec.rake
|
31
30
|
tasks/spec.rake
|
31
|
+
test/pbar
|
32
|
+
test/ui
|
32
33
|
Todo.rdoc
|
data/README.rdoc
CHANGED
@@ -6,7 +6,7 @@ Commander bridges the gap between other terminal related libraries
|
|
6
6
|
you know and love (OptionParser, HighLine), while providing many new
|
7
7
|
features, and an elegant API.
|
8
8
|
|
9
|
-
== Features
|
9
|
+
== Features
|
10
10
|
|
11
11
|
* Easier than baking cookies
|
12
12
|
* Parses options using OptionParser
|
@@ -18,7 +18,7 @@ features, and an elegant API.
|
|
18
18
|
* Multi-word command name support such as 'drupal module install MOD', rather than 'drupal module_install MOD'
|
19
19
|
* Use the 'commander' executable to initialize a commander driven program
|
20
20
|
|
21
|
-
== Example
|
21
|
+
== Example
|
22
22
|
|
23
23
|
For more option examples view the Commander::Command#option method. Also
|
24
24
|
an important feature to note is that when_called may be a class to instantiate,
|
@@ -48,7 +48,7 @@ as well as an object, specifying a method to call, so view the RDoc for more inf
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
== HighLine
|
51
|
+
== HighLine
|
52
52
|
|
53
53
|
As mentioned above the highline gem is imported into 'global scope', below
|
54
54
|
are some quick examples for how to utilize highline in your command(s):
|
@@ -101,7 +101,7 @@ are some quick examples for how to utilize highline in your command(s):
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
== HighLine & Interaction Additions
|
104
|
+
== HighLine & Interaction Additions
|
105
105
|
|
106
106
|
In addition to highline's fantastic choice of methods we will continue to
|
107
107
|
simplify common tasks using the following methods:
|
@@ -130,19 +130,6 @@ simplify common tasks using the following methods:
|
|
130
130
|
# 'Log' action to stdout
|
131
131
|
log "create", "path/to/file.rb"
|
132
132
|
|
133
|
-
== FileUtils:
|
134
|
-
|
135
|
-
The VerboseFileUtils module is automatically included within the main object for
|
136
|
-
global usage. These will output 'log' messages such as:
|
137
|
-
|
138
|
-
remove doc
|
139
|
-
create path
|
140
|
-
create path/to/file.rb
|
141
|
-
move path/to/something path/to/destination
|
142
|
-
|
143
|
-
If you do not wish to use FileUtils in a verbose manor simply call FileUtil's
|
144
|
-
methods directly.
|
145
|
-
|
146
133
|
== ASCII Tables
|
147
134
|
|
148
135
|
For feature rich ASCII tables for your terminal app check out visionmedia's terminal-table gem at
|
@@ -154,15 +141,15 @@ http://github.com/visionmedia/terminal-table
|
|
154
141
|
| | | | | get it while its hot! |
|
155
142
|
+----------+-------+----+--------+-----------------------+
|
156
143
|
|
157
|
-
== Known Issues
|
144
|
+
== Known Issues
|
158
145
|
|
159
146
|
* none
|
160
147
|
|
161
|
-
==
|
148
|
+
== License
|
162
149
|
|
163
150
|
(The MIT License)
|
164
151
|
|
165
|
-
Copyright (c) 2008 TJ Holowaychuk <tj@vision-media.ca>
|
152
|
+
Copyright (c) 2008-2009 TJ Holowaychuk <tj@vision-media.ca>
|
166
153
|
|
167
154
|
Permission is hereby granted, free of charge, to any person obtaining
|
168
155
|
a copy of this software and associated documentation files (the
|
data/Todo.rdoc
CHANGED
@@ -1,24 +1,29 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
*
|
5
|
-
*
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
*
|
10
|
-
*
|
2
|
+
== Major
|
3
|
+
|
4
|
+
* 1.9.x compatability
|
5
|
+
* Publish RDoc on mini page / screencasts
|
6
|
+
|
7
|
+
== Minor
|
8
|
+
|
9
|
+
* Fix multi-word command template creation via `commander init`
|
10
|
+
* Consider global #color method again
|
11
|
+
* Change; use stack technique for progress bar instead to clean things up
|
12
|
+
* Add; dynamically generate padding erb templates, command lists, multi-line text bodies etc
|
11
13
|
* Add optional command to be executed when none is specified
|
14
|
+
* Add global options... change runner implementations as well as displaying in terminal formatter, OpenStruct inherit these options?
|
15
|
+
* Add highline paging ... clean it up because its ugly
|
12
16
|
* Add aliasing of commands / args / options
|
13
|
-
*
|
14
|
-
* Change;
|
15
|
-
* Change; refactor specs
|
17
|
+
* Add option copying / merging capabilities
|
18
|
+
* Change; require that users explicitly require 'commander/import' (which in turn will highlight/import as well)
|
16
19
|
* Release to RubyForge as well
|
17
|
-
*
|
18
|
-
|
19
|
-
|
20
|
+
* Change; consider reversing |options, args| so args make use of ruby block param defaults with 1.9
|
21
|
+
or simply just to expand arg params like so |options, source_dir, dest_dir| ...
|
22
|
+
|
23
|
+
== Brainstorming
|
24
|
+
|
25
|
+
* Add global --trace method
|
26
|
+
* Add global trapping of INT to end process with less ugly output
|
20
27
|
* Add global --options switch for loading options from a filepath
|
21
|
-
* Add
|
22
|
-
* Add
|
23
|
-
* Change; consider reversing |options, args| so args make use of ruby block param defaults |options, file, dir = SOME_DIR| etc.. adjust doc
|
24
|
-
* Publish rdoc
|
28
|
+
* Add argument parser / defaults
|
29
|
+
* Add regexp matching for command names
|
data/bin/commander
CHANGED
@@ -10,43 +10,44 @@ program :description, 'Commander utility program.'
|
|
10
10
|
command :init do |c|
|
11
11
|
c.syntax = 'commander init <file>'
|
12
12
|
c.summary = 'Initialize a commander template'
|
13
|
-
c.description = 'Initialize an empty file with a commander template, allowing extremely quick creation of commader executables.'
|
14
|
-
c.example 'Create a new file with a commander template.', 'commander init
|
13
|
+
c.description = 'Initialize an empty <file> with a commander template, allowing extremely quick creation of commader executables.'
|
14
|
+
c.example 'Create a new file with a commander template.', 'commander init bin/my_executable'
|
15
15
|
c.when_called do |args, options|
|
16
|
-
|
16
|
+
file = args.shift || abort('file argument required.')
|
17
17
|
name = ask 'Machine name of program: '
|
18
18
|
description = ask 'Describe your program: '
|
19
|
-
commands =
|
19
|
+
commands = ask_for_array 'List the sub-commands you wish to create: '
|
20
20
|
begin
|
21
|
-
File.open(
|
22
|
-
f.write <<-
|
23
|
-
#!/usr/bin/env ruby
|
24
|
-
|
25
|
-
require 'rubygems'
|
26
|
-
require 'commander'
|
27
|
-
require '#{name}'
|
28
|
-
|
29
|
-
program :name, '#{name}'
|
30
|
-
program :version, #{name.
|
31
|
-
program :description, '#{description}'
|
32
|
-
|
33
|
-
|
21
|
+
File.open(file, 'w') do |f|
|
22
|
+
f.write <<-"...".gsub!(/^ {10}/, '')
|
23
|
+
#!/usr/bin/env ruby
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
require 'commander'
|
27
|
+
require '#{name}'
|
28
|
+
|
29
|
+
program :name, '#{name}'
|
30
|
+
program :version, #{name.capitalize}::VERSION
|
31
|
+
program :description, '#{description}'
|
32
|
+
|
33
|
+
...
|
34
34
|
commands.each do |command|
|
35
|
-
f.write <<-
|
36
|
-
command :#{command} do |c|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
35
|
+
f.write <<-"...".gsub!(/^ {12}/, '')
|
36
|
+
command :#{command} do |c|
|
37
|
+
c.syntax = '#{name} #{command} [options]'
|
38
|
+
c.summary = ''
|
39
|
+
c.description = ''
|
40
|
+
c.example 'description', 'command example'
|
41
|
+
c.option '--some-switch', 'Some switch that does something'
|
42
|
+
c.when_called do |args, options|
|
43
|
+
# Do something or c.when_called #{name.capitalize}::Commands::#{command.capitalize}
|
44
|
+
end
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
+
...
|
47
48
|
end
|
48
49
|
end
|
49
|
-
say "Initialized template in #{
|
50
|
+
say "Initialized template in #{file}"
|
50
51
|
rescue Exception => e
|
51
52
|
abort e
|
52
53
|
end
|
data/commander.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{commander}
|
5
|
-
s.version = "
|
5
|
+
s.version = "3.0.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["TJ Holowaychuk"]
|
9
|
-
s.date = %q{2009-03-
|
9
|
+
s.date = %q{2009-03-12}
|
10
10
|
s.default_executable = %q{commander}
|
11
11
|
s.description = %q{The complete solution for Ruby command-line executables}
|
12
12
|
s.email = %q{tj@vision-media.ca}
|
13
13
|
s.executables = ["commander"]
|
14
|
-
s.extra_rdoc_files = ["bin/commander", "lib/commander/command.rb", "lib/commander/core_ext/array.rb", "lib/commander/core_ext/
|
15
|
-
s.files = ["bin/commander", "commander.gemspec", "History.rdoc", "lib/commander/command.rb", "lib/commander/core_ext/array.rb", "lib/commander/core_ext/
|
14
|
+
s.extra_rdoc_files = ["bin/commander", "lib/commander/command.rb", "lib/commander/core_ext/array.rb", "lib/commander/core_ext/object.rb", "lib/commander/core_ext/string.rb", "lib/commander/core_ext.rb", "lib/commander/help_formatters/base.rb", "lib/commander/help_formatters/terminal/command_help.erb", "lib/commander/help_formatters/terminal/help.erb", "lib/commander/help_formatters/terminal.rb", "lib/commander/help_formatters.rb", "lib/commander/runner.rb", "lib/commander/user_interaction.rb", "lib/commander/version.rb", "lib/commander.rb", "README.rdoc", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
|
15
|
+
s.files = ["bin/commander", "commander.gemspec", "History.rdoc", "lib/commander/command.rb", "lib/commander/core_ext/array.rb", "lib/commander/core_ext/object.rb", "lib/commander/core_ext/string.rb", "lib/commander/core_ext.rb", "lib/commander/help_formatters/base.rb", "lib/commander/help_formatters/terminal/command_help.erb", "lib/commander/help_formatters/terminal/help.erb", "lib/commander/help_formatters/terminal.rb", "lib/commander/help_formatters.rb", "lib/commander/runner.rb", "lib/commander/user_interaction.rb", "lib/commander/version.rb", "lib/commander.rb", "Manifest", "Rakefile", "README.rdoc", "spec/command_spec.rb", "spec/core_ext/array_spec.rb", "spec/core_ext/object_spec.rb", "spec/core_ext/string_spec.rb", "spec/help_formatter_spec.rb", "spec/runner_spec.rb", "spec/spec_helper.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake", "test/pbar", "test/ui", "Todo.rdoc"]
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.homepage = %q{http://github.com/visionmedia/commander}
|
18
18
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Commander", "--main", "README.rdoc"]
|
data/lib/commander.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2008 TJ Holowaychuk <tj@vision-media.ca>
|
2
|
+
# Copyright (c) 2008-2009 TJ Holowaychuk <tj@vision-media.ca>
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -27,23 +27,12 @@ require 'rubygems'
|
|
27
27
|
require 'highline/import'
|
28
28
|
require 'commander/version'
|
29
29
|
require 'commander/user_interaction'
|
30
|
-
require 'commander/fileutils'
|
31
30
|
require 'commander/core_ext'
|
32
31
|
require 'commander/runner'
|
33
32
|
require 'commander/command'
|
34
33
|
require 'commander/help_formatters'
|
35
|
-
require 'commander/import'
|
36
34
|
|
37
35
|
$command_runner = Commander::Runner.new
|
38
|
-
|
39
|
-
# Highline terminal settings
|
40
36
|
$terminal.wrap_at = HighLine::SystemExtensions.terminal_size.first - 10 rescue 80
|
41
|
-
|
42
|
-
|
43
|
-
trap 'INT' do
|
44
|
-
say program(:int_message)
|
45
|
-
exit
|
46
|
-
end
|
47
|
-
|
48
|
-
# Auto-execute command runner
|
49
|
-
at_exit { $command_runner.run! }
|
37
|
+
trap('INT') { abort program(:int_message) }
|
38
|
+
at_exit { run! }
|
data/lib/commander/command.rb
CHANGED
@@ -7,22 +7,26 @@ module Commander
|
|
7
7
|
|
8
8
|
attr_reader :name, :examples, :options, :proxy_options
|
9
9
|
attr_accessor :syntax, :description, :summary
|
10
|
+
|
11
|
+
##
|
12
|
+
# Options struct.
|
13
|
+
|
14
|
+
class Options < OpenStruct
|
15
|
+
def default defaults = {}
|
16
|
+
defaults.each do |key, value|
|
17
|
+
send "#{key}=", value if send(key).nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
10
21
|
|
11
22
|
##
|
12
|
-
# Initialize new command with specified
|
23
|
+
# Initialize new command with specified +name+.
|
13
24
|
|
14
25
|
def initialize name
|
15
|
-
@name, @examples, @when_called = name.to_s, [],
|
26
|
+
@name, @examples, @when_called = name.to_s, [], []
|
16
27
|
@options, @proxy_options = [], []
|
17
28
|
end
|
18
29
|
|
19
|
-
#--
|
20
|
-
# Description aliases
|
21
|
-
#++
|
22
|
-
|
23
|
-
alias :long_description= :description=
|
24
|
-
alias :short_description= :summary=
|
25
|
-
|
26
30
|
##
|
27
31
|
# Add a usage example for this command.
|
28
32
|
#
|
@@ -31,16 +35,13 @@ module Commander
|
|
31
35
|
#
|
32
36
|
# === Examples:
|
33
37
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
38
|
+
# command :something do |c|
|
39
|
+
# c.example "Should do something", "my_command something"
|
40
|
+
# end
|
37
41
|
#
|
38
42
|
|
39
43
|
def example description, command
|
40
|
-
@examples
|
41
|
-
:description => description,
|
42
|
-
:command => command,
|
43
|
-
}
|
44
|
+
@examples.push description, command
|
44
45
|
end
|
45
46
|
|
46
47
|
##
|
@@ -51,27 +52,27 @@ module Commander
|
|
51
52
|
# passed to handle the option, otherwise the _options_ struct seen below
|
52
53
|
# contains the results of this option. This handles common formats such as:
|
53
54
|
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
55
|
+
# -h, --help options.help # => bool
|
56
|
+
# --[no-]feature options.feature # => bool
|
57
|
+
# --large-switch options.large_switch # => bool
|
58
|
+
# --file FILE options.file # => file passed
|
59
|
+
# --list WORDS options.list # => array
|
60
|
+
# --date [DATE] options.date # => date or nil when optional argument not set
|
60
61
|
#
|
61
62
|
# === Examples:
|
62
63
|
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
64
|
+
# command :something do |c|
|
65
|
+
# c.option '--recursive', 'Do something recursively'
|
66
|
+
# c.option '--file FILE', 'Specify a file'
|
67
|
+
# c.option('--info', 'Display info') { puts "handle with block" }
|
68
|
+
# c.option '--[no-]feature', 'With or without feature'
|
69
|
+
# c.option '--list FILES', Array, 'List the files specified'
|
70
|
+
#
|
71
|
+
# c.when_called do |args, options|
|
72
|
+
# do_something_recursively if options.recursive
|
73
|
+
# do_something_with_file options.file if options.file
|
74
|
+
# end
|
75
|
+
# end
|
75
76
|
#
|
76
77
|
# === Help Formatters:
|
77
78
|
#
|
@@ -82,16 +83,17 @@ module Commander
|
|
82
83
|
#
|
83
84
|
# === Input Parsing:
|
84
85
|
#
|
85
|
-
# Since Commander utilizes OptionParser you can pre-
|
86
|
-
# option arguments. Simply require 'optparse/time', or 'optparse/date',
|
86
|
+
# Since Commander utilizes OptionParser you can pre-parse and evaluate
|
87
|
+
# option arguments. Simply require 'optparse/time', or 'optparse/date', as these
|
88
|
+
# objects must respond to #parse.
|
87
89
|
#
|
88
90
|
# c.option '--time TIME', Time
|
89
91
|
# c.option '--date [DATE]', Date
|
90
92
|
#
|
91
93
|
|
92
94
|
def option *args, &block
|
93
|
-
switches, description = seperate_switches_from_description args
|
94
|
-
proc =
|
95
|
+
switches, description = seperate_switches_from_description *args
|
96
|
+
proc = block || option_proc(switches)
|
95
97
|
@options << {
|
96
98
|
:args => args,
|
97
99
|
:proc => proc,
|
@@ -101,42 +103,29 @@ module Commander
|
|
101
103
|
end
|
102
104
|
|
103
105
|
##
|
104
|
-
# Handle execution of command.
|
105
|
-
#
|
106
|
-
# An array of _args_ are passed to the handler, as well as an OpenStruct
|
107
|
-
# containing option values (populated regardless of them being declared).
|
108
|
-
# The handler may be a class, object, or block (see examples below).
|
106
|
+
# Handle execution of command. The handler may be a class,
|
107
|
+
# object, or block (see examples below).
|
109
108
|
#
|
110
109
|
# === Examples:
|
111
110
|
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
111
|
+
# # Simple block handling
|
112
|
+
# c.when_called do |args, options|
|
113
|
+
# # do something
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# # Create inst of Something and pass args / options
|
117
|
+
# c.when_called MyLib::Command::Something
|
118
|
+
#
|
119
|
+
# # Create inst of Something and use arbitrary method
|
120
|
+
# c.when_called MyLib::Command::Something, :some_method
|
121
|
+
#
|
122
|
+
# # Pass an object to handle callback (requires method symbol)
|
123
|
+
# c.when_called SomeObject, :some_method
|
125
124
|
#
|
126
125
|
|
127
126
|
def when_called *args, &block
|
128
|
-
|
129
|
-
|
130
|
-
case args.first
|
131
|
-
when Class
|
132
|
-
h[:class] = args.shift
|
133
|
-
h[:method] = args.shift
|
134
|
-
else
|
135
|
-
h[:object] = args.shift
|
136
|
-
h[:method] = args.shift
|
137
|
-
end
|
138
|
-
end
|
139
|
-
h[:proc] = block if block_given?
|
127
|
+
raise ArgumentError, 'must pass an object, class, or block.' if args.empty? and !block
|
128
|
+
@when_called = block ? [block] : args
|
140
129
|
end
|
141
130
|
|
142
131
|
##
|
@@ -146,83 +135,79 @@ module Commander
|
|
146
135
|
# * invokes when_called proc
|
147
136
|
#
|
148
137
|
|
149
|
-
def run args
|
150
|
-
call parse_options_and_call_procs(args)
|
138
|
+
def run *args
|
139
|
+
call parse_options_and_call_procs(*args)
|
151
140
|
end
|
152
141
|
|
153
142
|
##
|
154
|
-
# Parses options and calls associated procs
|
155
|
-
# returning the arguments
|
143
|
+
# Parses options and calls associated procs,
|
144
|
+
# returning the arguments remaining.
|
156
145
|
|
157
|
-
def parse_options_and_call_procs args
|
146
|
+
def parse_options_and_call_procs *args
|
158
147
|
return args if args.empty?
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
args
|
148
|
+
@options.inject OptionParser.new do |opts, option|
|
149
|
+
opts.on *option[:args], &option[:proc]
|
150
|
+
opts
|
151
|
+
end.parse! args
|
163
152
|
end
|
164
153
|
|
165
154
|
##
|
166
|
-
# Call the commands when_called block with
|
167
|
-
|
168
|
-
def call args = []
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
when h[:object] : h[:object].send(h[:method], args, proxy_option_struct)
|
178
|
-
when h[:proc] : h[:proc].call args, proxy_option_struct
|
179
|
-
end
|
155
|
+
# Call the commands when_called block with +args+.
|
156
|
+
|
157
|
+
def call args = []
|
158
|
+
object = @when_called.shift
|
159
|
+
meth = @when_called.shift || :call
|
160
|
+
options = proxy_option_struct
|
161
|
+
case object
|
162
|
+
when Proc ; object.call(args, options)
|
163
|
+
when Class ; meth != :call ? object.new.send(meth, args, options) : object.new(args, options)
|
164
|
+
else object.send(meth, args, options) if object
|
165
|
+
end
|
180
166
|
end
|
181
167
|
|
182
168
|
##
|
183
|
-
# Attempts to generate a method name symbol from
|
169
|
+
# Attempts to generate a method name symbol from +switch+.
|
184
170
|
# For example:
|
185
171
|
#
|
186
172
|
# -h # => :h
|
187
173
|
# --trace # => :trace
|
188
174
|
# --some-switch # => :some_switch
|
189
|
-
# --[
|
175
|
+
# --[no-]feature # => :feature
|
190
176
|
# --file FILE # => :file
|
191
|
-
# --list of,
|
192
|
-
|
193
|
-
def sym_from_switch switch
|
194
|
-
switch.gsub(/\[.*\]/, '').scan(/-([a-z]+)/).join('_').to_sym rescue nil
|
195
|
-
end
|
177
|
+
# --list of,things # => :list
|
196
178
|
|
197
|
-
def
|
198
|
-
|
179
|
+
def switch_to_sym switch
|
180
|
+
switch.scan(/[\-\]](\w+)/).join('_').to_sym rescue nil
|
199
181
|
end
|
200
182
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
183
|
+
##
|
184
|
+
# Return switches and description seperated from the +args+ passed.
|
185
|
+
|
186
|
+
def seperate_switches_from_description *args
|
187
|
+
switches = args.find_all { |arg| arg.to_s =~ /^-/ }
|
188
|
+
description = args.last unless !args.last.is_a? String or args.last.match(/^-/)
|
189
|
+
return switches, description
|
207
190
|
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Creates an Options instance populated with the option values
|
194
|
+
# collected by the #option_proc.
|
208
195
|
|
209
|
-
def
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
196
|
+
def proxy_option_struct
|
197
|
+
@proxy_options.inject Options.new do |options, (option, value)|
|
198
|
+
options.send :"#{option}=", value if option
|
199
|
+
options
|
200
|
+
end
|
214
201
|
end
|
215
202
|
|
216
203
|
##
|
217
|
-
#
|
218
|
-
#
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
:value => args,
|
225
|
-
}
|
204
|
+
# Option proxy proc used when a block is not explicitly passed
|
205
|
+
# via the #option method. This allows commander to auto-populate
|
206
|
+
# and work with option values.
|
207
|
+
|
208
|
+
def option_proc switches
|
209
|
+
Proc.new do |value|
|
210
|
+
@proxy_options.push [switch_to_sym(switches.last), value]
|
226
211
|
end
|
227
212
|
end
|
228
213
|
|