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 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/commander_spec.rb
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/import_spec.rb
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
- == LICENSE:
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
- * Use $terminal IO stream for progress bar
3
- * Fix stupid #program error output
4
- * mixins like c.use Commander::TraceOption ? ...
5
- * add configuration management like release gem
6
- * test bool switches --[no-]-foo ... document
7
- * Add option defaults when null / revisit OpenStruct population
8
- * Refactor specs / improve testing
9
- * Add option copying / merging capabilities
10
- * Fix issue with having command name in the args list, #args_without_command
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
- * Non-greedy matching of command name
14
- * Change; Have VerboseFileUtils only output basename ?
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
- * Add regexp matching for command names
18
- * Add highline paging ... clean it up
19
- * Add global options... change runner implementations as well as displaying in terminal formatter, OpenStruct inherit these options?
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; dynamically generate padding erb templates, command lists, multi-line text bodies etc
22
- * Add; display global options with global help
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 ./bin/my_executable'
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
- abort "Provide a filepath." if args.empty?
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 = ask 'List the sub-commands you wish to create: ', Array
19
+ commands = ask_for_array 'List the sub-commands you wish to create: '
20
20
  begin
21
- File.open(args.first, 'w') do |f|
22
- f.write <<-CODE
23
- #!/usr/bin/env ruby
24
-
25
- require 'rubygems'
26
- require 'commander'
27
- require '#{name}'
28
-
29
- program :name, '#{name}'
30
- program :version, #{name.camelcase}::VERSION
31
- program :description, '#{description}'
32
-
33
- CODE
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 <<-CODE
36
- command :#{command} do |c|
37
- c.syntax = ''
38
- c.description = ''
39
- c.example 'description', 'command example'
40
- c.option '--some-switch', 'Some switch that does something'
41
- c.when_called do |args, options|
42
- # Do something or c.when_called #{name.camelcase}::Commands::#{command.camelcase}
43
- end
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
- CODE
47
+ ...
47
48
  end
48
49
  end
49
- say "Initialized template in #{args.first}"
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 = "2.5.7"
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-11}
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/kernel.rb", "lib/commander/core_ext/object.rb", "lib/commander/core_ext/string.rb", "lib/commander/core_ext.rb", "lib/commander/fileutils.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/import.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/kernel.rb", "lib/commander/core_ext/object.rb", "lib/commander/core_ext/string.rb", "lib/commander/core_ext.rb", "lib/commander/fileutils.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/import.rb", "lib/commander/runner.rb", "lib/commander/user_interaction.rb", "lib/commander/version.rb", "lib/commander.rb", "Manifest", "Rakefile", "README.rdoc", "spec/commander_spec.rb", "spec/core_ext/string_spec.rb", "spec/help_formatter_spec.rb", "spec/import_spec.rb", "spec/spec_helper.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake", "Todo.rdoc"]
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
- # Display friendly interruption message
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! }
@@ -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 _name_.
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
- # command :something do |c|
35
- # c.example "Should do something", "my_command something"
36
- # end
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
- # -h, --help options.help # => bool
55
- # --[no-]feature options.feature # => bool
56
- # --large-switch options.large_switch # => bool
57
- # --file FILE options.file # => file passed
58
- # --list WORDS options.list # => array
59
- # --date [DATE] options.date # => date or nil when optional argument not set
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
- # command :something do |c|
64
- # c.option '--recursive', 'Do something recursively'
65
- # c.option '--file FILE', 'Specify a file'
66
- # c.option('--info', 'Display info') { puts "handle with block" }
67
- # c.option '--[no-]feature', 'With or without feature'
68
- # c.option '--list FILES', Array, 'List the files specified'
69
- #
70
- # c.when_called do |args, options|
71
- # do_something_recursively if options.recursive
72
- # do_something_with_file options.file if options.file
73
- # end
74
- # end
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-parser and evaluate
86
- # option arguments. Simply require 'optparse/time', or 'optparse/date', etc.
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 = block_given? ? block : populate_options_to_when_called(switches)
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
- # # Simple block handling
113
- # c.when_called do |args, options|
114
- # # do something
115
- # end
116
- #
117
- # # Create inst of Something and pass args / options
118
- # c.when_called MyLib::Command::Something
119
- #
120
- # # Create inst of Something and use arbitrary method
121
- # c.when_called MyLib::Command::Something, :some_method
122
- #
123
- # # Pass an object to handle callback (requires method symbol)
124
- # c.when_called SomeObject, :some_method
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
- h = @when_called
129
- unless args.empty?
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 left.
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
- opts = OptionParser.new
160
- @options.each { |o| opts.on(*o[:args], &o[:proc]) }
161
- opts.parse! args
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 _args_.
167
-
168
- def call args = []
169
- h = @when_called
170
- case
171
- when h[:class]
172
- if h[:method].nil?
173
- h[:class].new args, proxy_option_struct
174
- else
175
- h[:class].new.send h[:method], args, proxy_option_struct
176
- end
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 _switch_.
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
- # --[with]-feature # => :feature
175
+ # --[no-]feature # => :feature
190
176
  # --file FILE # => :file
191
- # --list of, things # => :list
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 inspect #:nodoc:
198
- "#<Commander::Command:#{@name}>"
179
+ def switch_to_sym switch
180
+ switch.scan(/[\-\]](\w+)/).join('_').to_sym rescue nil
199
181
  end
200
182
 
201
- private
202
-
203
- def proxy_option_struct #:nodoc:
204
- options = OpenStruct.new
205
- @proxy_options.each { |o| options.send("#{o[:method]}=", o[:value]) }
206
- options
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 seperate_switches_from_description args #:nodoc:
210
- # TODO: refactor this goodness
211
- switches = args.find_all { |a| a.index('-') == 0 if a.is_a? String }
212
- description = args.last unless !args.last.is_a? String or args.last.index('-') == 0
213
- [switches, description]
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
- # Pass option values to the when_called proc when a block
218
- # is not specifically supplied to #option.
219
-
220
- def populate_options_to_when_called switches #:nodoc:
221
- Proc.new do |args|
222
- @proxy_options << {
223
- :method => sym_from_switch(switches.last),
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