commander 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+
2
+ $:.unshift 'lib'
3
+ require 'commander'
4
+ require 'rubygems'
5
+ require 'rake'
6
+ require 'echoe'
7
+
8
+ Echoe.new "commander", Commander::VERSION do |p|
9
+ p.author = "TJ Holowaychuk"
10
+ p.email = "tj@vision-media.ca"
11
+ p.summary = "The complete solution for Ruby command-line executables"
12
+ p.url = "http://visionmedia.github.com/commander"
13
+ p.runtime_dependencies << "highline >=1.5.0"
14
+ end
15
+
16
+ Dir['tasks/**/*.rake'].sort.each { |lib| load lib }
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'commander/import'
5
+
6
+ program :name, 'commander'
7
+ program :version, Commander::VERSION
8
+ program :description, 'Commander utility program.'
9
+
10
+ command :init do |c|
11
+ c.syntax = 'commander init <file>'
12
+ c.summary = 'Initialize a commander template'
13
+ c.description = 'Initialize an empty <file> with a commander template,
14
+ allowing very quick creation of commander executables.'
15
+ c.example 'Create a new file with a commander template.', 'commander init bin/my_executable'
16
+ c.when_called do |args, options|
17
+ file = args.shift || abort('file argument required.')
18
+ name = ask 'Machine name of program: '
19
+ description = ask 'Describe your program: '
20
+ commands = ask_for_array 'List the commands you wish to create: '
21
+ begin
22
+ File.open(file, 'w') do |f|
23
+ f.write <<-"...".gsub!(/^ {10}/, '')
24
+ #!/usr/bin/env ruby
25
+
26
+ require 'rubygems'
27
+ require 'commander'
28
+ require '#{name}'
29
+
30
+ program :version, #{name.capitalize}::VERSION
31
+ program :description, '#{description}'
32
+
33
+ ...
34
+ commands.each do |command|
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
46
+
47
+ ...
48
+ end
49
+ end
50
+ say "Initialized template in #{file}"
51
+ rescue Exception => e
52
+ abort e
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{commander}
5
+ s.version = "3.3.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["TJ Holowaychuk"]
9
+ s.date = %q{2009-10-08}
10
+ s.default_executable = %q{commander}
11
+ s.description = %q{The complete solution for Ruby command-line executables}
12
+ s.email = %q{tj@vision-media.ca}
13
+ s.executables = ["commander"]
14
+ s.extra_rdoc_files = ["README.rdoc", "bin/commander", "lib/commander.rb", "lib/commander/blank.rb", "lib/commander/command.rb", "lib/commander/core_ext.rb", "lib/commander/core_ext/array.rb", "lib/commander/core_ext/object.rb", "lib/commander/delegates.rb", "lib/commander/help_formatters.rb", "lib/commander/help_formatters/base.rb", "lib/commander/help_formatters/terminal.rb", "lib/commander/help_formatters/terminal/command_help.erb", "lib/commander/help_formatters/terminal/help.erb", "lib/commander/help_formatters/terminal_compact.rb", "lib/commander/help_formatters/terminal_compact/command_help.erb", "lib/commander/help_formatters/terminal_compact/help.erb", "lib/commander/import.rb", "lib/commander/runner.rb", "lib/commander/user_interaction.rb", "lib/commander/version.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
15
+ s.files = ["History.rdoc", "Manifest", "README.rdoc", "Rakefile", "bin/commander", "commander.gemspec", "lib/commander.rb", "lib/commander/blank.rb", "lib/commander/command.rb", "lib/commander/core_ext.rb", "lib/commander/core_ext/array.rb", "lib/commander/core_ext/object.rb", "lib/commander/delegates.rb", "lib/commander/help_formatters.rb", "lib/commander/help_formatters/base.rb", "lib/commander/help_formatters/terminal.rb", "lib/commander/help_formatters/terminal/command_help.erb", "lib/commander/help_formatters/terminal/help.erb", "lib/commander/help_formatters/terminal_compact.rb", "lib/commander/help_formatters/terminal_compact/command_help.erb", "lib/commander/help_formatters/terminal_compact/help.erb", "lib/commander/import.rb", "lib/commander/runner.rb", "lib/commander/user_interaction.rb", "lib/commander/version.rb", "spec/command_spec.rb", "spec/core_ext/array_spec.rb", "spec/core_ext/object_spec.rb", "spec/help_formatters/base_spec.rb", "spec/help_formatters/terminal_spec.rb", "spec/runner_spec.rb", "spec/spec_helper.rb", "spec/ui_spec.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
16
+ s.homepage = %q{http://visionmedia.github.com/commander}
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Commander", "--main", "README.rdoc"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{commander}
20
+ s.rubygems_version = %q{1.3.5}
21
+ s.summary = %q{The complete solution for Ruby command-line executables}
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 3
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_runtime_dependency(%q<highline>, [">= 1.5.0"])
29
+ else
30
+ s.add_dependency(%q<highline>, [">= 1.5.0"])
31
+ end
32
+ else
33
+ s.add_dependency(%q<highline>, [">= 1.5.0"])
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ #--
2
+ # Copyright (c) 2008-2009 TJ Holowaychuk <tj@vision-media.ca>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'highline/import'
25
+ require 'commander/version'
26
+ require 'commander/blank'
27
+ require 'commander/user_interaction'
28
+ require 'commander/core_ext'
29
+ require 'commander/runner'
30
+ require 'commander/command'
31
+ require 'commander/help_formatters'
@@ -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,210 @@
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
+ end
44
+
45
+ ##
46
+ # Add a usage example for this command.
47
+ #
48
+ # Usage examples are later displayed in help documentation
49
+ # created by the help formatters.
50
+ #
51
+ # === Examples
52
+ #
53
+ # command :something do |c|
54
+ # c.example "Should do something", "my_command something"
55
+ # end
56
+ #
57
+
58
+ def example description, command
59
+ @examples << [description, command]
60
+ end
61
+
62
+ ##
63
+ # Add an option.
64
+ #
65
+ # Options are parsed via OptionParser so view it
66
+ # for additional usage documentation. A block may optionally be
67
+ # passed to handle the option, otherwise the _options_ struct seen below
68
+ # contains the results of this option. This handles common formats such as:
69
+ #
70
+ # -h, --help options.help # => bool
71
+ # --[no-]feature options.feature # => bool
72
+ # --large-switch options.large_switch # => bool
73
+ # --file FILE options.file # => file passed
74
+ # --list WORDS options.list # => array
75
+ # --date [DATE] options.date # => date or nil when optional argument not set
76
+ #
77
+ # === Examples
78
+ #
79
+ # command :something do |c|
80
+ # c.option '--recursive', 'Do something recursively'
81
+ # c.option '--file FILE', 'Specify a file'
82
+ # c.option('--info', 'Display info') { puts "handle with block" }
83
+ # c.option '--[no-]feature', 'With or without feature'
84
+ # c.option '--list FILES', Array, 'List the files specified'
85
+ #
86
+ # c.when_called do |args, options|
87
+ # do_something_recursively if options.recursive
88
+ # do_something_with_file options.file if options.file
89
+ # end
90
+ # end
91
+ #
92
+ # === Help Formatters
93
+ #
94
+ # This method also parses the arguments passed in order to determine
95
+ # which were switches, and which were descriptions for the
96
+ # option which can later be used within help formatters
97
+ # using option[:switches] and option[:description].
98
+ #
99
+ # === Input Parsing
100
+ #
101
+ # Since Commander utilizes OptionParser you can pre-parse and evaluate
102
+ # option arguments. Simply require 'optparse/time', or 'optparse/date', as these
103
+ # objects must respond to #parse.
104
+ #
105
+ # c.option '--time TIME', Time
106
+ # c.option '--date [DATE]', Date
107
+ #
108
+
109
+ def option *args, &block
110
+ switches, description = Runner.separate_switches_from_description *args
111
+ proc = block || option_proc(switches)
112
+ @options << {
113
+ :args => args,
114
+ :proc => proc,
115
+ :switches => switches,
116
+ :description => description,
117
+ }
118
+ end
119
+
120
+ ##
121
+ # Handle execution of command. The handler may be a class,
122
+ # object, or block (see examples below).
123
+ #
124
+ # === Examples
125
+ #
126
+ # # Simple block handling
127
+ # c.when_called do |args, options|
128
+ # # do something
129
+ # end
130
+ #
131
+ # # Create inst of Something and pass args / options
132
+ # c.when_called MyLib::Command::Something
133
+ #
134
+ # # Create inst of Something and use arbitrary method
135
+ # c.when_called MyLib::Command::Something, :some_method
136
+ #
137
+ # # Pass an object to handle callback (requires method symbol)
138
+ # c.when_called SomeObject, :some_method
139
+ #
140
+
141
+ def when_called *args, &block
142
+ raise ArgumentError, 'must pass an object, class, or block.' if args.empty? and !block
143
+ @when_called = block ? [block] : args
144
+ end
145
+
146
+ ##
147
+ # Run the command with _args_.
148
+ #
149
+ # * parses options, call option blocks
150
+ # * invokes when_called proc
151
+ #
152
+
153
+ def run *args
154
+ call parse_options_and_call_procs(*args)
155
+ end
156
+
157
+ #:stopdoc:
158
+
159
+ ##
160
+ # Parses options and calls associated procs,
161
+ # returning the arguments remaining.
162
+
163
+ def parse_options_and_call_procs *args
164
+ return args if args.empty?
165
+ @options.inject OptionParser.new do |opts, option|
166
+ opts.on *option[:args], &option[:proc]
167
+ opts
168
+ end.parse! args
169
+ end
170
+
171
+ ##
172
+ # Call the commands when_called block with _args_.
173
+
174
+ def call args = []
175
+ object = @when_called.shift
176
+ meth = @when_called.shift || :call
177
+ options = proxy_option_struct
178
+ case object
179
+ when Proc ; object.call(args, options)
180
+ when Class ; meth != :call ? object.new.send(meth, args, options) : object.new(args, options)
181
+ else object.send(meth, args, options) if object
182
+ end
183
+ end
184
+
185
+ ##
186
+ # Creates an Options instance populated with the option values
187
+ # collected by the #option_proc.
188
+
189
+ def proxy_option_struct
190
+ proxy_options.inject Options.new do |options, (option, value)|
191
+ options.__send__ :"#{option}=", value
192
+ options
193
+ end
194
+ end
195
+
196
+ ##
197
+ # Option proxy proc used when a block is not explicitly passed
198
+ # via the #option method. This allows commander to auto-populate
199
+ # and work with option values.
200
+
201
+ def option_proc switches
202
+ lambda { |value| proxy_options << [Runner.switch_to_sym(switches.last), value] }
203
+ end
204
+
205
+ def inspect
206
+ "<Commander::Command:#{name}>"
207
+ end
208
+
209
+ end
210
+ end
@@ -0,0 +1,3 @@
1
+
2
+ require 'commander/core_ext/array'
3
+ require 'commander/core_ext/object'
@@ -0,0 +1,25 @@
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
+ eval "%w(#{string})"
23
+ end
24
+
25
+ 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,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,8 @@
1
+
2
+ module Commander
3
+ module HelpFormatter
4
+ autoload :Base, 'commander/help_formatters/base'
5
+ autoload :Terminal, 'commander/help_formatters/terminal'
6
+ autoload :TerminalCompact, 'commander/help_formatters/terminal_compact'
7
+ end
8
+ 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