taco_it 1.5.1 → 1.5.2

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/bin/taco CHANGED
@@ -12,7 +12,7 @@ end
12
12
  require 'taco/commander/import'
13
13
 
14
14
  program :name, 'taco'
15
- program :version, '1.5.1'
15
+ program :version, '1.5.2'
16
16
  program :description, 'simple command line issue tracking'
17
17
 
18
18
  command :init do |c|
@@ -0,0 +1,8 @@
1
+
2
+ module Blank
3
+ def self.included base
4
+ base.class_eval do
5
+ instance_methods.each { |m| undef_method m unless m =~ /^__|object_id/ }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,226 @@
1
+
2
+ require 'optparse'
3
+
4
+ module Commander
5
+ class Command
6
+
7
+ attr_accessor :name, :examples, :syntax, :description
8
+ attr_accessor :summary, :proxy_options, :options
9
+
10
+ ##
11
+ # Options struct.
12
+
13
+ class Options
14
+ include Blank
15
+
16
+ def initialize
17
+ @table = {}
18
+ end
19
+
20
+ def __hash__
21
+ @table
22
+ end
23
+
24
+ def method_missing meth, *args, &block
25
+ meth.to_s =~ /=$/ ? @table[meth.to_s.chop.to_sym] = args.first : @table[meth]
26
+ end
27
+
28
+ def default defaults = {}
29
+ @table = defaults.merge! @table
30
+ end
31
+
32
+ def inspect
33
+ "<Commander::Command::Options #{ __hash__.map { |k,v| "#{k}=#{v.inspect}" }.join(', ') }>"
34
+ end
35
+ end
36
+
37
+ ##
38
+ # Initialize new command with specified _name_.
39
+
40
+ def initialize name
41
+ @name, @examples, @when_called = name.to_s, [], []
42
+ @options, @proxy_options = [], []
43
+ @argument_validator = nil
44
+ end
45
+
46
+ ##
47
+ # Add a usage example for this command.
48
+ #
49
+ # Usage examples are later displayed in help documentation
50
+ # created by the help formatters.
51
+ #
52
+ # === Examples
53
+ #
54
+ # command :something do |c|
55
+ # c.example "Should do something", "my_command something"
56
+ # end
57
+ #
58
+
59
+ def example description, command
60
+ @examples << [description, command]
61
+ end
62
+
63
+
64
+ def arguments proc
65
+ @argument_validator = proc
66
+ end
67
+
68
+ ##
69
+ # Add an option.
70
+ #
71
+ # Options are parsed via OptionParser so view it
72
+ # for additional usage documentation. A block may optionally be
73
+ # passed to handle the option, otherwise the _options_ struct seen below
74
+ # contains the results of this option. This handles common formats such as:
75
+ #
76
+ # -h, --help options.help # => bool
77
+ # --[no-]feature options.feature # => bool
78
+ # --large-switch options.large_switch # => bool
79
+ # --file FILE options.file # => file passed
80
+ # --list WORDS options.list # => array
81
+ # --date [DATE] options.date # => date or nil when optional argument not set
82
+ #
83
+ # === Examples
84
+ #
85
+ # command :something do |c|
86
+ # c.option '--recursive', 'Do something recursively'
87
+ # c.option '--file FILE', 'Specify a file'
88
+ # c.option('--info', 'Display info') { puts "handle with block" }
89
+ # c.option '--[no-]feature', 'With or without feature'
90
+ # c.option '--list FILES', Array, 'List the files specified'
91
+ #
92
+ # c.when_called do |args, options|
93
+ # do_something_recursively if options.recursive
94
+ # do_something_with_file options.file if options.file
95
+ # end
96
+ # end
97
+ #
98
+ # === Help Formatters
99
+ #
100
+ # This method also parses the arguments passed in order to determine
101
+ # which were switches, and which were descriptions for the
102
+ # option which can later be used within help formatters
103
+ # using option[:switches] and option[:description].
104
+ #
105
+ # === Input Parsing
106
+ #
107
+ # Since Commander utilizes OptionParser you can pre-parse and evaluate
108
+ # option arguments. Simply require 'optparse/time', or 'optparse/date', as these
109
+ # objects must respond to #parse.
110
+ #
111
+ # c.option '--time TIME', Time
112
+ # c.option '--date [DATE]', Date
113
+ #
114
+
115
+ def option *args, &block
116
+ switches, description = Runner.separate_switches_from_description(*args)
117
+ proc = block || option_proc(switches)
118
+ @options << {
119
+ :args => args,
120
+ :proc => proc,
121
+ :switches => switches,
122
+ :description => description,
123
+ }
124
+ end
125
+
126
+ ##
127
+ # Handle execution of command. The handler may be a class,
128
+ # object, or block (see examples below).
129
+ #
130
+ # === Examples
131
+ #
132
+ # # Simple block handling
133
+ # c.when_called do |args, options|
134
+ # # do something
135
+ # end
136
+ #
137
+ # # Create inst of Something and pass args / options
138
+ # c.when_called MyLib::Command::Something
139
+ #
140
+ # # Create inst of Something and use arbitrary method
141
+ # c.when_called MyLib::Command::Something, :some_method
142
+ #
143
+ # # Pass an object to handle callback (requires method symbol)
144
+ # c.when_called SomeObject, :some_method
145
+ #
146
+
147
+ def when_called *args, &block
148
+ raise ArgumentError, 'must pass an object, class, or block.' if args.empty? and !block
149
+ @when_called = block ? [block] : args
150
+ end
151
+ alias :action :when_called
152
+
153
+ ##
154
+ # Run the command with _args_.
155
+ #
156
+ # * parses options, call option blocks
157
+ # * invokes when_called proc
158
+ #
159
+
160
+ def run *args
161
+ call parse_options_and_call_procs(*args)
162
+ end
163
+
164
+ #:stopdoc:
165
+
166
+ ##
167
+ # Parses options and calls associated procs,
168
+ # returning the arguments remaining.
169
+
170
+ def parse_options_and_call_procs *args
171
+ return args if args.empty?
172
+ @options.inject OptionParser.new do |opts, option|
173
+ opts.on(*option[:args], &option[:proc])
174
+ opts
175
+ end.parse! args
176
+ end
177
+
178
+ ##
179
+ # Call the commands when_called block with _args_.
180
+
181
+ def call args = []
182
+ object = @when_called.shift
183
+ meth = @when_called.shift || :call
184
+ options = proxy_option_struct
185
+
186
+ if @argument_validator
187
+ raise ArgumentError.new("Unexpected arguments: #{args.join(' ')}") unless @argument_validator.call(args)
188
+ elsif args.size > 0
189
+ raise ArgumentError.new("Unexpected arguments: #{args.join(' ')}")
190
+ end
191
+
192
+ case object
193
+ when Proc ; object.call(args, options)
194
+ when Class ; meth != :call ? object.new.send(meth, args, options) : object.new(args, options)
195
+ else object.send(meth, args, options) if object
196
+ end
197
+ end
198
+
199
+ ##
200
+ # Creates an Options instance populated with the option values
201
+ # collected by the #option_proc.
202
+
203
+ def proxy_option_struct
204
+ proxy_options.inject Options.new do |options, (option, value)|
205
+ # options that are present will evaluate to true
206
+ value = true if value.nil?
207
+ options.__send__ :"#{option}=", value
208
+ options
209
+ end
210
+ end
211
+
212
+ ##
213
+ # Option proxy proc used when a block is not explicitly passed
214
+ # via the #option method. This allows commander to auto-populate
215
+ # and work with option values.
216
+
217
+ def option_proc switches
218
+ lambda { |value| proxy_options << [Runner.switch_to_sym(switches.last), value] }
219
+ end
220
+
221
+ def inspect
222
+ "<Commander::Command:#{name}>"
223
+ end
224
+
225
+ end
226
+ end
@@ -0,0 +1,26 @@
1
+
2
+ class Array
3
+
4
+ ##
5
+ # Split _string_ into an array. Used in
6
+ # conjunction with Highline's #ask, or #ask_for_array
7
+ # methods, which must respond to #parse.
8
+ #
9
+ # This method allows escaping of whitespace. For example
10
+ # the arguments foo bar\ baz will become ['foo', 'bar baz']
11
+ #
12
+ # === Example
13
+ #
14
+ # # ask invokes Array#parse
15
+ # list = ask 'Favorite cookies:', Array
16
+ #
17
+ # # or use ask_for_CLASS
18
+ # list = ask_for_array 'Favorite cookies: '
19
+ #
20
+
21
+ def self.parse string
22
+ # Using reverse + lookahead to work around Ruby 1.8's lack of lookbehind
23
+ string.reverse.split(/\s(?!\\)/).reverse.map { |s| s.reverse.gsub('\\ ', ' ') }
24
+ end
25
+
26
+ end
@@ -0,0 +1,11 @@
1
+
2
+ class Object
3
+
4
+ ##
5
+ # Return the current binding.
6
+
7
+ def get_binding
8
+ binding
9
+ end
10
+
11
+ end
@@ -0,0 +1,3 @@
1
+
2
+ require 'taco/commander/core_ext/array'
3
+ require 'taco/commander/core_ext/object'
@@ -0,0 +1,13 @@
1
+
2
+ module Commander
3
+ module Delegates
4
+ %w( add_command command program run! global_option
5
+ commands alias_command default_command ).each do |meth|
6
+ eval <<-END, binding, __FILE__, __LINE__
7
+ def #{meth} *args, &block
8
+ ::Commander::Runner.instance.#{meth} *args, &block
9
+ end
10
+ END
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Commander
3
+
4
+ ##
5
+ # = Help Formatter
6
+ #
7
+ # Commander's help formatters control the output when
8
+ # either the help command, or --help switch are called.
9
+ # The default formatter is Commander::HelpFormatter::Terminal.
10
+
11
+ module HelpFormatter
12
+ class Base
13
+ def initialize runner; @runner = runner end
14
+ def render; 'Implement global help here' end
15
+ def render_command command; "Implement help for #{command.name} here" end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+
2
+ <%= $terminal.color "NAME", :bold %>:
3
+
4
+ <%= @name %>
5
+ <% if @syntax -%>
6
+
7
+ <%= $terminal.color "SYNOPSIS", :bold %>:
8
+
9
+ <%= @syntax -%>
10
+
11
+ <% end -%>
12
+
13
+ <%= $terminal.color "DESCRIPTION", :bold %>:
14
+
15
+ <%= Commander::HelpFormatter.indent 4, (@description || @summary || 'No description.') -%>
16
+
17
+ <% unless @examples.empty? -%>
18
+
19
+ <%= $terminal.color "EXAMPLES", :bold %>:
20
+ <% for description, command in @examples -%>
21
+
22
+ # <%= description %>
23
+ <%= command %>
24
+ <% end -%>
25
+ <% end -%>
26
+ <% unless @options.empty? -%>
27
+
28
+ <%= $terminal.color "OPTIONS", :bold %>:
29
+ <% for option in @options -%>
30
+
31
+ <%= option[:switches].join ', ' %>
32
+ <%= option[:description] %>
33
+ <% end -%>
34
+ <% end -%>
35
+
@@ -0,0 +1,36 @@
1
+ <%= $terminal.color "NAME", :bold %>:
2
+
3
+ <%= program :name %>
4
+
5
+ <%= $terminal.color "DESCRIPTION", :bold %>:
6
+
7
+ <%= Commander::HelpFormatter.indent 4, program(:description) %>
8
+
9
+ <%= $terminal.color "COMMANDS", :bold %>:
10
+ <% for name, command in @commands.sort -%>
11
+ <% unless alias? name %>
12
+ <%= "%-20s %s" % [command.name, command.summary || command.description] -%>
13
+ <% end -%>
14
+ <% end %>
15
+ <% unless @aliases.empty? %>
16
+ <%= $terminal.color "ALIASES", :bold %>:
17
+ <% for alias_name, args in @aliases.sort %>
18
+ <%= "%-20s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] -%>
19
+ <% end %>
20
+ <% end %>
21
+ <% unless @options.empty? -%>
22
+ <%= $terminal.color "GLOBAL OPTIONS", :bold %>:
23
+ <% for option in @options -%>
24
+
25
+ <%= option[:switches].join ', ' %>
26
+ <%= option[:description] %>
27
+ <% end -%>
28
+ <% end -%>
29
+ <% if program :help -%>
30
+ <% for title, body in program(:help) %>
31
+ <%= $terminal.color title.to_s.upcase, :bold %>:
32
+
33
+ <%= body %>
34
+ <% end -%>
35
+ <% end -%>
36
+
@@ -0,0 +1,20 @@
1
+
2
+ require 'erb'
3
+
4
+ module Commander
5
+ module HelpFormatter
6
+ class Terminal < Base
7
+ def render
8
+ template(:help).result @runner.get_binding
9
+ end
10
+
11
+ def render_command command
12
+ template(:command_help).result command.get_binding
13
+ end
14
+
15
+ def template name
16
+ ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal', "#{name}.erb")), nil, '-')
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+
2
+ <%= @name %>
3
+ <% if @syntax -%>
4
+
5
+ Usage: <%= @syntax %>
6
+ <% end -%>
7
+ <% if @description || @summary -%>
8
+
9
+ <%= @description || @summary %>
10
+ <% end -%>
11
+ <% unless @examples.empty? -%>
12
+
13
+ Examples:
14
+ <% for description, command in @examples -%>
15
+
16
+ # <%= description %>
17
+ <%= command %>
18
+ <% end -%>
19
+ <% end -%>
20
+ <% unless @options.empty? -%>
21
+
22
+ Options:
23
+ <% for option in @options -%>
24
+ <%= "%-20s %s" % [option[:switches].join(', '), option[:description]] %>
25
+ <% end -%>
26
+ <% end -%>
27
+
@@ -0,0 +1,29 @@
1
+ <%= program :name %>
2
+
3
+ <%= program :description %>
4
+
5
+ Commands:
6
+ <% for name, command in @commands.sort -%>
7
+ <% unless alias? name -%>
8
+ <%= "%-20s %s" % [command.name, command.summary || command.description] %>
9
+ <% end -%>
10
+ <% end -%>
11
+ <% unless @aliases.empty? %>
12
+ Aliases:
13
+ <% for alias_name, args in @aliases.sort -%>
14
+ <%= "%-20s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] %>
15
+ <% end -%>
16
+ <% end %>
17
+ <% unless @options.empty? -%>
18
+ Global Options:
19
+ <% for option in @options -%>
20
+ <%= "%-20s %s" % [option[:switches].join(', '), option[:description]] -%>
21
+ <% end -%>
22
+ <% end -%>
23
+ <% if program :help -%>
24
+ <% for title, body in program(:help) %>
25
+ <%= title %>:
26
+ <%= body %>
27
+ <% end %>
28
+ <% end -%>
29
+
@@ -0,0 +1,12 @@
1
+
2
+ require 'erb'
3
+
4
+ module Commander
5
+ module HelpFormatter
6
+ class TerminalCompact < Terminal
7
+ def template name
8
+ ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal_compact', "#{name}.erb")), nil, '-')
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+
2
+ module Commander
3
+ module HelpFormatter
4
+ autoload :Base, 'taco/commander/help_formatters/base'
5
+ autoload :Terminal, 'taco/commander/help_formatters/terminal'
6
+ autoload :TerminalCompact, 'taco/commander/help_formatters/terminal_compact'
7
+
8
+ module_function
9
+ def indent amount, text
10
+ text.gsub("\n", "\n" + (' ' * amount))
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+
2
+ require 'taco/commander'
3
+ require 'taco/commander/delegates'
4
+
5
+ include Commander::Delegates
6
+
7
+ $terminal.wrap_at = HighLine::SystemExtensions.terminal_size.first - 5 rescue 80 if $stdin.tty?
8
+ at_exit { run! }
@@ -0,0 +1,8 @@
1
+
2
+ module Commander
3
+ module Platform
4
+ def self.jruby?
5
+ defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,405 @@
1
+
2
+ require 'optparse'
3
+
4
+ module Commander
5
+ class Runner
6
+
7
+ #--
8
+ # Exceptions
9
+ #++
10
+
11
+ class CommandError < StandardError; end
12
+ class InvalidCommandError < CommandError; end
13
+
14
+ ##
15
+ # Array of commands.
16
+
17
+ attr_reader :commands
18
+
19
+ ##
20
+ # Global options.
21
+
22
+ attr_reader :options
23
+
24
+ ##
25
+ # Hash of help formatter aliases.
26
+
27
+ attr_reader :help_formatter_aliases
28
+
29
+ ##
30
+ # Initialize a new command runner. Optionally
31
+ # supplying _args_ for mocking, or arbitrary usage.
32
+
33
+ def initialize args = ARGV
34
+ @args, @commands, @aliases, @options = args, {}, {}, []
35
+ @help_formatter_aliases = help_formatter_alias_defaults
36
+ @program = program_defaults
37
+ create_default_commands
38
+ end
39
+
40
+ ##
41
+ # Return singleton Runner instance.
42
+
43
+ def self.instance
44
+ @singleton ||= new
45
+ end
46
+
47
+ ##
48
+ # Run command parsing and execution process.
49
+
50
+ def run!
51
+ trace = false
52
+ require_program :version, :description
53
+ trap('INT') { abort program(:int_message) } if program(:int_message)
54
+ trap('INT') { program(:int_block).call } if program(:int_block)
55
+ global_option('-h', '--help', 'Display help documentation') do
56
+ args = @args - %w[-h --help]
57
+ command(:help).run(*args)
58
+ return
59
+ end
60
+ global_option('-v', '--version', 'Display version information') { say version; return }
61
+ global_option('-t', '--trace', 'Display backtrace when an error occurs') { trace = true }
62
+ parse_global_options
63
+ remove_global_options options, @args
64
+ unless trace
65
+ begin
66
+ run_active_command
67
+ rescue InvalidCommandError => e
68
+ abort "Error: Invalid command. See 'taco --help' for more information."
69
+ rescue Exception => e
70
+ abort "Error: #{e.to_s}"
71
+ end
72
+ else
73
+ run_active_command
74
+ end
75
+ end
76
+
77
+ ##
78
+ # Return program version.
79
+
80
+ def version
81
+ '%s %s' % [program(:name), program(:version)]
82
+ end
83
+
84
+ ##
85
+ # Assign program information.
86
+ #
87
+ # === Examples
88
+ #
89
+ # # Set data
90
+ # program :name, 'Commander'
91
+ # program :version, Commander::VERSION
92
+ # program :description, 'Commander utility program.'
93
+ # program :help, 'Copyright', '2008 TJ Holowaychuk'
94
+ # program :help, 'Anything', 'You want'
95
+ # program :int_message 'Bye bye!'
96
+ # program :help_formatter, :compact
97
+ # program :help_formatter, Commander::HelpFormatter::TerminalCompact
98
+ #
99
+ # # Get data
100
+ # program :name # => 'Commander'
101
+ #
102
+ # === Keys
103
+ #
104
+ # :version (required) Program version triple, ex: '0.0.1'
105
+ # :description (required) Program description
106
+ # :name Program name, defaults to basename of executable
107
+ # :help_formatter Defaults to Commander::HelpFormatter::Terminal
108
+ # :help Allows addition of arbitrary global help blocks
109
+ # :int_message Message to display when interrupted (CTRL + C)
110
+ #
111
+
112
+ def program key, *args, &block
113
+ if key == :help and !args.empty?
114
+ @program[:help] ||= {}
115
+ @program[:help][args.first] = args.at(1)
116
+ elsif key == :help_formatter && !args.empty?
117
+ @program[key] = (@help_formatter_aliases[args.first] || args.first)
118
+ elsif block
119
+ @program[key] = block
120
+ else
121
+ unless args.empty?
122
+ @program[key] = (args.count == 1 && args[0]) || args
123
+ end
124
+ @program[key]
125
+ end
126
+ end
127
+
128
+ ##
129
+ # Creates and yields a command instance when a block is passed.
130
+ # Otherwise attempts to return the command, raising InvalidCommandError when
131
+ # it does not exist.
132
+ #
133
+ # === Examples
134
+ #
135
+ # command :my_command do |c|
136
+ # c.when_called do |args|
137
+ # # Code
138
+ # end
139
+ # end
140
+ #
141
+
142
+ def command name, &block
143
+ yield add_command(Commander::Command.new(name)) if block
144
+ @commands[name.to_s]
145
+ end
146
+
147
+ ##
148
+ # Add a global option; follows the same syntax as Command#option
149
+ # This would be used for switches such as --version, --trace, etc.
150
+
151
+ def global_option *args, &block
152
+ switches, description = Runner.separate_switches_from_description *args
153
+ @options << {
154
+ :args => args,
155
+ :proc => block,
156
+ :switches => switches,
157
+ :description => description,
158
+ }
159
+ end
160
+
161
+ ##
162
+ # Alias command _name_ with _alias_name_. Optionally _args_ may be passed
163
+ # as if they were being passed straight to the original command via the command-line.
164
+
165
+ def alias_command alias_name, name, *args
166
+ @commands[alias_name.to_s] = command name
167
+ @aliases[alias_name.to_s] = args
168
+ end
169
+
170
+ ##
171
+ # Default command _name_ to be used when no other
172
+ # command is found in the arguments.
173
+
174
+ def default_command name
175
+ @default_command = name
176
+ end
177
+
178
+ ##
179
+ # Add a command object to this runner.
180
+
181
+ def add_command command
182
+ @commands[command.name] = command
183
+ end
184
+
185
+ ##
186
+ # Check if command _name_ is an alias.
187
+
188
+ def alias? name
189
+ @aliases.include? name.to_s
190
+ end
191
+
192
+ ##
193
+ # Check if a command _name_ exists.
194
+
195
+ def command_exists? name
196
+ @commands[name.to_s]
197
+ end
198
+
199
+ #:stopdoc:
200
+
201
+ ##
202
+ # Get active command within arguments passed to this runner.
203
+
204
+ def active_command
205
+ @__active_command ||= command(command_name_from_args)
206
+ end
207
+
208
+ ##
209
+ # Attempts to locate a command name from within the arguments.
210
+ # Supports multi-word commands, using the largest possible match.
211
+
212
+ def command_name_from_args
213
+ @__command_name_from_args ||= (valid_command_names_from(*@args.dup).sort.last || @default_command)
214
+ end
215
+
216
+ ##
217
+ # Returns array of valid command names found within _args_.
218
+
219
+ def valid_command_names_from *args
220
+ arg_string = args.delete_if { |value| value =~ /^-/ }.join ' '
221
+ commands.keys.find_all { |name| name if /^#{name}\b/.match arg_string }
222
+ end
223
+
224
+ ##
225
+ # Help formatter instance.
226
+
227
+ def help_formatter
228
+ @__help_formatter ||= program(:help_formatter).new self
229
+ end
230
+
231
+ ##
232
+ # Return arguments without the command name.
233
+
234
+ def args_without_command_name
235
+ removed = []
236
+ parts = command_name_from_args.split rescue []
237
+ @args.dup.delete_if do |arg|
238
+ removed << arg if parts.include?(arg) and not removed.include?(arg)
239
+ end
240
+ end
241
+
242
+ ##
243
+ # Returns hash of help formatter alias defaults.
244
+
245
+ def help_formatter_alias_defaults
246
+ return :compact => HelpFormatter::TerminalCompact
247
+ end
248
+
249
+ ##
250
+ # Returns hash of program defaults.
251
+
252
+ def program_defaults
253
+ return :help_formatter => HelpFormatter::Terminal,
254
+ :name => File.basename($0)
255
+ end
256
+
257
+ ##
258
+ # Creates default commands such as 'help' which is
259
+ # essentially the same as using the --help switch.
260
+
261
+ def create_default_commands
262
+ command :help do |c|
263
+ c.syntax = 'commander help [command]'
264
+ c.description = 'Display global or [command] help documentation.'
265
+ c.example 'Display global help', 'command help'
266
+ c.example "Display help for 'foo'", 'command help foo'
267
+ c.when_called do |args, options|
268
+ if args.empty?
269
+ say help_formatter.render
270
+ else
271
+ command = command args.join(' ')
272
+ begin
273
+ require_valid_command command
274
+ rescue InvalidCommandError => e
275
+ abort "#{e}. Use --help for more information"
276
+ end
277
+ say help_formatter.render_command(command)
278
+ end
279
+ end
280
+ end
281
+ end
282
+
283
+ ##
284
+ # Raises InvalidCommandError when a _command_ is not found.
285
+
286
+ def require_valid_command command = active_command
287
+ raise InvalidCommandError, 'invalid command', caller if command.nil?
288
+ end
289
+
290
+ ##
291
+ # Removes global _options_ from _args_. This prevents an invalid
292
+ # option error from occurring when options are parsed
293
+ # again for the command.
294
+
295
+ def remove_global_options options, args
296
+ # TODO: refactor with flipflop, please TJ ! have time to refactor me !
297
+ options.each do |option|
298
+ switches = option[:switches].dup
299
+ next if switches.empty?
300
+
301
+ if switchHasArg = switches.any? { |s| s =~ /[ =]/ }
302
+ switches.map! { |s| s[0, s.index('=') || s.index(' ') || s.length] }
303
+ end
304
+
305
+ past_switch, arg_removed = false, false
306
+ args.delete_if do |arg|
307
+ if switches.any? { |s| arg[0, s.length] == s }
308
+ arg_removed = !switchHasArg
309
+ past_switch = true
310
+ elsif past_switch && !arg_removed && arg !~ /^-/
311
+ arg_removed = true
312
+ else
313
+ arg_removed = true
314
+ false
315
+ end
316
+ end
317
+ end
318
+ end
319
+
320
+ ##
321
+ # Parse global command options.
322
+
323
+ def parse_global_options
324
+
325
+ parser = options.inject(OptionParser.new) do |options, option|
326
+ options.on *option[:args], &global_option_proc(option[:switches], &option[:proc])
327
+ end
328
+
329
+ options = @args.dup
330
+ begin
331
+ parser.parse!(options)
332
+ rescue OptionParser::InvalidOption => e
333
+ # Remove the offending args and retry.
334
+ options = options.reject { |o| e.args.include?(o) }
335
+ retry
336
+ end
337
+ end
338
+
339
+ ##
340
+ # Returns a proc allowing for commands to inherit global options.
341
+ # This functionality works whether a block is present for the global
342
+ # option or not, so simple switches such as --verbose can be used
343
+ # without a block, and used throughout all commands.
344
+
345
+ def global_option_proc switches, &block
346
+ lambda do |value|
347
+ unless active_command.nil?
348
+ active_command.proxy_options << [Runner.switch_to_sym(switches.last), value]
349
+ end
350
+ yield value if block and !value.nil?
351
+ end
352
+ end
353
+
354
+ ##
355
+ # Raises a CommandError when the program any of the _keys_ are not present, or empty.
356
+
357
+ def require_program *keys
358
+ keys.each do |key|
359
+ raise CommandError, "program #{key} required" if program(key).nil? or program(key).empty?
360
+ end
361
+ end
362
+
363
+ ##
364
+ # Return switches and description separated from the _args_ passed.
365
+
366
+ def self.separate_switches_from_description *args
367
+ switches = args.find_all { |arg| arg.to_s =~ /^-/ }
368
+ description = args.last unless !args.last.is_a? String or args.last.match(/^-/)
369
+ return switches, description
370
+ end
371
+
372
+ ##
373
+ # Attempts to generate a method name symbol from +switch+.
374
+ # For example:
375
+ #
376
+ # -h # => :h
377
+ # --trace # => :trace
378
+ # --some-switch # => :some_switch
379
+ # --[no-]feature # => :feature
380
+ # --file FILE # => :file
381
+ # --list of,things # => :list
382
+ #
383
+
384
+ def self.switch_to_sym switch
385
+ switch.scan(/[\-\]](\w+)/).join('_').to_sym rescue nil
386
+ end
387
+
388
+ ##
389
+ # Run the active command.
390
+
391
+ def run_active_command
392
+ require_valid_command
393
+ if alias? command_name_from_args
394
+ active_command.run *(@aliases[command_name_from_args.to_s] + args_without_command_name)
395
+ else
396
+ active_command.run *args_without_command_name
397
+ end
398
+ end
399
+
400
+ def say *args #:nodoc:
401
+ $terminal.say *args
402
+ end
403
+
404
+ end
405
+ end
@@ -0,0 +1,3 @@
1
+ module Commander
2
+ VERSION = '4.1.4'
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taco_it
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 1.5.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -35,18 +35,36 @@ executables:
35
35
  extensions: []
