mercenary 0.2.1 → 0.3.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: 3ab95f854272a3615464fc0189bb7dd05de87115
4
- data.tar.gz: 5cb99b4246ee7194d1c69a142ef2b8ff8f1e3b3a
3
+ metadata.gz: d9ebb7e735aa1147cbcc69420fa3a934830c0415
4
+ data.tar.gz: 120e555e1d05e2af4e674b42cd9143195310b92e
5
5
  SHA512:
6
- metadata.gz: d557c2b7ec5b68148a50aded7101043f5de8f8e2024faa76fd745df535fb8c06ade969c9ebe3caa0f9345d777eedef954645e59777e4ac7767b638d7e924ebec
7
- data.tar.gz: 75495874c6ee7cd0c287005f4ef4ce2e4089ff07557014812f516a80805c04d7d84a6b7a021b97f8080721004bc0d7220c3e2376542e90728cb22bdac818524c
6
+ metadata.gz: becf09d037cb3f6475239595c42deba5c89791ccc13f5d2c622d1a88769d91e89c7da2685f1c238f2e41d0308b81cd81679f7ac7352fffa93d36cf7d989a7975
7
+ data.tar.gz: 2ca3a69a6039ab31343002957dec0c8753181c17817d3d6b59afaa7dc6186e3d78f501979ffae98e3ecb4ba730bdbd46e4d8d5974f653f25fedf603fc9c75cde
data/.travis.yml CHANGED
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
3
  - 1.9.3
5
4
  - 2.0.0
5
+ - 2.1.0
6
6
  script: "./script/cibuild"
7
7
  notifications:
8
8
  email:
data/History.markdown CHANGED
@@ -8,6 +8,25 @@
8
8
 
9
9
  ### Development Fixes
10
10
 
