commandant 0.2.0
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/.document +5 -0
- data/.gitignore +23 -0
- data/LICENSE +20 -0
- data/README.rdoc +34 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/lib/commandant.rb +76 -0
- data/lib/commandant/command.rb +30 -0
- data/spec/commandant/commands_spec.rb +45 -0
- data/spec/commandant_spec.rb +83 -0
- data/spec/fixtures/basic_runner.rb +12 -0
- data/spec/integration/run_spec.rb +24 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +9 -0
- metadata +106 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Rein Henrichs
|
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,34 @@
|
|
1
|
+
= commander
|
2
|
+
|
3
|
+
The simplest possible command line subcommand tool. It provides about half of
|
4
|
+
what you want and none of what you don't. If you don't like it, don't use it.
|
5
|
+
|
6
|
+
== Example:
|
7
|
+
|
8
|
+
#!/usr/bin/env ruby -rubygems
|
9
|
+
require 'commander'
|
10
|
+
include Commander
|
11
|
+
|
12
|
+
command :hello do
|
13
|
+
puts "Hello, World!"
|
14
|
+
end
|
15
|
+
|
16
|
+
command :argprint do |args| # Array of arguments, like ARGV
|
17
|
+
puts args
|
18
|
+
end
|
19
|
+
|
20
|
+
run
|
21
|
+
|
22
|
+
== Note on Patches/Pull Requests
|
23
|
+
|
24
|
+
* Fork the project.
|
25
|
+
* Make your feature addition or bug fix.
|
26
|
+
* Add tests for it. This is important so I don't break it in a
|
27
|
+
future version unintentionally.
|
28
|
+
* Commit, do not mess with rakefile, version, or history.
|
29
|
+
(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)
|
30
|
+
* Send me a pull request. Bonus points for topic branches.
|
31
|
+
|
32
|
+
== Copyright
|
33
|
+
|
34
|
+
Copyright (c) 2010 Rein Henrichs. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "commandant"
|
8
|
+
gem.summary = %Q{A simple library for writing commands with subcommands (like git)}
|
9
|
+
gem.email = "reinh@reinh.com"
|
10
|
+
gem.homepage = "http://github.com/reinh/commandant"
|
11
|
+
gem.authors = ["Rein Henrichs"]
|
12
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
13
|
+
gem.add_development_dependency "yard", ">= 0"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
spec.rcov_opts = ['--exclude /Library,spec/'] # not excluding /Library for some reason"
|
32
|
+
end
|
33
|
+
|
34
|
+
task :spec => :check_dependencies
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
begin
|
39
|
+
require 'yard'
|
40
|
+
YARD::Rake::YardocTask.new
|
41
|
+
rescue LoadError
|
42
|
+
task :yard do
|
43
|
+
abort "YARD is not available. In order to run yard, you must: sudo gem install yard"
|
44
|
+
end
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/lib/commandant.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
require 'commandant/command'
|
3
|
+
|
4
|
+
module Commandant
|
5
|
+
COMMANDS = {}
|
6
|
+
|
7
|
+
class UnknownCommand < NameError
|
8
|
+
def initialize(name); super "Unknown command `#{name}`" end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Call a given command by name
|
12
|
+
#
|
13
|
+
# @param [Symbol] name the name of the command to be called
|
14
|
+
# @param [Array] args the command's arguments
|
15
|
+
# @raise [UnknownCommand] attempt to call a command that does not exist
|
16
|
+
def self.call(name, args=nil)
|
17
|
+
raise UnknownCommand.new(name) unless COMMANDS[name]
|
18
|
+
COMMANDS[name].call(args)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Clears out all defined commands. Primarily useful for testing
|
22
|
+
def self.clear!
|
23
|
+
COMMANDS.clear
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates an alias for each given command.
|
27
|
+
#
|
28
|
+
# @param [Hash<Symbol => Symbol>] commands the aliases to create ( new name => old name )
|
29
|
+
# @example
|
30
|
+
# alias :br => :branch, :co => :checkout
|
31
|
+
def add_alias(commands)
|
32
|
+
commands.each do |new, old|
|
33
|
+
Commandant::COMMANDS[new] = Commandant::COMMANDS[old]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
module_function :add_alias
|
37
|
+
|
38
|
+
# Create a new command
|
39
|
+
#
|
40
|
+
# @param [Symbol] name the name of the command that is created
|
41
|
+
# @param [String, nil] description the command's description
|
42
|
+
# @yield The command that will be run
|
43
|
+
# @yieldparam [Array] args optional: arguments to the command (typically from ARGV)
|
44
|
+
#
|
45
|
+
# @example A Hello World! command
|
46
|
+
# Commandant.command :hello do
|
47
|
+
# puts "Hello World!"
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# Commandant.run "hello"
|
51
|
+
#
|
52
|
+
# @example A command with arguments
|
53
|
+
# Commandant.command :argprint do |args|
|
54
|
+
# puts args
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# Commandant.run "argprint foo bizz bazz"
|
58
|
+
def command(name, description="", &command)
|
59
|
+
Command.new(name, description, &command)
|
60
|
+
end
|
61
|
+
module_function :command
|
62
|
+
|
63
|
+
# Runs a given commandline by parsing the command name and arguments. If no
|
64
|
+
# command is given, defaults to a command called :main. If that is not
|
65
|
+
# present, an UnknownCommand error will be raised.
|
66
|
+
#
|
67
|
+
# @param [Array] cmdline the command line args to be run
|
68
|
+
# @raise [UnknownCommand] command is unknown and no :main command is available
|
69
|
+
def run(cmdline=ARGV)
|
70
|
+
name, *args = cmdline
|
71
|
+
name, args = :main, [name, *args] if name.nil? || COMMANDS[name.to_sym].nil? && COMMANDS[:main]
|
72
|
+
Commandant.call name.to_sym, args.compact
|
73
|
+
end
|
74
|
+
module_function :run
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Commandant
|
2
|
+
class Command
|
3
|
+
attr_reader :description
|
4
|
+
|
5
|
+
# Create a new command by name and add it to the commands list.
|
6
|
+
#
|
7
|
+
# @param [Symbol] name the name of the command
|
8
|
+
# @param [String, nil] description the command's description
|
9
|
+
# @raise [ArgumentError] if a command block is not provided
|
10
|
+
# @raise [ArgumentError] if a command already exists by that name
|
11
|
+
def initialize(name, description=nil, &command)
|
12
|
+
raise ArgumentError, "Must provide a command block" unless command
|
13
|
+
raise ArgumentError, "Command already exists: #{name}" if COMMANDS[name]
|
14
|
+
|
15
|
+
@name = name
|
16
|
+
@description = description
|
17
|
+
@command = command
|
18
|
+
|
19
|
+
COMMANDS[@name] = self
|
20
|
+
end
|
21
|
+
|
22
|
+
# Execute the command
|
23
|
+
#
|
24
|
+
# @param [Array] args the command's arguments
|
25
|
+
def call(args=nil)
|
26
|
+
@command.call(args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Commandant::Command do
|
4
|
+
before { Commandant.clear! }
|
5
|
+
subject { Commandant::Command }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
it "requres a name" do
|
9
|
+
lambda { subject.new(){ "this is the command" }
|
10
|
+
}.should raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "requires a block" do
|
14
|
+
lambda { subject.new(:name)
|
15
|
+
}.should raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts a description" do
|
19
|
+
subject.new(:name, "description"){}.description.should == "description"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "adds the command to the list of commands by name" do
|
23
|
+
command = subject.new(:name){ "block" }
|
24
|
+
Commandant::COMMANDS[:name].should == command
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "when the command already exists" do
|
28
|
+
before { Commandant::Command.new(:dup) { "I am a duplicate" } }
|
29
|
+
|
30
|
+
it do
|
31
|
+
lambda {
|
32
|
+
Commandant.command(:dup) { "I am a duplicate" }
|
33
|
+
}.should raise_error(ArgumentError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#call" do
|
39
|
+
subject { Commandant::Command.new(:name){ "called" } }
|
40
|
+
|
41
|
+
it "calls the given command" do
|
42
|
+
subject.call.should == "called"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Commandant do
|
4
|
+
before { Commandant.clear! }
|
5
|
+
|
6
|
+
describe ".call" do
|
7
|
+
it "calls the given command" do
|
8
|
+
Commandant.command(:test) { "test" }
|
9
|
+
Commandant.call(:test).should == "test"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "passes args if given" do
|
13
|
+
Commandant.command(:test) {|args| args }
|
14
|
+
|
15
|
+
Commandant.call(:test, "args").should == "args"
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "when the command is unavailable" do
|
19
|
+
subject { lambda{Commandant.call(:missing)} }
|
20
|
+
it { should raise_error(Commandant::UnknownCommand) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".clear!" do
|
25
|
+
before { Commandant.command(:main){"main"} }
|
26
|
+
|
27
|
+
it "should empty the command list" do
|
28
|
+
lambda {
|
29
|
+
Commandant.clear!
|
30
|
+
}.should change{Commandant::COMMANDS.empty?}.from(false).to(true)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".add_alias" do
|
35
|
+
it "creates an alias for a given command" do
|
36
|
+
Commandant.command(:hello) { "hello" }
|
37
|
+
Commandant.add_alias :hi => :hello
|
38
|
+
|
39
|
+
Commandant.run(:hi).should == "hello"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ".command" do
|
44
|
+
subject { Commandant.command(:test) { "this is a test" } }
|
45
|
+
it "creates a new Command with the given name and command block" do
|
46
|
+
should be_a_kind_of(Commandant::Command)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ".run" do
|
51
|
+
before { Commandant.command(:main) {|args| "main called with #{args.inspect}" } }
|
52
|
+
|
53
|
+
it "runs the command specified" do
|
54
|
+
Commandant::COMMANDS[:main].should_receive(:call)
|
55
|
+
|
56
|
+
Commandant.run("main")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "runs the command with arguments" do
|
60
|
+
Commandant::COMMANDS[:main].should_receive(:call).with(["args"])
|
61
|
+
|
62
|
+
Commandant.run(%w{main args})
|
63
|
+
end
|
64
|
+
|
65
|
+
it "defaults to the :main command, if available" do
|
66
|
+
Commandant.run(%w{ some args }).should == 'main called with ["some", "args"]'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "runs the main command if no arguments are passed" do
|
70
|
+
Commandant.run(nil).should == "main called with []"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "raises an errur of no main command is available" do
|
74
|
+
Commandant.clear!
|
75
|
+
|
76
|
+
lambda {
|
77
|
+
Commandant.run(%w{ some args })
|
78
|
+
}.should raise_error(Commandant::UnknownCommand)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Integration:", "Running a command" do
|
4
|
+
def running(args, &block)
|
5
|
+
IO.popen "ruby spec/fixtures/basic_runner.rb #{args}", &block
|
6
|
+
end
|
7
|
+
private :running
|
8
|
+
|
9
|
+
describe "that prints \"main\" to STDOUT" do
|
10
|
+
it "should output \"main\" to STDOUT" do
|
11
|
+
running :main do |io|
|
12
|
+
io.read.should == "main"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "that prints its arguments to STDOUT" do
|
18
|
+
it "should output its arguments to STDOUT" do
|
19
|
+
running "argprinter foo biz bazz" do |io|
|
20
|
+
io.read.should == %w{foo biz bazz}.inspect
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/rcov.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--exclude /Library
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: commandant
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Rein Henrichs
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-21 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
31
|
+
version: 1.2.9
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: yard
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
description:
|
47
|
+
email: reinh@reinh.com
|
48
|
+
executables: []
|
49
|
+
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
extra_rdoc_files:
|
53
|
+
- LICENSE
|
54
|
+
- README.rdoc
|
55
|
+
files:
|
56
|
+
- .document
|
57
|
+
- .gitignore
|
58
|
+
- LICENSE
|
59
|
+
- README.rdoc
|
60
|
+
- Rakefile
|
61
|
+
- VERSION
|
62
|
+
- lib/commandant.rb
|
63
|
+
- lib/commandant/command.rb
|
64
|
+
- spec/commandant/commands_spec.rb
|
65
|
+
- spec/commandant_spec.rb
|
66
|
+
- spec/fixtures/basic_runner.rb
|
67
|
+
- spec/integration/run_spec.rb
|
68
|
+
- spec/rcov.opts
|
69
|
+
- spec/spec.opts
|
70
|
+
- spec/spec_helper.rb
|
71
|
+
has_rdoc: true
|
72
|
+
homepage: http://github.com/reinh/commandant
|
73
|
+
licenses: []
|
74
|
+
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options:
|
77
|
+
- --charset=UTF-8
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
version: "0"
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.3.6
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: A simple library for writing commands with subcommands (like git)
|
101
|
+
test_files:
|
102
|
+
- spec/commandant/commands_spec.rb
|
103
|
+
- spec/commandant_spec.rb
|
104
|
+
- spec/fixtures/basic_runner.rb
|
105
|
+
- spec/integration/run_spec.rb
|
106
|
+
- spec/spec_helper.rb
|