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 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
|
[<img src="https://api.travis-ci.org/commander-rb/commander.svg" alt="Build Status" />](https://travis-ci.org/commander-rb/commander)
[](https://inch-ci.org/github/commander-rb/commander)
# Commander
The complete solution for Ruby command-line executables.
Commander bridges the gap between other terminal related libraries
you know and love (OptionParser, HighLine), while providing many new
features, and an elegant API.
## Features
* Easier than baking cookies
* Parses options using OptionParser
* Auto-populates struct with options ( no more `{ |v| options[:recursive] = v }` )
* Auto-generates help documentation via pluggable help formatters
* Optional default command when none is present
* Global / Command level options
* Packaged with two help formatters (Terminal, TerminalCompact)
* Imports the highline gem for interacting with the terminal
* Adds additional user interaction functionality
* Highly customizable progress bar with intuitive, simple usage
* Multi-word command name support such as `drupal module install MOD`, rather than `drupal module_install MOD`
* Sexy paging for long bodies of text
* Support for MacOS text-to-speech
* Command aliasing (very powerful, as both switches and arguments can be used)
* Growl notification support for MacOS
* Use the `commander` executable to initialize a commander driven program
## Installation
$ gem install commander
## Quick Start
To generate a quick template for a commander app, run:
$ commander init yourfile.rb
To generate a quick modular style template for a commander app, run:
$ commander init --modular yourfile.rb
## Example
For more option examples view the `Commander::Command#option` method. Also
an important feature to note is that action may be a class to instantiate,
as well as an object, specifying a method to call, so view the RDoc for more information.
### Classic style
```ruby
require 'rubygems'
require 'commander/import'
# :name is optional, otherwise uses the basename of this executable
program :name, 'Foo Bar'
program :version, '1.0.0'
program :description, 'Stupid command that prints foo or bar.'
command :foo do |c|
c.syntax = 'foobar foo'
c.description = 'Displays foo'
c.action do |args, options|
say 'foo'
end
end
command :bar do |c|
c.syntax = 'foobar bar [options]'
c.description = 'Display bar with optional prefix and suffix'
c.option '--prefix STRING', String, 'Adds a prefix to bar'
c.option '--suffix STRING', String, 'Adds a suffix to bar'
c.action do |args, options|
options.default :prefix => '(', :suffix => ')'
say "#{options.prefix}bar#{options.suffix}"
end
end
```
Example output:
```
$ foobar bar
# => (bar)
$ foobar bar --suffix '}' --prefix '{'
# => {bar}
```
### Modular style
**NOTE:** Make sure to use `require 'commander'` rather than `require 'commander/import'`, otherwise Commander methods will still be imported into the global namespace.
```ruby
require 'rubygems'
require 'commander'
class MyApplication
include Commander::Methods
def run
program :name, 'Foo Bar'
program :version, '1.0.0'
program :description, 'Stupid command that prints foo or bar.'
command :foo do |c|
c.syntax = 'foobar foo'
c.description = 'Displays foo'
c.action do |args, options|
say 'foo'
end
end
run!
end
end
MyApplication.new.run if $0 == __FILE__
```
### Block style
```ruby
require 'rubygems'
require 'commander'
Commander.configure do
program :name, 'Foo Bar'
program :version, '1.0.0'
program :description, 'Stupid command that prints foo or bar.'
# see classic style example for options
end
```
## HighLine
As mentioned above, the highline gem is imported into the global scope. Here
are some quick examples for how to utilize highline in your commands:
```ruby
# Ask for password masked with '*' character
ask("Password: ") { |q| q.echo = "*" }
# Ask for password
ask("Password: ") { |q| q.echo = false }
# Ask if the user agrees (yes or no)
agree("Do something?")
# Asks on a single line (note the space after ':')
ask("Name: ")
# Asks with new line after "Description:"
ask("Description:")
# Calls Date#parse to parse the date string passed
ask("Birthday? ", Date)
# Ensures Integer is within the range specified
ask("Age? ", Integer) { |q| q.in = 0..105 }
# Asks for a list of strings, converts to array
ask("Fav colors?", Array)
```
## HighLine & Interaction Additions
In addition to highline's fantastic choice of methods, commander adds the
following methods to simplify common tasks:
```ruby
# Ask for password
password
# Ask for password with specific message and mask character
password "Enter your password please:", '-'
# Ask for CLASS, which may be any valid class responding to #parse. Date, Time, Array, etc
names = ask_for_array 'Names: '
bday = ask_for_date 'Birthday?: '
# Simple progress bar (Commander::UI::ProgressBar)
uris = %w[
http://vision-media.ca
http://google.com
http://yahoo.com
]
progress uris do |uri|
res = open uri
# Do something with response
end
# 'Log' action to stdout
log "create", "path/to/file.rb"
# Enable paging of output after this point
enable_paging
# Ask editor for input (EDITOR environment variable or whichever is available: TextMate, vim, vi, emacs, nano, pico)
ask_editor
# Ask editor, supplying initial text
ask_editor 'previous data to update'
# Ask editor, preferring a specific editor
ask_editor 'previous data', 'vim'
# Choose from an array of elements
choice = choose("Favorite language?", :ruby, :perl, :js)
# Alter IO for the duration of the block
io new_input, new_output do
new_input_contents = $stdin.read
puts new_input_contents # outputs to new_output stream
end
# $stdin / $stdout reset back to original streams
# Speech synthesis
speak 'What is your favorite food? '
food = ask 'favorite food?: '
speak "Wow, I like #{food} too. We have so much in common."
speak "I like #{food} as well!", "Victoria", 190
# Execute arbitrary applescript
applescript 'foo'
# Converse with speech recognition server
case converse 'What is the best food?', :cookies => 'Cookies', :unknown => 'Nothing'
when :cookies
speak 'o.m.g. you are awesome!'
else
case converse 'That is lame, shall I convince you cookies are the best?', :yes => 'Ok', :no => 'No', :maybe => 'Maybe another time'
when :yes
speak 'Well you see, cookies are just fantastic, they melt in your mouth.'
else
speak 'Ok then, bye.'
end
end
```
## Growl Notifications
Commander provides methods for displaying Growl notifications. To use these
methods you need to install https://github.com/tj/growl which utilizes
the [growlnotify](https://growl.info/extras.php#growlnotify) executable. Note that
growl is auto-imported by Commander when available, no need to require.
```ruby
# Display a generic Growl notification
notify 'Something happened'
# Display an 'info' status notification
notify_info 'You have #{emails.length} new email(s)'
# Display an 'ok' status notification
notify_ok 'Gems updated'
# Display a 'warning' status notification
notify_warning '1 gem failed installation'
# Display an 'error' status notification
notify_error "Gem #{name} failed"
```
## Commander Goodies
### Option Defaults
The options struct passed to `#action` provides a `#default` method, allowing you
to set defaults in a clean manner for options which have not been set.
```ruby
command :foo do |c|
c.option '--interval SECONDS', Integer, 'Interval in seconds'
c.option '--timeout SECONDS', Integer, 'Timeout in seconds'
c.action do |args, options|
options.default \
:interval => 2,
:timeout => 60
end
end
```
### Command Aliasing
Aliases can be created using the `#alias_command` method like below:
```ruby
command :'install gem' do |c|
c.action { puts 'foo' }
end
alias_command :'gem install', :'install gem'
```
Or more complicated aliases can be made, passing any arguments
as if it was invoked via the command line:
```ruby
command :'install gem' do |c|
c.syntax = 'install gem <name> [options]'
c.option '--dest DIR', String, 'Destination directory'
c.action { |args, options| puts "installing #{args.first} to #{options.dest}" }
end
alias_command :update, :'install gem', 'rubygems', '--dest', 'some_path'
```
```
$ foo update
# => installing rubygems to some_path
```
### Command Defaults
Although working with a command executable framework provides many
benefits over a single command implementation, sometimes you still
want the ability to create a terse syntax for your command. With that
in mind we may use `#default_command` to help with this. Considering
our previous `:'install gem'` example:
```ruby
default_command :update
```
```
$ foo
# => installing rubygems to some_path
```
Keeping in mind that commander searches for the longest possible match
when considering a command, so if you were to pass arguments to foo
like below, expecting them to be passed to `:update`, this would be incorrect,
and would end up calling `:'install gem'`, so be careful that the users do
not need to use command names within the arguments.
```
$ foo install gem
# => installing to
```
### Long descriptions
If you need to have a long command description, keep your short description under `summary`, and consider multi-line strings for `description`:
```ruby
program :summary, 'Stupid command that prints foo or bar.'
program :description, %q(
#{c.summary}
More information about that stupid command that prints foo or bar.
And more
)
```
### Additional Global Help
Arbitrary help can be added using the following `#program` symbol:
```ruby
program :help, 'Author', 'TJ Holowaychuk <tj@vision-media.ca>'
```
Which will output the rest of the help doc, along with:
AUTHOR:
TJ Holowaychuk <tj@vision-media.ca>
### Global Options
Although most switches will be at the command level, several are available by
default at the global level, such as `--version`, and `--help`. Using
`#global_option` you can add additional global options:
```ruby
global_option('-c', '--config FILE', 'Load config data for your commands to use') { |file| ... }
```
This method accepts the same syntax as `Commander::Command#option` so check it out for documentation.
All global options regardless of providing a block are accessable at the command level. This
means that instead of the following:
```ruby
global_option('--verbose') { $verbose = true }
...
c.action do |args, options|
say 'foo' if $verbose
...
```
You may:
```ruby
global_option '--verbose'
...
c.action do |args, options|
say 'foo' if options.verbose
...
```
### Formatters
Two core formatters are currently available, the default `Terminal` formatter
as well as `TerminalCompact`. To utilize a different formatter simply use
`:help_formatter` like below:
```ruby
program :help_formatter, Commander::HelpFormatter::TerminalCompact
```
Or utilize the help formatter aliases:
```ruby
program :help_formatter, :compact
```
This abstraction could be utilized to generate HTML documentation for your executable.
### Tracing
By default the `-t` and `--trace` global options are provided to allow users to get a backtrace to aid debugging.
You can disable these options:
```ruby
never_trace!
```
Or make it always on:
```ruby
always_trace!
```
## Tips
When adding a global or command option, OptionParser implicitly adds a small
switch even when not explicitly created, for example `-c` will be the same as
`--config` in both examples, however `-c` will only appear in the documentation
when explicitly assigning it.
```ruby
global_option '-c', '--config FILE'
global_option '--config FILE'
```
## ASCII Tables
For feature rich ASCII tables for your terminal app check out the terminal-table gem at https://github.com/tj/terminal-table
+----------+-------+----+--------+-----------------------+
| Terminal | Table | Is | Wicked | Awesome |
+----------+-------+----+--------+-----------------------+
| | | | | get it while its hot! |
+----------+-------+----+--------+-----------------------+
## Running Specifications
$ rake spec
OR
$ spec --color spec
## Contrib
Feel free to fork and request a pull, or submit a ticket
https://github.com/commander-rb/commander/issues
## License
This project is available under the MIT license. See LICENSE for details.
|