36
36
  extra_rdoc_files: []
37
37
  files:
38
- - lib/taco.rb
39
38
  - lib/taco/change.rb
40
39
  - lib/taco/cli.rb
40
+ - lib/taco/commander/blank.rb
41
+ - lib/taco/commander/command.rb
42
+ - lib/taco/commander/core_ext/array.rb
43
+ - lib/taco/commander/core_ext/object.rb
44
+ - lib/taco/commander/core_ext.rb
45
+ - lib/taco/commander/delegates.rb
46
+ - lib/taco/commander/help_formatters/base.rb
47
+ - lib/taco/commander/help_formatters/terminal/command_help.erb
48
+ - lib/taco/commander/help_formatters/terminal/help.erb
49
+ - lib/taco/commander/help_formatters/terminal.rb
50
+ - lib/taco/commander/help_formatters/terminal_compact/command_help.erb
51
+ - lib/taco/commander/help_formatters/terminal_compact/help.erb
52
+ - lib/taco/commander/help_formatters/terminal_compact.rb
53
+ - lib/taco/commander/help_formatters.rb
54
+ - lib/taco/commander/import.rb
55
+ - lib/taco/commander/platform.rb
56
+ - lib/taco/commander/runner.rb
57
+ - lib/taco/commander/version.rb
41
58
  - lib/taco/commander.rb
59
+ - lib/taco/defaults/index.html.erb
60
+ - lib/taco/defaults/taco_profile
61
+ - lib/taco/defaults/tacorc
42
62
  - lib/taco/issue.rb
43
63
  - lib/taco/schema.rb
44
64
  - lib/taco/taco.rb
45
65
  - lib/taco/taco_profile.rb
46
66
  - lib/taco/tacorc.rb
47
- - lib/taco/defaults/index.html.erb
48
- - lib/taco/defaults/taco_profile
49
- - lib/taco/defaults/tacorc
67
+ - lib/taco.rb
50
68
  - bin/taco
51
69
  homepage: http://github.com/mikepartelow/taco
52
70
  licenses: []