11
+ ## 0.3.0 / 2014-02-20
12
+
13
+ ### Major Enhancements
14
+
15
+ * Officially drop 1.8.7 support (#14)
16
+ * Allow Commands to set their own versions (#17)
17
+ * Show subcommands, options and usage in help and attach to all commands (#18)
18
+ * Add `-t, --trace` to allow full exception backtrace to print, otherwise print
19
+ just the error message (#19)
20
+
21
+ ### Minor Enhancements
22
+
23
+ * Logging state is maintained throughout process (#12)
24
+ * Tidy up Command#logger output (#21)
25
+
26
+ ### Development Fixes
27
+
28
+ * Added specs for `Program` (#13)
29
+
11
30
  ## 0.2.1 / 2013-12-25
12
31
 
13
32
  ### Bug Fixes
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Parker Moore
1
+ Copyright (c) 2013-2014 Parker Moore
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -18,6 +18,8 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install mercenary
20
20
 
21
+ **Note: Mercenary may not work with Ruby < 1.9.3.**
22
+
21
23
  ## Usage
22
24
 
23
25
  ```ruby
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
4
+
5
+ require "mercenary"
6
+
7
+ # This example sets the logging mode of mercenary to
8
+ # debug. Logging messages from "p.logger.debug" will
9
+ # be output to STDOUT.
10
+
11
+ Mercenary.program(:help_dialogue) do |p|
12
+
13
+ p.version "2.0.1"
14
+ p.description 'An example of the help dialogue in Mercenary'
15
+ p.syntax 'help_dialogue <subcommand>'
16
+
17
+ p.command(:some_subcommand) do |c|
18
+ c.version '1.4.2'
19
+ c.syntax 'some_subcommand <subcommand> [options]'
20
+ c.description 'Some subcommand to do something'
21
+ c.option 'an_option', '-o', '--option', 'Some option'
22
+
23
+ c.command(:yet_another_sub) do |f|
24
+ f.syntax 'yet_another_sub [options]'
25
+ f.description 'Do amazing things'
26
+ f.option 'blah', '-b', '--blah', 'Trigger blah flag'
27
+ f.option 'heh', '-H ARG', '--heh ARG', 'Give a heh'
28
+
29
+ f.action do |args, options|
30
+ print "Args: "
31
+ p args
32
+ print "Opts: "
33
+ p options
34
+ end
35
+ end
36
+ end
37
+
38
+ p.command(:another_subcommand) do |c|
39
+ c.syntax 'another_subcommand <subcommand> [options]'
40
+ c.description 'Another subcommand to do something different.'
41
+ c.option 'an_option', '-O', '--option', 'Some option'
42
+ c.option 'another_options', '--pluginzzz', 'Set where the plugins should be found from'
43
+ end
44
+
45
+ end
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
4
+
5
+ require "mercenary"
6
+
7
+ # This example sets the logging mode of mercenary to
8
+ # debug. Logging messages from "p.logger.debug" will
9
+ # be output to STDOUT.
10
+
11
+ Mercenary.program(:logger_output) do |p|
12
+
13
+ p.version "5.2.6"
14
+ p.description 'An example of turning on logging for Mercenary.'
15
+ p.syntax 'logger_output'
16
+
17
+
18
+ p.logger.info "The default log level is INFO. So this will output."
19
+ p.logger.debug "Since DEBUG is below INFO, this will not output."
20
+
21
+ p.logger(Logger::DEBUG)
22
+ p.logger.debug "Logger level now set to DEBUG. So everything will output."
23
+
24
+ p.logger.debug "Example of DEBUG level message."
25
+ p.logger.info "Example of INFO level message."
26
+ p.logger.warn "Example of WARN level message."
27
+ p.logger.error "Example of ERROR level message."
28
+ p.logger.fatal "Example of FATAL level message."
29
+ p.logger.unknown "Example of UNKNOWN level message."
30
+
31
+ p.action do |args, options|
32
+
33
+ p.logger(Logger::INFO)
34
+ p.logger.debug "Logger level back to INFO. This line will not output."
35
+ p.logger.info "This INFO message will output."
36
+
37
+ end
38
+
39
+ end
data/examples/trace.rb ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
4
+
5
+ require "mercenary"
6
+
7
+ # This example sets the logging mode of mercenary to
8
+ # debug. Logging messages from "p.logger.debug" will
9
+ # be output to STDOUT.
10
+
11
+ Mercenary.program(:trace) do |p|
12
+
13
+ p.version "2.0.1"
14
+ p.description 'An example of traces in Mercenary'
15
+ p.syntax 'trace <subcommand>'
16
+
17
+ p.action do |_, _|
18
+ raise ArgumentError.new("YOU DID SOMETHING TERRIBLE YOU BUFFOON")
19
+ end
20
+
21
+ end
data/lib/mercenary.rb CHANGED
@@ -6,8 +6,10 @@ require "optparse"
6
6
  require "logger"
7
7
 
8
8
  module Mercenary
9
- autoload :Command, "mercenary/command"
10
- autoload :Program, "mercenary/program"
9
+ autoload :Command, "mercenary/command"
10
+ autoload :Option, "mercenary/option"
11
+ autoload :Presenter, "mercenary/presenter"
12
+ autoload :Program, "mercenary/program"
11
13
 
12
14
  # Public: Instantiate a new program and execute.
13
15
  #
@@ -8,6 +8,7 @@ module Mercenary
8
8
  attr_accessor :actions
9
9
  attr_reader :map
10
10
  attr_accessor :parent
11
+ attr_reader :trace
11
12
 
12
13
  # Public: Creates a new Command
13
14
  #
@@ -17,12 +18,23 @@ module Mercenary
17
18
  #
18
19
  # Returns nothing
19
20
  def initialize(name, parent = nil)
20
- @name = name
21
- @options = []
22
- @commands = {}
23
- @actions = []
24
- @map = {}
25
- @parent = parent
21
+ @name = name
22
+ @options = []
23
+ @commands = {}
24
+ @actions = []
25
+ @map = {}
26
+ @parent = parent
27
+ @trace = false
28
+ end
29
+
30
+ # Public: Sets or gets the command version
31
+ #
32
+ # version - the command version (optional)
33
+ #
34
+ # Returns the version and sets it if an argument is non-nil
35
+ def version(version = nil)
36
+ @version = version if version
37
+ @version
26
38
  end
27
39
 
28
40
  # Public: Sets or gets the syntax string
@@ -32,7 +44,12 @@ module Mercenary
32
44
  # Returns the syntax string and sets it if an argument is present
33
45
  def syntax(syntax = nil)
34
46
  @syntax = syntax if syntax
35
- @syntax
47
+ syntax_list = []
48
+ if parent
49
+ syntax_list << parent.syntax.to_s.gsub(/<[\w\s-]+>/, '').gsub(/\[[\w\s-]+\]/, '').strip
50
+ end
51
+ syntax_list << (@syntax || name.to_s)
52
+ syntax_list.join(" ")
36
53
  end
37
54
 
38
55
  # Public: Sets or gets the command description
@@ -71,8 +88,9 @@ module Mercenary
71
88
  #
72
89
  # Returns nothing
73
90
  def option(sym, *options)
74
- @options << options
75
- @map[options[0]] = sym
91
+ new_option = Option.new(sym, options)
92
+ @options << new_option
93
+ @map[new_option.hash] = sym
76
94
  end
77
95
 
78
96
  # Public: Adds a subcommand
@@ -112,15 +130,16 @@ module Mercenary
112
130
  # level - the logger level (a Logger constant, see docs for more info)
113
131
  #
114
132
  # Returns the instance of Logger
115
- def logger(level = Logger::INFO)
133
+ def logger(level = nil)
116
134
  unless @logger
117
135
  @logger = Logger.new(STDOUT)
136
+ @logger.level = level || Logger::INFO
118
137
  @logger.formatter = proc do |severity, datetime, progname, msg|
119
- "#{ident} (#{severity}): #{msg}\n"
138
+ "#{identity} | " << "#{severity.downcase.capitalize}:".ljust(7) << " #{msg}\n"
120
139
  end
121
140
  end
122
141
 
123
- @logger.level = level
142
+ @logger.level = level unless level.nil?
124
143
  @logger
125
144
  end
126
145
 
@@ -134,6 +153,7 @@ module Mercenary
134
153
  def go(argv, opts, config)
135
154
  opts.banner = "Usage: #{syntax}"
136
155
  process_options(opts, config)
156
+ add_default_options(opts)
137
157
 
138
158
  if argv[0] && cmd = commands[argv[0].to_sym]
139
159
  logger.debug "Found subcommand '#{cmd.name}'"
@@ -153,13 +173,36 @@ module Mercenary
153
173
  #
154
174
  # Returns nothing
155
175
  def process_options(opts, config)
156
- options.each do |o|
157
- opts.on(*o) do |x|
158
- config[map[o[0]]] = x
176
+ options.each do |option|
177
+ opts.on(*option.for_option_parser) do |x|
178
+ config[map[option.hash]] = x
159
179
  end
160
180
  end
161
181
  end
162
182
 
183
+ # Public: Add version and help options to the command
184
+ #
185
+ # opts - instance of OptionParser
186
+ #
187
+ # Returns nothing
188
+ def add_default_options(opts)
189
+ option 'show_help', '-h', '--help', 'Show this message'
190
+ option 'show_version', '-v', '--version', 'Print the name and version'
191
+ opts.on("-v", "--version", "Print the version") do
192
+ puts "#{name} #{version}"
193
+ abort
194
+ end
195
+
196
+ opts.on('-t', '--trace', 'Show full backtrace if an error occurs') do
197
+ @trace = true
198
+ end
199
+
200
+ opts.on_tail("-h", "--help", "Show this message") do
201
+ puts self
202
+ exit
203
+ end
204
+ end
205
+
163
206
  # Public: Execute all actions given the inputted args and options
164
207
  #
165
208
  # argv - (optional) command-line args (sans opts)
@@ -188,19 +231,39 @@ module Mercenary
188
231
  #
189
232
  # Returns a string which identifies this command
190
233
  def ident
191
- "<Command name=#{name}>"
234
+ "<Command name=#{identity}>"
235
+ end
236
+
237
+ # Public: Get the full identity (name & version) of this command
238
+ #
239
+ # Returns a string containing the name and version if it exists
240
+ def identity
241
+ "#{full_name} #{version if version}".strip
242
+ end
243
+
244
+ # Public: Get the name of the current command plus that of
245
+ # its parent commands
246
+ #
247
+ # Returns the full name of the command
248
+ def full_name
249
+ the_name = []
250
+ the_name << parent.full_name if parent && parent.full_name
251
+ the_name << name
252
+ the_name.join(" ")
253
+ end
254
+
255
+ # Public: Build a string containing a summary of the command
256
+ #
257
+ # Returns a one-line summary of the command.
258
+ def summarize
259
+ " #{name.to_s.ljust(20)} #{description}"
192
260
  end
193
261
 
194
262
  # Public: Build a string containing the command name, options and any subcommands
195
263
  #
196
264
  # Returns the string identifying this command, its options and its subcommands
197
265
  def to_s
198
- msg = ''
199
- msg += "Command: #{name}\n"
200
- options.each { |o| msg += " " + o.inspect + "\n"}
201
- msg += "\n"
202
- commands.each { |k, v| msg += commands[k].inspect }
203
- msg
266
+ Presenter.new(self).print_command
204
267
  end
205
268
  end
206
269
  end
@@ -0,0 +1,80 @@
1
+ module Mercenary
2
+ class Option
3
+ attr_reader :config_key, :description, :switches
4
+
5
+ # Public: Create a new Option
6
+ #
7
+ # config_key - the key in the config hash to which the value of this option will map
8
+ # info - an array containing first the switches, then a description of the option
9
+ #
10
+ # Returns nothing
11
+ def initialize(config_key, info)
12
+ @config_key = config_key
13
+ @description = info.last unless info.last.start_with?("-")
14
+ set_switches(info.take(info.size - [@description].reject(&:nil?).size))
15
+ end
16
+
17
+ # Public: Fetch the array containing the info OptionParser is interested in
18
+ #
19
+ # Returns the array which OptionParser#on wants
20
+ def for_option_parser
21
+ [switches.reject(&:empty?), description].reject{ |o| o.nil? || o.empty? }.flatten
22
+ end
23
+
24
+ # Public: Build a string representation of this option including the
25
+ # switches and description
26
+ #
27
+ # Returns a string representation of this option
28
+ def to_s
29
+ "#{formatted_switches} #{description}"
30
+ end
31
+
32
+ # Public: Build a beautifully-formatted string representation of the switches
33
+ #
34
+ # Returns a formatted string representation of the switches
35
+ def formatted_switches
36
+ [
37
+ switches.first.rjust(10),
38
+ switches.last.ljust(13)
39
+ ].join(", ").gsub(/ , /, ' ').gsub(/, /, ' ')
40
+ end
41
+
42
+ # Public: Hash based on the hash value of instance variables
43
+ #
44
+ # Returns a Fixnum which is unique to this Option based on the instance variables
45
+ def hash
46
+ instance_variables.map do |var|
47
+ instance_variable_get(var).hash
48
+ end.reduce(:&)
49
+ end
50
+
51
+ # Public: Check equivalence of two Options based on equivalence of their
52
+ # instance variables
53
+ #
54
+ # Returns true if all the instance variables are equal, false otherwise
55
+ def eql?(other)
56
+ return false unless self.class.eql?(other.class)
57
+ instance_variables.map do |var|
58
+ instance_variable_get(var).eql?(other.instance_variable_get(var))
59
+ end.all?
60
+ end
61
+
62
+ private
63
+
64
+ # Private: Set the full switches array, ensuring the first element is the
65
+ # short switch and the second element is the long switch
66
+ #
67
+ # Returns the corrected switches array
68
+ def set_switches(switches)
69
+ if switches.size < 2
70
+ if switches.first.start_with?("--")
71
+ switches.unshift ""
72
+ else
73
+ switches << ""
74
+ end
75
+ end
76
+ @switches = switches
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,80 @@
1
+ module Mercenary
2
+ class Presenter
3
+ attr_accessor :command
4
+
5
+ # Public: Make a new Presenter
6
+ #
7
+ # command - a Mercenary::Command to present
8
+ #
9
+ # Returns nothing
10
+ def initialize(command)
11
+ @command = command
12
+ end
13
+
14
+ # Public: Builds a string representation of the command usage
15
+ #
16
+ # Returns the string representation of the command usage
17
+ def usage_presentation
18
+ " #{command.syntax}"
19
+ end
20
+
21
+ # Public: Builds a string representation of the options
22
+ #
23
+ # Returns the string representation of the options
24
+ def options_presentation
25
+ return nil unless command.options.size > 0
26
+ command.options.map(&:to_s).join("\n")
27
+ end
28
+
29
+ # Public: Builds a string representation of the subcommands
30
+ #
31
+ # Returns the string representation of the subcommands
32
+ def subcommands_presentation
33
+ return nil unless command.commands.size > 0
34
+ command.commands.values.map(&:summarize).join("\n")
35
+ end
36
+
37
+ # Public: Builds the command header, including the command identity and description
38
+ #
39
+ # Returns the command header as a String
40
+ def command_header
41
+ header = "#{command.identity}"
42
+ header << " -- #{command.description}" if command.description
43
+ header
44
+ end
45
+
46
+ # Public: Builds a string representation of the whole command
47
+ #
48
+ # Returns the string representation of the whole command
49
+ def command_presentation
50
+ msg = []
51
+ msg << command_header
52
+ msg << "Usage:"
53
+ msg << usage_presentation
54
+
55
+ if opts = options_presentation
56
+ msg << "Options:\n#{opts}"
57
+ end
58
+ if subcommands = subcommands_presentation
59
+ msg << "Subcommands:\n#{subcommands_presentation}"
60
+ end
61
+ msg.join("\n\n")
62
+ end
63
+
64
+ # Public: Turn a print_* into a *_presentation or freak out
65
+ #
66
+ # meth - the method being called
67
+ # args - an array of arguments passed to the missing method
68
+ # block - the block passed to the missing method
69
+ #
70
+ # Returns the value of whatever function is called
71
+ def method_missing(meth, *args, &block)
72
+ if meth.to_s =~ /^print_(.+)$/
73
+ send("#{$1.downcase}_presentation")
74
+ else
75
+ super # You *must* call super if you don't handle the method,
76
+ # otherwise you'll mess up Ruby's method lookup.
77
+ end
78
+ end
79
+ end
80
+ end
@@ -13,19 +13,9 @@ module Mercenary
13
13
  super(name)
14
14
  end
15
15
 
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
24
- end
25
-
26
16
  # Public: Run the program
27
17
  #
28
- # argv - an array of string args (usually ARGV)
18
+ # argv - an array of string args (usually ARGV)
29
19
  #
30
20
  # Returns nothing
31
21
  def go(argv)
@@ -35,18 +25,22 @@ module Mercenary
35
25
 
36
26
  @optparse = OptionParser.new do |opts|
37
27
  cmd = super(argv, opts, @config)
38
-
39
- opts.on('-v', '--version', 'Print the version') do
40
- puts "#{name} #{version}"
41
- abort
42
- end
43
28
  end
44
29
 
45
30
  @optparse.parse!(argv)
46
31
 
47
32
  logger.debug("Parsed config: #{@config.inspect}")
48
33
 
49
- cmd.execute(argv, @config)
34
+ begin
35
+ cmd.execute(argv, @config)
36
+ rescue => e
37
+ if cmd.trace
38
+ raise e
39
+ else
40
+ logger.error e.message
41
+ abort
42
+ end
43
+ end
50
44
  end
51
45
  end
52
46
  end
@@ -1,3 +1,3 @@
1
1
  module Mercenary
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/script/cibuild CHANGED
@@ -1,3 +1,6 @@
1
1
  #! /bin/sh
2
2
 
3
+ set -ex
4
+
3
5
  bundle exec rspec
6
+ ./script/examples
data/script/console ADDED
@@ -0,0 +1,3 @@
1
+ #! /bin/bash
2
+
3
+ irb -r./lib/mercenary.rb
data/script/examples ADDED
@@ -0,0 +1,17 @@
1
+ #! /bin/bash
2
+
3
+ set -e
4
+
5
+ function run () {
6
+ echo "+ ruby ./examples/$@"
7
+ ruby -e "puts '=' * 79"
8
+ ruby ./examples/$@
9
+ ruby -e "puts '=' * 79"
10
+ }
11
+
12
+ run logging.rb
13
+ run help_dialogue.rb -h
14
+ run help_dialogue.rb some_subcommand -h
15
+ run help_dialogue.rb another_subcommand -h
16
+ run help_dialogue.rb some_subcommand yet_another_sub -h
17
+ run help_dialogue.rb some_subcommand yet_another_sub -b
data/spec/command_spec.rb CHANGED
@@ -35,6 +35,12 @@ describe(Mercenary::Command) do
35
35
  expect(add_sub.call(command).parent).to eq(command)
36
36
  end
37
37
 
38
+ it "can set its version" do
39
+ version = "1.4.2"
40
+ command.version version
41
+ expect(command.version).to eq(version)
42
+ end
43
+
38
44
  it "can set its syntax" do
39
45
  syntax_string = "my_name [options]"
40
46
  cmd = described_class.new(:my_name)
@@ -50,10 +56,20 @@ describe(Mercenary::Command) do
50
56
 
51
57
  it "can set its options" do
52
58
  name = "show_drafts"
53
- opt = ['--drafts', 'Render posts in the _drafts folder']
54
- command.option name, *opt
55
- expect(command.options).to eq([opt])
56
- expect(command.map).to include({opt.first => name})
59
+ opts = ['--drafts', 'Render posts in the _drafts folder']
60
+ option = Mercenary::Option.new(name, opts)
61
+ command.option name, *opts
62
+ expect(command.options).to eql([option])
63
+ expect(command.map).to include({option.hash => name})
64
+ end
65
+
66
+ it "knows its full name" do
67
+ expect(command_with_parent.full_name).to eql("my_parent i_have_parent")
68
+ end
69
+
70
+ it "knows its identity" do
71
+ command_with_parent.version '1.8.7'
72
+ expect(command_with_parent.identity).to eql("my_parent i_have_parent 1.8.7")
57
73
  end
58
74
 
59
75
  it "raises an ArgumentError if I specify a default_command that isn't there" do
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe(Mercenary::Option) do
4
+ let(:config_key) { "largo" }
5
+ let(:description) { "This is a description" }
6
+ let(:switches) { ['-l', '--largo'] }
7
+ let(:option) { described_class.new(config_key, [switches, description].flatten.reject(&:nil?)) }
8
+
9
+ it "knows its config key" do
10
+ expect(option.config_key).to eql(config_key)
11
+ end
12
+
13
+ it "knows its description" do
14
+ expect(option.description).to eql(description)
15
+ end
16
+
17
+ it "knows its switches" do
18
+ expect(option.switches).to eql(switches)
19
+ end
20
+
21
+ it "knows how to present itself" do
22
+ expect(option.to_s).to eql(" -l, --largo #{description}")
23
+ end
24
+
25
+ it "has an OptionParser representation" do
26
+ expect(option.for_option_parser).to eql([switches, description].flatten)
27
+ end
28
+
29
+ it "compares itself with other options well" do
30
+ new_option = described_class.new(config_key, ['-l', '--largo', description])
31
+ expect(option.eql?(new_option)).to be_true
32
+ expect(option.hash.eql?(new_option.hash)).to be_true
33
+ end
34
+
35
+ it "has a custom #hash" do
36
+ expect(option.hash.to_s).to match(/\d+/)
37
+ end
38
+
39
+ context "with just the long switch" do
40
+ let(:switches) { ['--largo'] }
41
+
42
+ it "adds an empty string in place of the short switch" do
43
+ expect(option.switches).to eql(['', '--largo'])
44
+ end
45
+
46
+ it "sets its description properly" do
47
+ expect(option.description).to eql(description)
48
+ end
49
+
50
+ it "knows how to present the switch" do
51
+ expect(option.formatted_switches).to eql(" --largo ")
52
+ end
53
+ end
54
+
55
+ context "with just the short switch" do
56
+ let(:switches) { ['-l'] }
57
+
58
+ it "adds an empty string in place of the long switch" do
59
+ expect(option.switches).to eql(['-l', ''])
60
+ end
61
+
62
+ it "sets its description properly" do
63
+ expect(option.description).to eql(description)
64
+ end
65
+
66
+ it "knows how to present the switch" do
67
+ expect(option.formatted_switches).to eql(" -l ")
68
+ end
69
+ end
70
+
71
+ context "without a description" do
72
+ let(:description) { nil }
73
+
74
+ it "knows there is no description" do
75
+ expect(option.description).to be_nil
76
+ end
77
+
78
+ it "knows both inputs are switches" do
79
+ expect(option.switches).to eql(switches)
80
+ end
81
+ end
82
+
83
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe(Mercenary::Presenter) do
4
+ let(:supercommand) { Mercenary::Command.new(:script_name) }
5
+ let(:command) { Mercenary::Command.new(:subcommand, supercommand) }
6
+ let(:presenter) { described_class.new(command) }
7
+
8
+ before(:each) do
9
+ command.version '1.4.2'
10
+ command.description 'Do all the things.'
11
+ command.option 'one', '-1', '--one', 'The first option'
12
+ command.option 'two', '-2', '--two', 'The second option'
13
+ supercommand.commands[command.name] = command
14
+ end
15
+
16
+ it "knows how to present the command" do
17
+ expect(presenter.command_presentation).to eql("script_name subcommand 1.4.2 -- Do all the things.\n\nUsage:\n\n script_name subcommand\n\nOptions:\n -1, --one The first option\n -2, --two The second option")
18
+ end
19
+
20
+ it "knows how to present the subcommands" do
21
+ expect(described_class.new(supercommand).subcommands_presentation).to eql(" subcommand Do all the things.")
22
+ end
23
+
24
+ it "knows how to present the usage" do
25
+ expect(presenter.usage_presentation).to eql(" script_name subcommand")
26
+ end
27
+
28
+ it "knows how to present the options" do
29
+ expect(presenter.options_presentation).to eql(" -1, --one The first option\n -2, --two The second option")
30
+ end
31
+
32
+ it "allows you to say print_* instead of *_presentation" do
33
+ expect(presenter.print_usage).to eql(presenter.usage_presentation)
34
+ expect(presenter.print_subcommands).to eql(presenter.subcommands_presentation)
35
+ expect(presenter.print_options).to eql(presenter.options_presentation)
36
+ expect(presenter.print_command).to eql(presenter.command_presentation)
37
+ end
38
+ end
data/spec/program_spec.rb CHANGED
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe(Mercenary::Program) do
4
+
5
+ context "a basic program" do
6
+ let(:program) { Mercenary::Program.new(:my_name) }
7
+
8
+ it "can be created with just a name" do
9
+ expect(program.name).to eql(:my_name)
10
+ end
11
+
12
+ it "can set its version" do
13
+ version = Mercenary::VERSION
14
+ program.version version
15
+ expect(program.version).to eq(version)
16
+ end
17
+ end
18
+
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mercenary
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Preston-Werner
@@ -9,48 +9,48 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-26 00:00:00.000000000 Z
12
+ date: 2014-02-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ~>
19
19
  - !ruby/object:Gem::Version
20
20
  version: '1.3'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "~>"
25
+ - - ~>
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.3'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - '>='
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - '>='
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ~>
47
47
  - !ruby/object:Gem::Version
48
48
  version: '2.14'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ~>
54
54
  - !ruby/object:Gem::Version
55
55
  version: '2.14'
56
56
  description: Lightweight and flexible library for writing command-line apps in Ruby.
@@ -61,22 +61,31 @@ executables: []
61
61
  extensions: []
62
62
  extra_rdoc_files: []
63
63
  files:
64
- - ".gitignore"
65
- - ".rspec"
66
- - ".travis.yml"
64
+ - .gitignore
65
+ - .rspec
66
+ - .travis.yml
67
67
  - Gemfile
68
68
  - History.markdown
69
69
  - LICENSE.txt
70
70
  - README.md
71
71
  - Rakefile
72
+ - examples/help_dialogue.rb
73
+ - examples/logging.rb
74
+ - examples/trace.rb
72
75
  - lib/mercenary.rb
73
76
  - lib/mercenary/command.rb
77
+ - lib/mercenary/option.rb
78
+ - lib/mercenary/presenter.rb
74
79
  - lib/mercenary/program.rb
75
80
  - lib/mercenary/version.rb
76
81
  - mercenary.gemspec
77
82
  - script/bootstrap
78
83
  - script/cibuild
84
+ - script/console
85
+ - script/examples
79
86
  - spec/command_spec.rb
87
+ - spec/option_spec.rb
88
+ - spec/presenter_spec.rb
80
89
  - spec/program_spec.rb
81
90
  - spec/spec_helper.rb
82
91
  homepage: https://github.com/jekyll/mercenary
@@ -89,21 +98,23 @@ require_paths:
89
98
  - lib
90
99
  required_ruby_version: !ruby/object:Gem::Requirement
91
100
  requirements:
92
- - - ">="
101
+ - - '>='
93
102
  - !ruby/object:Gem::Version
94
103
  version: '0'
95
104
  required_rubygems_version: !ruby/object:Gem::Requirement
96
105
  requirements:
97
- - - ">="
106
+ - - '>='
98
107
  - !ruby/object:Gem::Version
99
108
  version: '0'
100
109
  requirements: []
101
110
  rubyforge_project:
102
- rubygems_version: 2.2.0
111
+ rubygems_version: 2.0.14
103
112
  signing_key:
104
113
  specification_version: 4
105
114
  summary: Lightweight and flexible library for writing command-line apps in Ruby.
106
115
  test_files:
107
116
  - spec/command_spec.rb
117
+ - spec/option_spec.rb
118
+ - spec/presenter_spec.rb
108
119
  - spec/program_spec.rb
109
120
  - spec/spec_helper.rb