mercenary 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 467dae27c989bd4d07318b1965e6e28930f90aeb
4
- data.tar.gz: be71811e5f88c21cc07105822a0d77874893617f
3
+ metadata.gz: 3f441ca546550e0899b4f6aa2135994f482d5d29
4
+ data.tar.gz: d5d7fd3ecd26cf8065b78fd51575c0fe197b9557
5
5
  SHA512:
6
- metadata.gz: bf722d831a506ee191a2609b3420e132f50ddd4d00f87cc3686376767321a77af4310c0f71e481c1138d610b0780395e6b73fda297829b9a8ad8d3846e4160cc
7
- data.tar.gz: c9080a9dbcdda0da115f5d22b511bb20d6e7ce1fe08611076c81c007f69dcd72b96c8a2d6fde4b5694c6ee76c9878cba30f23b9507e1528e8a44a48965c4f9e0
6
+ metadata.gz: bd7eaa27cbe85b82a1997eb6b73b429707c5a63c38e1f09b144eed56f04e819e35759e2b3a7d65bb4c977d87998e7d174544f023c2aa4a0e4f32362f5b9dcf9f
7
+ data.tar.gz: dbf6c19a22daf82dffd6ca7007d9fea7e32e18fe170da8c972779db8e2e76826956028d90febc845b75c79f11377817da42683d3db3291d4faf22440c47b27ff
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ - 2.0.0
6
+ script: "bundle exec rspec"
7
+ notification:
8
+ recipients:
9
+ - mercenary@jekyllrb.com
10
+ email:
11
+ on_success: change
12
+ on_failure: change
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Mercenary
2
2
 
