1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
# Mercenary
Lightweight and flexible library for writing command-line apps in Ruby.
[](https://travis-ci.org/jekyll/mercenary)
## Installation
Add this line to your application's Gemfile:
gem 'mercenary'
And then execute:
$ bundle
Or install it yourself as:
$ gem install mercenary
**Note: Mercenary may not work with Ruby < 1.9.3.**
## Usage
Creating programs and commands with Mercenary is easy:
```ruby
Mercenary.program(:jekyll) do |p|
p.version Jekyll::VERSION
p.description 'Jekyll is a blog-aware, static site generator in Ruby'
p.syntax "jekyll <subcommand> [options]"
p.command(:new) do |c|
c.syntax "new PATH" # do not include the program name or super commands
c.description "Creates a new Jekyll site scaffold in PATH"
c.option 'blank', '--blank', 'Initialize the new site without any content.'
c.action do |args, options|
Jekyll::Commands::New.process(args, blank: options['blank'])
end
end
p.command(:build) do |c|
c.syntax "build [options]"
c.description "Builds your Jekyll site"
c.option 'safe', '--safe', 'Run in safe mode'
c.option 'source', '--source DIR', 'From where to collect the source files'
c.option 'destination', '--dest DIR', 'To where the compiled files should be written'
c.action do |_, options|
Jekyll::Commands::Build.process(options)
end
end
# Bring in command bundled in external gem
begin
require "jekyll-import"
JekyllImport.init_with_program(p)
rescue LoadError
end
p.default_command(:build)
end
```
All commands have the following default options:
- `-h/--help` - show a help message
- `-v/--version` - show the program version
- `-t/--trace` - show the full backtrace when an error occurs
## API
### `Mercenary`
#### `.program`
Creates and executes a program. Accepts two arguments:
- `name` - program name as a Symbol
- `block` - the specification for the program, passed the program instance as an
argument.
Example is above, under the heading [Usage](#usage).
### `Program`
`Program` is a subclass of `Command`, so it has all of the methods documented
below as well as those for `Command`.
#### `#config`
Fetches the program configuration hash.
### `Command`
#### `#new`
Create a new command. Accepts one argument:
- `name` - the name of your command, as a symbol
#### `#version`
Sets or gets the version of the command. Accepts an optional argument:
- `version` - (optional) the version to set for the command. If present, this
becomes the new version for the command and persists.
#### `#syntax`
Sets or gets the syntax of the command. Built on parent syntaxes if a parent
exists. Accepts one optional argument:
- `syntax` - (optional) the syntax to set for the command. Will inherit from the
parent commands or program. Usually in the form of
`"command_name <SUBCOMMAND> [OPTIONS]"`
When a parent command exists, say `supercommand`, with syntax set as
`supercommand <SUBCOMMAND> [OPTIONS]`, the syntax of the command in question
will be `supercommand command_name <SUBCOMMAND> [OPTIONS]` with both
`<SUBCOMMAND>` and `[OPTIONS]` stripped out. Any text between `<` and `>` or
between `[` and `]` will be stripped from parent command syntaxes. The purpose
of this chaining is to reduce redundancy.
#### `#description`
Sets or gets the description of the command. Accepts one optional argument:
- `desc` - (optional) the description to set for the command. If
provided, will override any previous description set for the command.
#### `#default_command`
Sets or gets the default subcommand of the command to execute in the event no
subcommand is passed during execution. Accepts one optional argument:
- `command_name` - (optional) the `Symbol` name of the subcommand to be
executed. Raises an `ArgumentError` if the subcommand doesn't exist.
Overwrites previously-set default commands.
#### `#option`
Adds a new option to the command. Accepts many arguments:
- `config_key` - the configuration key that the value of this option maps to.
- `*options` - all the options, globbed, to be passed to `OptionParser`, namely the
switches and the option description. Usually in the format
`"-s", "--switch", "Sets the 'switch' flag"`.
Valid option calls:
```ruby
cmd.option 'config_key', '-c', 'Sets the "config" flag'
cmd.option 'config_key', '--config', 'Sets the "config" flag'
cmd.option 'config_key', '-c', '--config', 'Sets the "config" flag.'
cmd.option 'config_key', '-c FILE', '--config FILE', 'The config file.'
cmd.option 'config_key', '-c FILE1[,FILE2[,FILE3...]]', '--config FILE1[,FILE2[,FILE3...]]', Array, 'The config files.'
```
Notice that you can specify either a short switch, a long switch, or both. If
you want to accept an argument, you have to specify it in the switch strings.
The class of the argument defaults to `String`, but you can optionally set a
different class to create, e.g. `Array`, if you are expecting a particular class
in your code from this option's value. The description is also optional, but
it's highly recommended to include a description.
#### `#alias`
Specifies an alias for this command such that the alias may be used in place of
the command during execution. Accepts one argument:
- `cmd_name` - the alias name for this command as a `Symbol`
Example:
```ruby
cmd.alias(:my_alias)
# Now `cmd` is now also executable via "my_alias"
```
#### `#action`
Specifies a block to be executed in the event the command is specified at
runtime. The block is given two arguments:
- `args` - the non-switch arguments given from the command-line
- `options` - the options hash built via the switches passed
**Note that actions are additive**, meaning any new call to `#action` will
result in another action to be executed at runtime. Actions will be executed in
the order they are specified in.
Example:
```ruby
cmd.action do |args, options|
# do something!
end
```
#### `#logger`
Access the logger for this command. Useful for outputting information to STDOUT.
Accepts one optional argument:
- `level` - (optional) the severity threshold at which to begin logging. Uses
Ruby's built-in
[`Logger`](http://www.ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html)
levels.
Log level defaults to `Logger::INFO`.
Examples:
```ruby
cmd.logger(Logger::DEBUG)
cmd.logger.debug "My debug message."
cmd.logger.info "My informative message."
cmd.logger.warn "ACHTUNG!!"
cmd.logger.error "Something terrible has happened."
cmd.logger.fatal "I can't continue doing what I'm doing."
```
#### `#command`
Creates a new subcommand for the current command. Accepts two arguments:
- `cmd_name` - the command name, as a Symbol
- `block` - the specification of the subcommand in a block
Example:
```ruby
my_command.command(:my_subcommand) do |subcmd|
subcmd.description 'My subcommand'
subcmd.syntax 'my_subcommand [OPTIONS]'
# ...
end
```
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
|