visionmedia-commander 2.5.7 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|