subcommand 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Rahul Kumar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,108 @@
1
+ = subcommand
2
+
3
+ A tiny wrapper over ruby's awesome OptionParser (standard) which gives easy facility of subcommands.
4
+ It has a similar interface to git and prints subcommands summary as well.
5
+
6
+ == Features:
7
+
8
+ 1. subcommands using all of OptionParser's features
9
+ 2. aliases for subcommands
10
+
11
+
12
+ e.g
13
+ Assuming a program "prog" with subcommands "del" and "add"
14
+
15
+ prog help
16
+ prog --help
17
+
18
+ prog help del
19
+ prog del --help
20
+
21
+ prog del --force file.a
22
+ prog --verbose del --force file.a
23
+
24
+ == Examples
25
+
26
+ if a program has subcommands foo and baz
27
+
28
+ ruby subcommand.rb help
29
+ ruby subcommand.rb --help
30
+ ruby subcommand.rb help foo
31
+ ruby subcommand.rb foo --help
32
+ ruby subcommand.rb baz --quiet "some text"
33
+ ruby subcommand.rb --verbose foo --force file.zzz
34
+
35
+ == STEPS
36
+
37
+ 1. define global_options (optional)
38
+
39
+ global_options do |opts|
40
+ opts.banner = "Usage: subcommand.rb [options] [subcommand [options]]"
41
+ opts.description = "Stupid program that does something"
42
+ opts.separator ""
43
+ opts.separator "Global options are:"
44
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
45
+ options[:verbose] = v
46
+ end
47
+ end
48
+
49
+ 2. define commands using command(). Send multiple names for aliases.
50
+
51
+ command :foo do |opts|
52
+ opts.banner = "Usage: foo [options]"
53
+ opts.description = "desc for foo"
54
+ opts.on("-f", "--[no-]force", "force action") do |v|
55
+ options[:force] = v
56
+ end
57
+ end
58
+
59
+ # aliases init and create
60
+ command :init, :create do |opts| ...
61
+
62
+ 3. call opt_parse()
63
+
64
+ == Sample Output
65
+
66
+ $ ruby subcommand.rb help
67
+
68
+ Usage: subcommand.rb [options] [subcommand [options]]
69
+ Stupid program that does something
70
+
71
+ Global options are:
72
+ -v, --[no-]verbose Run verbosely
73
+
74
+ Commands are:
75
+ foo : desc for foo
76
+ baz : desc for baz
77
+
78
+ Aliases:
79
+ goo - foo
80
+
81
+ See 'subcommand.rb help COMMAND' for more information on a specific command.
82
+
83
+
84
+ $ ruby subcommand.rb help foo
85
+
86
+ Usage: foo [options]
87
+ desc for foo
88
+ -f, --[no-]force force action
89
+
90
+ == Install
91
+
92
+ sudo gem install subcommand
93
+
94
+ Or, copy into your lib directory and require (see source for sample usage)
95
+
96
+ == Note on Patches/Pull Requests
97
+
98
+ * Fork the project.
99
+ * Make your feature addition or bug fix.
100
+ * Add tests for it. This is important so I don't break it in a
101
+ future version unintentionally.
102
+ * Commit, do not mess with rakefile, version, or history.
103
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
104
+ * Send me a pull request. Bonus points for topic branches.
105
+
106
+ == Copyright
107
+
108
+ Copyright (c) 2010 Rahul Kumar. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "subcommand"
8
+ gem.summary = %Q{A tiny wrapper over OptionParser giving simple, elegant subcommand facility}
9
+ gem.description = %Q{Subcommand and alias facility for command line programs with elegant help printing}
10
+ gem.email = "sentinel.1879@gmail.com"
11
+ gem.homepage = "http://github.com/rkumar/subcommand"
12
+ gem.authors = ["Rahul Kumar"]
13
+ #gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_development_dependency "yard", ">= 0"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ begin
47
+ require 'yard'
48
+ YARD::Rake::YardocTask.new
49
+ rescue LoadError
50
+ task :yardoc do
51
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
52
+ end
53
+ end
data/TODO ADDED
@@ -0,0 +1 @@
1
+ Add aliases
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/lib/subcommand.rb ADDED
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env ruby -w
2
+ ######################################
3
+ # A tiny wrapper over optparse that gives easy subcommand facility.
4
+ # It also neatly prints help for global and subcommands
5
+ # as well as summarizes subcommands in global help.
6
+ #
7
+ # Thanks to Robert Klemme for his idea on lazy loading the subcommand option parsers.
8
+ #
9
+ # @author Rahul Kumar, Jun 2010
10
+ # @date 2010-06-20 22:33
11
+ #
12
+ # @examples
13
+ # if a program has subcommands foo and baz
14
+ #
15
+ # ruby opt.rb help
16
+ # ruby opt.rb --help
17
+ # ruby opt.rb help foo
18
+ # ruby opt.rb foo --help
19
+ # ruby opt.rb baz --quiet "some text"
20
+ # ruby opt.rb --verbose foo --force file.zzz
21
+ #
22
+ # == STEPS
23
+ # 1. define global_options (optional)
24
+ #
25
+ # global_options do |opts|
26
+ # opts.banner = "Usage: #{$0} [options] [subcommand [options]]"
27
+ # opts.description = "Stupid program that does something"
28
+ # opts.separator ""
29
+ # opts.separator "Global options are:"
30
+ # opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
31
+ # options[:verbose] = v
32
+ # end
33
+ # end
34
+ #
35
+ # 2. define commands using command().
36
+ # command :foo do |opts|
37
+ # opts.banner = "Usage: foo [options]"
38
+ # opts.description = "desc for foo"
39
+ # opts.on("-f", "--[no-]force", "force verbosely") do |v|
40
+ # options[:force] = v
41
+ # end
42
+ # end
43
+ #
44
+ # 3. call opt_parse()
45
+ #
46
+ # 4. As before, handle ARGS and options hash.
47
+ #
48
+ # TODO: add aliases for commands
49
+ ######################################
50
+ require 'optparse'
51
+
52
+ # Allow command to have a description to generate help
53
+ class OptionParser
54
+ attr_accessor :description
55
+ #attr_accessor :action
56
+ end
57
+
58
+ module Subcommands
59
+ ##
60
+ # specify a single command and all its options
61
+ # If multiple names are given, they are treated as aliases.
62
+ # Do repeatedly for each command
63
+ # Yields the optionparser
64
+ def command *names
65
+ #puts "inside command with #{names} "
66
+ name = names.shift
67
+ @commands ||= {}
68
+ @aliases ||= {}
69
+ if names.length > 0
70
+ names.each do |n|
71
+ #puts "aliases #{n} => #{name} "
72
+ @aliases[n.to_s] = name.to_s
73
+ end
74
+ end
75
+ # Thanks to Robert Klemme for the lazy loading idea.
76
+ opt = lambda { OptionParser.new do |opts|
77
+ yield opts
78
+ # append desc to banner in next line
79
+ opts.banner << "\n#{opts.description}\n" if opts.description
80
+ end }
81
+ @commands[name.to_s] = opt
82
+ end
83
+ # specify global options and banner and description
84
+ # Yields the optionparser
85
+ def global_options
86
+ if !defined? @global
87
+ @global = OptionParser.new do |opts|
88
+ yield opts
89
+ end
90
+ else
91
+ yield @global
92
+ end
93
+ end
94
+ # first parse global optinos
95
+ # then parse subcommand options if valid subcommand
96
+ # special case of "help command" so we print help of command - git style (3)
97
+ # in all invalid cases print global help
98
+ def opt_parse
99
+ # if user has not defined global, we need to create it
100
+ if !defined? @global
101
+ global_options do |opts|
102
+ opts.banner = "Usage: #{$0} [options] [subcommand [options]]"
103
+ opts.separator ""
104
+ opts.separator "Global options are:"
105
+ opts.on("-h", "--help", "Print this help") do |v|
106
+ puts @global
107
+ exit
108
+ end
109
+ opts.separator ""
110
+ opts.separator subtext
111
+ end
112
+ else
113
+ # user has defined some, but lets add subcommand information
114
+ cmdtext = "Commands are:"
115
+ @commands.each_pair do |c, opt|
116
+ desc = opt.call.description
117
+ cmdtext << "\n #{c} : #{desc}"
118
+ end
119
+
120
+ # print aliases
121
+ unless @aliases.empty?
122
+ cmdtext << "\n\nAliases: \n"
123
+ @aliases.each_pair { |name, val| cmdtext << " #{name} - #{val}" }
124
+ end
125
+
126
+ cmdtext << "\n\nSee '#{$0} help COMMAND' for more information on a specific command."
127
+
128
+ global_options do |opts|
129
+ # lets add the description user gave into banner
130
+ opts.banner << "\n#{opts.description}\n" if opts.description
131
+ opts.separator ""
132
+ opts.separator cmdtext
133
+ end
134
+ end
135
+ @global.order!
136
+ cmd = ARGV.shift
137
+ if cmd
138
+ #puts "Command: #{cmd} "
139
+ sc = @commands[cmd]
140
+ unless sc
141
+ # see if an alias exists
142
+ #puts "sc nil #{@aliases} "
143
+ alas = @aliases[cmd]
144
+ #puts "sc nil #{alas} "
145
+ sc = @commands[alas] if alas
146
+ #puts "sc nil #{sc} "
147
+ end
148
+ # if valid command parse the args
149
+ if sc
150
+ sc.call.order!
151
+ else
152
+ # else if help <command> then print its help GIT style (3)
153
+ if !ARGV.empty? and cmd == "help"
154
+ cmd = ARGV.shift
155
+ sc = @commands[cmd]
156
+ # if valid command print help, else print global help
157
+ if sc
158
+ #puts " 111 help foo/baz"
159
+ puts sc.call
160
+ else puts @global
161
+ end
162
+ else
163
+ # invalid command
164
+ puts @global
165
+ end
166
+ exit 0
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ if __FILE__ == $PROGRAM_NAME
173
+ include Subcommands
174
+ options = {}
175
+ appname = File.basename($0)
176
+ # global is optional
177
+ global_options do |opts|
178
+ opts.banner = "Usage: #{appname} [options] [subcommand [options]]"
179
+ opts.description = "Stupid program that does something"
180
+ opts.separator ""
181
+ opts.separator "Global options are:"
182
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
183
+ options[:verbose] = v
184
+ end
185
+ end
186
+ # define a command
187
+ command :foo, :goo do |opts|
188
+ opts.banner = "Usage: foo [options]"
189
+ opts.description = "desc for foo"
190
+ opts.on("-f", "--[no-]force", "force verbosely") do |v|
191
+ options[:force] = v
192
+ end
193
+ end
194
+ command :baz do |opts|
195
+ opts.banner = "Usage: baz [options]"
196
+ opts.description = "desc for baz"
197
+ opts.on("-q", "--[no-]quiet", "quietly run ") do |v|
198
+ options[:quiet] = v
199
+ end
200
+ end
201
+
202
+ # do the parsing.
203
+ opt_parse()
204
+
205
+ puts "options ......"
206
+ p options
207
+ puts "ARGV:"
208
+ p ARGV
209
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'subcommand'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestSubcommand < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: subcommand
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Rahul Kumar
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-21 00:00:00 +05:30
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: yard
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ description: Subcommand and alias facility for command line programs with elegant help printing
33
+ email: sentinel.1879@gmail.com
34
+ executables: []
35
+
36
+ extensions: []
37
+
38
+ extra_rdoc_files:
39
+ - LICENSE
40
+ - README.rdoc
41
+ - TODO
42
+ files:
43
+ - .document
44
+ - .gitignore
45
+ - LICENSE
46
+ - README.rdoc
47
+ - Rakefile
48
+ - VERSION
49
+ - lib/subcommand.rb
50
+ - test/helper.rb
51
+ - test/test_subcommand.rb
52
+ - TODO
53
+ has_rdoc: true
54
+ homepage: http://github.com/rkumar/subcommand
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options:
59
+ - --charset=UTF-8
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.6
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: A tiny wrapper over OptionParser giving simple, elegant subcommand facility
83
+ test_files:
84
+ - test/helper.rb
85
+ - test/test_subcommand.rb