3
- TODO: Write a gem description
3
+ Lightweight and flexible library for writing command-line apps in Ruby.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/jekyll/mercenary.png)](https://travis-ci.org/jekyll/mercenary)
4
6
 
5
7
  ## Installation
6
8
 
@@ -18,7 +20,39 @@ Or install it yourself as:
18
20
 
19
21
  ## Usage
20
22
 
21
- TODO: Write usage instructions here
23
+ ```ruby
24
+ Mercenary.program(:jekyll) do |p|
25
+ p.version Jekyll::VERSION
26
+ p.description 'Jekyll is a blog-aware, static site generator in Ruby'
27
+
28
+ p.command(:new) do |c|
29
+ c.syntax "jekyll new PATH"
30
+ c.description "Creates a new Jekyll site scaffold in PATH"
31
+
32
+ c.action do |args, options|
33
+ Jekyll::Commands::New.process(args)
34
+ end
35
+ end
36
+
37
+ p.command(:import) do |c|
38
+ c.syntax "jekyll import <platform> [options]"
39
+ c.description "Import your old blog to Jekyll"
40
+
41
+ c.action do |args, options|
42
+ begin
43
+ require "jekyll-import"
44
+ rescue
45
+ msg = "You must install the 'jekyll-import' gem before continuing.\n"
46
+ msg += "* Do this by running `gem install jekyll-import`.\n"
47
+ msg += "* Or if you need root privileges, run `sudo gem install jekyll-import`."
48
+ abort msg
49
+ end
50
+
51
+ Jekyll::Commands::Import.process(args.first, options)
52
+ end
53
+ end
54
+ end
55
+ ```
22
56
 
23
57
  ## Contributing
24
58
 
data/lib/mercenary.rb CHANGED
@@ -1,5 +1,9 @@
1
+ lib = File.expand_path('../', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
1
4
  require "mercenary/version"
2
5
  require "optparse"
6
+ require "logger"
3
7
 
4
8
  module Mercenary
5
9
  autoload :Command, "mercenary/command"
@@ -9,6 +9,13 @@ module Mercenary
9
9
  attr_reader :map
10
10
  attr_accessor :parent
11
11
 
12
+ # Public: Creates a new Command
13
+ #
14
+ # name - the name of the command
15
+ # parent - (optional) the instancce of Mercenary::Command which you wish to
16
+ # be the parent of this command
17
+ #
18
+ # Returns nothing
12
19
  def initialize(name, parent = nil)
13
20
  @name = name
14
21
  @options = []
@@ -18,46 +25,114 @@ module Mercenary
18
25
  @parent = parent
19
26
  end
20
27
 
21
- def syntax(syntax)
22
- @syntax = syntax
28
+ # Public: Sets or gets the syntax string
29
+ #
30
+ # syntax - the string which describes this command's usage syntax (optional)
31
+ #
32
+ # Returns the syntax string and sets it if an argument is present
33
+ def syntax(syntax = nil)
34
+ @syntax = syntax if syntax
35
+ @syntax
23
36
  end
24
37
 
25
- def description(desc)
26
- @description = desc
38
+ # Public: Sets or gets the command description
39
+ #
40
+ # description - the description of what the command does (optional)
41
+ #
42
+ # Returns the description and sets it if an argument is present
43
+ def description(desc = nil)
44
+ @description = desc if desc
45
+ @description
27
46
  end
28
47
 
48
+ # Public: Adds an option switch
49
+ #
50
+ # sym - the variable key which is used to identify the value of the switch
51
+ # at runtime in the options hash
52
+ #
53
+ # Returns nothing
29
54
  def option(sym, *options)
30
55
  @options << options
31
56
  @map[options[0]] = sym
32
57
  end
33
58
 
59
+ # Public: Adds a subcommand
60
+ #
61
+ # cmd_name - the name of the command
62
+ # block - a block accepting the new instance of Mercenary::Command to be
63
+ # modified (optional)
64
+ #
65
+ # Returns nothing
34
66
  def command(cmd_name)
35
67
  cmd = Command.new(cmd_name, self)
36
68
  yield cmd
37
69
  @commands[cmd_name] = cmd
38
70
  end
39
71
 
72
+ # Public: Add an alias for this command's name to be attached to the parent
73
+ #
74
+ # cmd_name - the name of the alias
75
+ #
76
+ # Returns nothing
40
77
  def alias(cmd_name)
78
+ logger.debug "adding alias to parent for self: '#{cmd_name}'"
41
79
  @parent.commands[cmd_name] = self
42
80
  end
43
81
 
82
+ # Public: Add an action Proc to be executed at runtime
83
+ #
84
+ # block - the Proc to be executed at runtime
85
+ #
86
+ # Returns nothing
44
87
  def action(&block)
45
88
  @actions << block
46
89
  end
47
90
 
91
+ # Public: Fetch a Logger (stdlib)
92
+ #
93
+ # level - the logger level (a Logger constant, see docs for more info)
94
+ #
95
+ # Returns the instance of Logger
96
+ def logger(level = Logger::INFO)
97
+ unless @logger
98
+ @logger = Logger.new(STDOUT)
99
+ @logger.formatter = proc do |severity, datetime, progname, msg|
100
+ "#{ident} (#{severity}): #{msg}\n"
101
+ end
102
+ end
103
+
104
+ @logger.level = level
105
+ @logger
106
+ end
107
+
108
+ # Public: Run the command
109
+ #
110
+ # argv - an array of string args
111
+ # opts - the instance of OptionParser
112
+ # config - the output config hash
113
+ #
114
+ # Returns the command to be executed
48
115
  def go(argv, opts, config)
116
+ opts.banner = "Usage: #{syntax}"
49
117
  process_options(opts, config)
50
118
 
51
119
  if argv[0] && cmd = commands[argv[0].to_sym]
52
- puts "Found #{cmd.name}"
120
+ logger.debug "Found subcommand '#{cmd.name}'"
53
121
  argv.shift
54
122
  cmd.go(argv, opts, config)
55
123
  else
56
- puts "No additional command found, time to exec"
124
+ logger.debug "No additional command found, time to exec"
57
125
  self
58
126
  end
59
127
  end
60
128
 
129
+ # Public: Add this command's options to OptionParser and set a default
130
+ # action of setting the value of the option to the inputted hash
131
+ #
132
+ # opts - instance of OptionParser
133
+ # config - the Hash in which the option values should be placed
134
+ #
135
+ # Returns nothing
61
136
  def process_options(opts, config)
62
137
  options.each do |o|
63
138
  opts.on(*o) do |x|
@@ -66,13 +141,29 @@ module Mercenary
66
141
  end
67
142
  end
68
143
 
144
+ # Public: Check if this command has a subcommand
145
+ #
146
+ # sub_command - the name of the subcommand
147
+ #
148
+ # Returns true if this command is the parent of a command of name
149
+ # 'sub_command' and false otherwise
150
+ def has_command?(sub_command)
151
+ commands.keys.include?(sub_command)
152
+ end
153
+
154
+ # Public: Identify this command
155
+ #
156
+ # Returns a string which identifies this command
69
157
  def ident
70
158
  "<Command name=#{name}>"
71
159
  end
72
160
 
73
- def inspect
161
+ # Public: Build a string containing the command name, options and any subcommands
162
+ #
163
+ # Returns the string identifying this command, its options and its subcommands
164
+ def to_s
74
165
  msg = ''
75
- msg += "Command #{name}\n"
166
+ msg += "Command: #{name}\n"
76
167
  options.each { |o| msg += " " + o.inspect + "\n"}
77
168
  msg += "\n"
78
169
  commands.each { |k, v| msg += commands[k].inspect }
@@ -1,37 +1,50 @@
1
1
  module Mercenary
2
2
  class Program < Command
3
- attr_reader :version
4
- attr_reader :description
5
3
  attr_reader :optparse
6
4
  attr_reader :config
7
5
 
6
+ # Public: Creates a new Program
7
+ #
8
+ # name - the name of the program
9
+ #
10
+ # Returns nothing
8
11
  def initialize(name)
9
12
  @config = {}
10
13
  super(name)
11
14
  end
12
15
 
13
- def version(version)
14
- @version = version
15
- end
16
-
17
- def description(description)
18
- @description = description
16
+ # Public: Sets or gets the program version
17
+ #
18
+ # version - the program version (optional)
19
+ #
20
+ # Returns the version and sets it if an argument is present
21
+ def version(version = nil)
22
+ @version = version if version
23
+ @version
19
24
  end
20
25
 
26
+ # Public: Run the program
27
+ #
28
+ # argv - an array of string args (usually ARGV)
29
+ #
30
+ # Returns nothing
21
31
  def go(argv)
22
- p argv
23
- puts
24
- p self
32
+ logger.debug("Using args passed in: #{argv.inspect}")
25
33
 
26
34
  cmd = nil
27
35
 
28
36
  @optparse = OptionParser.new do |opts|
29
37
  cmd = super(argv, opts, @config)
38
+
39
+ opts.on('-v' '--version', 'Print the version') do
40
+ puts "#{name} #{version}"
41
+ abort
42
+ end
30
43
  end
31
44
 
32
45
  @optparse.parse!(argv)
33
46
 
34
- p @config
47
+ logger.debug("Parsed config: #{@config.inspect}")
35
48
 
36
49
  cmd.actions.each { |a| a.call(argv, @config) }
37
50
  end
@@ -1,3 +1,3 @@
1
1
  module Mercenary
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/mercenary.gemspec CHANGED
@@ -6,11 +6,11 @@ require 'mercenary/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "mercenary"
8
8
  spec.version = Mercenary::VERSION
9
- spec.authors = ["Parker Moore", "Tom Preston-Werner"]
10
- spec.email = ["parkrmoore@gmail.com", "tom@mojombo.com"]
11
- spec.description = %q{Write better command-line apps.}
12
- spec.summary = %q{Write better command-line apps.}
13
- spec.homepage = "http://github.com/jekyll/mercenary"
9
+ spec.authors = ["Tom Preston-Werner", "Parker Moore"]
10
+ spec.email = ["tom@mojombo.com", "parkrmoore@gmail.com"]
11
+ spec.description = %q{Lightweight and flexible library for writing command-line apps in Ruby.}
12
+ spec.summary = %q{Lightweight and flexible library for writing command-line apps in Ruby.}
13
+ spec.homepage = "https://github.com/jekyll/mercenary"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec", "~> 2.14"
23
24
  end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ describe(Mercenary::Command) do
4
+
5
+ context "a basic command" do
6
+ let(:command) { Mercenary::Command.new(:my_name) }
7
+ let(:command_with_parent) do
8
+ Mercenary::Command.new(
9
+ :i_have_parent,
10
+ parent
11
+ )
12
+ end
13
+ let(:parent) { Mercenary::Command.new(:my_parent) }
14
+ let(:add_sub) do
15
+ Proc.new do |c|
16
+ c.command(:sub_command) { |p| }
17
+ end
18
+ end
19
+
20
+ it "can be created with just a name" do
21
+ expect(command.name).to eql(:my_name)
22
+ end
23
+
24
+ it "can hold a parent command" do
25
+ expect(command_with_parent.parent).to eql(parent)
26
+ end
27
+
28
+ it "can create subcommands" do
29
+ expect(add_sub.call(command)).to be_a(Mercenary::Command)
30
+ expect(add_sub.call(command).parent).to eq(command)
31
+ end
32
+
33
+ it "can set its syntax" do
34
+ syntax_string = "my_name [options]"
35
+ cmd = described_class.new(:my_name)
36
+ cmd.syntax syntax_string
37
+ expect(cmd.syntax).to eq(syntax_string)
38
+ end
39
+
40
+ it "can set its description" do
41
+ desc = "run all the things"
42
+ command.description desc
43
+ expect(command.description).to eq(desc)
44
+ end
45
+
46
+ it "can set its options" do
47
+ name = "show_drafts"
48
+ opt = ['--drafts', 'Render posts in the _drafts folder']
49
+ command.option name, *opt
50
+ expect(command.options).to eq([opt])
51
+ expect(command.map).to include({opt.first => name})
52
+ end
53
+ end
54
+
55
+ end
File without changes
@@ -0,0 +1,15 @@
1
+ lib = File.expand_path('../../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'mercenary'
4
+
5
+ RSpec.configure do |config|
6
+ config.treat_symbols_as_metadata_keys_with_true_values = true
7
+ config.run_all_when_everything_filtered = true
8
+ config.filter_run :focus
9
+
10
+ # Run specs in random order to surface order dependencies. If you find an
11
+ # order dependency and want to debug it, you can fix the order by providing
12
+ # the seed, which is printed after each run.
13
+ # --seed 1234
14
+ config.order = 'random'
15
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mercenary
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - Parker Moore
8
7
  - Tom Preston-Werner
8
+ - Parker Moore
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-06 00:00:00.000000000 Z
12
+ date: 2013-11-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -39,15 +39,31 @@ dependencies:
39
39
  - - '>='
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
- description: Write better command-line apps.
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '2.14'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '2.14'
56
+ description: Lightweight and flexible library for writing command-line apps in Ruby.
43
57
  email:
44
- - parkrmoore@gmail.com
45
58
  - tom@mojombo.com
59
+ - parkrmoore@gmail.com
46
60
  executables: []
47
61
  extensions: []
48
62
  extra_rdoc_files: []
49
63
  files:
50
64
  - .gitignore
65
+ - .rspec
66
+ - .travis.yml
51
67
  - Gemfile
52
68
  - LICENSE.txt
53
69
  - README.md
@@ -57,7 +73,10 @@ files:
57
73
  - lib/mercenary/program.rb
58
74
  - lib/mercenary/version.rb
59
75
  - mercenary.gemspec
60
- homepage: http://github.com/jekyll/mercenary
76
+ - spec/command_spec.rb
77
+ - spec/program_spec.rb
78
+ - spec/spec_helper.rb
79
+ homepage: https://github.com/jekyll/mercenary
61
80
  licenses:
62
81
  - MIT
63
82
  metadata: {}
@@ -80,5 +99,8 @@ rubyforge_project:
80
99
  rubygems_version: 2.0.3
81
100
  signing_key:
82
101
  specification_version: 4
83
- summary: Write better command-line apps.
84
- test_files: []
102
+ summary: Lightweight and flexible library for writing command-line apps in Ruby.
103
+ test_files:
104
+ - spec/command_spec.rb
105
+ - spec/program_spec.rb
106
+ - spec/spec_helper.rb