[DRE-commits] [ruby-commander] 01/11: New upstream version 4.4.1
Daisuke Higuchi
dai at moszumanska.debian.org
Sat Oct 21 12:40:35 UTC 2017
This is an automated email from the git hooks/post-receive script.
dai pushed a commit to branch master
in repository ruby-commander.
commit 242f29889bf7a17bdb3cf6d1ab1d959fc572bf93
Author: HIGUCHI Daisuke (VDR dai) <dai at debian.org>
Date: Sat Oct 21 21:16:39 2017 +0900
New upstream version 4.4.1
---
.rspec | 2 +
.rubocop.yml | 9 +
.rubocop_todo.yml | 77 +++
.travis.yml | 11 +-
Gemfile | 2 +-
History.rdoc | 65 +++
LICENSE | 22 +
README.md | 460 ++++++++++++++++++
README.rdoc | 372 ---------------
Rakefile | 11 +-
bin/commander | 87 +++-
commander.gemspec | 39 +-
lib/commander.rb | 3 +
lib/commander/blank.rb | 5 +-
lib/commander/command.rb | 131 +++--
lib/commander/configure.rb | 14 +
lib/commander/core_ext.rb | 3 +-
lib/commander/core_ext/array.rb | 6 +-
lib/commander/core_ext/object.rb | 5 +-
lib/commander/delegates.rb | 24 +-
lib/commander/help_formatters.rb | 42 +-
lib/commander/help_formatters/base.rb | 22 +-
lib/commander/help_formatters/terminal.rb | 15 +-
.../help_formatters/terminal/command_help.erb | 2 +-
lib/commander/help_formatters/terminal/help.erb | 4 +-
lib/commander/help_formatters/terminal_compact.rb | 5 +-
.../help_formatters/terminal_compact/help.erb | 4 +-
lib/commander/import.rb | 7 +-
lib/commander/methods.rb | 11 +
lib/commander/platform.rb | 1 -
lib/commander/runner.rb | 293 +++++++-----
lib/commander/user_interaction.rb | 245 +++++-----
lib/commander/version.rb | 2 +-
metadata.yml | 157 ------
spec/command_spec.rb | 150 +++---
spec/configure_spec.rb | 37 ++
spec/core_ext/array_spec.rb | 16 +-
spec/core_ext/object_spec.rb | 18 +-
spec/help_formatters/terminal_compact_spec.rb | 69 +++
spec/help_formatters/terminal_spec.rb | 58 +--
spec/methods_spec.rb | 20 +
spec/runner_spec.rb | 527 ++++++++++++---------
spec/spec_helper.rb | 58 +--
spec/ui_spec.rb | 26 +-
44 files changed, 1813 insertions(+), 1324 deletions(-)
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..83e16f8
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--color
+--require spec_helper
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..a44b4d9
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,9 @@
+inherit_from: .rubocop_todo.yml
+
+# Offense count: 5
+Encoding:
+ Enabled: false
+
+# Enforce trailing comma after last item of multiline hashes.
+Style/TrailingComma:
+ EnforcedStyleForMultiline: comma
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
new file mode 100644
index 0000000..6f806dc
--- /dev/null
+++ b/.rubocop_todo.yml
@@ -0,0 +1,77 @@
+# This configuration was generated by `rubocop --auto-gen-config`
+# on 2015-02-16 16:08:54 -0800 using RuboCop version 0.29.0.
+# The point is for the user to remove these configuration records
+# one by one as the offenses are removed from the code base.
+# Note that changes in the inspected code, or installation of new
+# versions of RuboCop, may require this file to be generated again.
+
+# Offense count: 2
+Lint/Eval:
+ Enabled: false
+
+# Offense count: 2
+Lint/HandleExceptions:
+ Enabled: false
+
+# Offense count: 5
+Metrics/AbcSize:
+ Max: 29
+
+# Offense count: 1
+# Configuration parameters: CountComments.
+Metrics/ClassLength:
+ Enabled: false
+
+# Offense count: 4
+Metrics/CyclomaticComplexity:
+ Max: 13
+
+# Offense count: 89
+# Configuration parameters: AllowURI, URISchemes.
+Metrics/LineLength:
+ Max: 242
+
+# Offense count: 7
+# Configuration parameters: CountComments.
+Metrics/MethodLength:
+ Max: 36
+
+# Offense count: 4
+Metrics/PerceivedComplexity:
+ Max: 14
+
+# Offense count: 1
+Style/AccessorMethodName:
+ Enabled: false
+
+# Offense count: 18
+Style/Documentation:
+ Enabled: false
+
+# Offense count: 12
+# Configuration parameters: AllowedVariables.
+Style/GlobalVars:
+ Enabled: false
+
+# Offense count: 1
+# Configuration parameters: MaxLineLength.
+Style/IfUnlessModifier:
+ Enabled: false
+
+# Offense count: 1
+Style/MultilineBlockChain:
+ Enabled: false
+
+# Offense count: 1
+Style/MultilineTernaryOperator:
+ Enabled: false
+
+# Offense count: 5
+Style/RescueModifier:
+ Enabled: false
+
+# Offense count: 2
+# Cop supports --auto-correct.
+# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, Whitelist.
+Style/TrivialAccessors:
+ Enabled: false
diff --git a/.travis.yml b/.travis.yml
index 78d5e9c..eb94999 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,10 @@
language: ruby
-before_install: gem update --system
+before_install:
+ - gem update --system
+ - gem update bundler
rvm:
- - 1.8.7
- - 1.9.2
- 1.9.3
- 2.0.0
- - jruby-18mode
+ - 2.1.0
+ - 2.2.0
- jruby-19mode
- - rbx-18mode
- - rbx-19mode
diff --git a/Gemfile b/Gemfile
index c80ee36..fa75df1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,3 @@
-source "http://rubygems.org"
+source 'https://rubygems.org'
gemspec
diff --git a/History.rdoc b/History.rdoc
index 4951319..d05c0e9 100644
--- a/History.rdoc
+++ b/History.rdoc
@@ -1,3 +1,68 @@
+=== 4.4.1 / 2016-12-02
+
+* Fix #36 - Warning about MissingSourceFile (@fallwith)
+* Fix build on Ruby 1.9
+
+=== 4.4.0 / 2016-02-19
+
+* Add modular style template initialization. (@lebogan)
+* Allow option names that start with a global option name.
+* Fix handling of negatable global flags. (@mfurtak)
+
+=== 4.3.8 / 2016-02-09
+
+* Fix regression for deprecation warnings.
+
+=== 4.3.7 / 2016-01-26
+
+* Fix regression in help formatter introduced in 4.3.6.
+
+=== 4.3.6 / 2016-01-26 [YANKED]
+
+* Fix deprecation warnings on Ruby 2.3.0.
+* Indent option descriptions the same way as program and command descriptions. (@badeball)
+
+=== 4.3.5 / 2015-08-09
+
+* Fixed a bug with small terminal widths, changed minimum screen width for wrapping to 40 columns. (@toolmantim)
+
+=== 4.3.4 / 2015-05-03
+
+* Fixed a regression with the compact help formatter.
+
+=== 4.3.3 / 2015-04-21
+
+* Updated to highline 1.7.2 to fix a regression with terminal size (https://github.com/JEG2/highline/pull/139).
+* Help formatting updated to look better for commands with long names. (@jszwedko)
+
+=== 4.3.2 / 2015-03-31
+
+* Version bump to publish new location of Commander to Rubygems. Moved to https://github.com/commander-rb/commander
+
+=== 4.3.1 / 2015-03-27
+
+* Fix various Ruby warnings for circular requires, etc.
+* Update to use highline 1.7 (@SkyTrix)
+
+=== 4.3.0 / 2015-02-07
+
+* Drops support for Ruby 1.8. Please use 4.2.1 if you still need Ruby 1.8 compatibility.
+* Fixed a bug with `always_trace` (#91) (@KrauseFx)
+* Renamed `commands` to `defined_commands` for better compatibility with Pry
+
+=== 4.2.1 / 2014-09-28
+
+* Improve `choose` compatibility with HighLine's version (#79)
+
+=== 4.2.0 / 2014-04-29
+
+* Add ability to use commander without importing into the global namespace (#61) (@krissi)
+
+=== 4.1.6 / 2014-02-11
+
+* Respect environment setting for $LESS (@ellemenno)
+* Add ability to hide trace flags and globally enable tracing (#16, #17) (@jamesrwhite)
+
=== 4.1.5 / 2013-08-11
* Prevent deprecation warning when loaded in a Rails 4 environment (#58)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..02caa4d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2008-2013 TJ Holowaychuk <tj at vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d47d804
--- /dev/null
+++ b/README.md
@@ -0,0 +1,460 @@
+[<img src="https://secure.travis-ci.org/commander-rb/commander.png?branch=master" alt="Build Status" />](http://travis-ci.org/commander-rb/commander)
+[](http://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 http://github.com/tj/growl which utilizes
+the [growlnotify](http://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
+```
+
+### Additional Global Help
+
+Arbitrary help can be added using the following `#program` symbol:
+
+```ruby
+program :help, 'Author', 'TJ Holowaychuk <tj at vision-media.ca>'
+```
+
+Which will output the rest of the help doc, along with:
+
+ AUTHOR:
+
+ TJ Holowaychuk <tj at 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 http://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
+http://github.com/commander-rb/commander/issues
+
+## License
+
+This project is available under the MIT license. See LICENSE for details.
diff --git a/README.rdoc b/README.rdoc
deleted file mode 100644
index 373047d..0000000
--- a/README.rdoc
+++ /dev/null
@@ -1,372 +0,0 @@
-{<img src="https://secure.travis-ci.org/ggilder/commander.png?branch=master" alt="Build Status" />}[http://travis-ci.org/ggilder/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
-
-== 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.
-
- 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
-
- $ foobar bar
- # => (bar)
-
- $ foobar bar --suffix '}' --prefix '{'
- # => {bar}
-
-== HighLine
-
-As mentioned above the highline gem is imported into 'global scope', below
-are some quick examples for how to utilize highline in your command(s):
-
- # 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:
-
- # 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 http://github.com/visionmedia/growl which utilizes
-the growlnotify[http://growl.info/extras.php#growlnotify] executable. Note that
-growl is auto-imported by Commander when available, no need to require.
-
- # 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.
-
- 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:
-
- 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:
-
- 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:
-
- 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
-
-=== Additional Global Help
-
-Arbitrary help can be added using the following #program symbol:
-
- program :help, 'Author', 'TJ Holowaychuk <tj at vision-media.ca>'
-
-Which will output the rest of the help doc, along with:
-
- AUTHOR:
-
- TJ Holowaychuk <tj at 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:
-
- 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:
-
- global_option('--verbose') { $verbose = true }
- ...
- c.action do |args, options|
- say 'foo' if $verbose
- ...
-
-You may:
-
- 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:
-
- program :help_formatter, Commander::HelpFormatter::TerminalCompact
-
-Or utilize the help formatter aliases:
-
- program :help_formatter, :compact
-
-This abstraction could be utilized to generate HTML documentation for your executable.
-
-== 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.
-
- global_option '-c', '--config FILE'
- global_option '--config FILE'
-
-== ASCII Tables
-
-For feature rich ASCII tables for your terminal app check out visionmedia's terminal-table gem at
-http://github.com/visionmedia/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
-http://github.com/visionmedia/commander/issues
-
-== License
-
-(The MIT License)
-
-Copyright (c) 2008-2009 TJ Holowaychuk <tj at vision-media.ca>
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-'Software'), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Rakefile b/Rakefile
index 0d2bb42..33bbf85 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,10 +1,13 @@
-require "rspec/core/rake_task"
-require "bundler/gem_tasks"
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+require 'rubocop/rake_task'
-desc "Run specs"
+desc 'Run specs'
RSpec::Core::RakeTask.new do |t|
t.verbose = false
t.rspec_opts = '--color --order random'
end
-task :default => :spec
+RuboCop::RakeTask.new
+
+task default: [:spec, :rubocop]
diff --git a/bin/commander b/bin/commander
index 393daec..faaf322 100755
--- a/bin/commander
+++ b/bin/commander
@@ -8,30 +8,78 @@ program :version, Commander::VERSION
program :description, 'Commander utility program.'
command :init do |c|
- c.syntax = 'commander init <file>'
+ c.syntax = 'commander init [option] <file>'
c.summary = 'Initialize a commander template'
- c.description = 'Initialize an empty <file> with a commander template,
+ c.description = 'Initialize an empty <file> with a commander template,
allowing very quick creation of commander executables.'
- c.example 'Create a new file with a commander template.', 'commander init bin/my_executable'
+ c.example 'Create a new classic style template file.', 'commander init bin/my_executable'
+ c.example 'Create a new modular style template file.', 'commander init --modular bin/my_executable'
+ c.option '-m', '--modular', 'Initialize a modular style template'
c.action do |args, options|
file = args.shift || abort('file argument required.')
name = ask 'Machine name of program: '
description = ask 'Describe your program: '
commands = ask_for_array 'List the commands you wish to create: '
begin
- File.open(file, 'w') do |f|
- f.write <<-"...".gsub!(/^ {10}/, '')
+ if options.modular
+ File.open(file, 'w') do |f|
+ f.write <<-"...".gsub!(/^ {10}/, '')
#!/usr/bin/env ruby
-
+
+ require 'rubygems'
+ require 'commander'
+
+ class MyApplication
+ include Commander::Methods
+ # include whatever modules you need
+
+ def run
+ program :name, '#{name}'
+ program :version, '0.0.1'
+ program :description, '#{description}'
+
+ ...
+ commands.each do |command|
+ f.write <<-"...".gsub!(/^ {12}/, '')
+ command :#{command} do |c|
+ c.syntax = '#{name} #{command} [options]'
+ c.summary = ''
+ c.description = ''
+ c.example 'description', 'command example'
+ c.option '--some-switch', 'Some switch that does something'
+ c.action do |args, options|
+ # Do something or c.when_called #{name.capitalize}::Commands::#{command.capitalize}
+ end
+ end
+
+ ...
+ end
+ f.write <<-"...".gsub!(/^ {12}/, '')
+ run!
+ end
+ end
+
+ MyApplication.new.run if $0 == __FILE__
+ ...
+ end
+
+ File.chmod(0755, file)
+ say "Initialized modular template in #{file}"
+ else
+ File.open(file, 'w') do |f|
+ f.write <<-"...".gsub!(/^ {10}/, '')
+ #!/usr/bin/env ruby
+
require 'rubygems'
require 'commander/import'
-
+
+ program :name, '#{name}'
program :version, '0.0.1'
program :description, '#{description}'
-
- ...
- commands.each do |command|
- f.write <<-"...".gsub!(/^ {12}/, '')
+
+ ...
+ commands.each do |command|
+ f.write <<-"...".gsub!(/^ {12}/, '')
command :#{command} do |c|
c.syntax = '#{name} #{command} [options]'
c.summary = ''
@@ -43,13 +91,14 @@ command :init do |c|
end
end
- ...
+ ...
+ end
end
- end
- File.chmod 0755, file
- say "Initialized template in #{file}"
- rescue Exception => e
- abort e
- end
+ File.chmod 0755, file
+ say "Initialized template in #{file}"
+ end
+ rescue => e
+ abort e
+ end
end
-end
\ No newline at end of file
+end
diff --git a/commander.gemspec b/commander.gemspec
index 15cbb35..1990387 100644
--- a/commander.gemspec
+++ b/commander.gemspec
@@ -1,26 +1,29 @@
# -*- encoding: utf-8 -*-
-$:.push File.expand_path("../lib", __FILE__)
-require "commander/version"
+$LOAD_PATH.push File.expand_path('../lib', __FILE__)
+require 'commander/version'
Gem::Specification.new do |s|
- s.name = "commander"
+ s.name = 'commander'
s.version = Commander::VERSION
- s.authors = ["TJ Holowaychuk", "Gabriel Gilder"]
- s.email = ["ggilder at tractionco.com"]
- s.homepage = "http://visionmedia.github.com/commander"
- s.summary = "The complete solution for Ruby command-line executables"
- s.description = "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."
-
- s.rubyforge_project = "commander"
+ s.authors = ['TJ Holowaychuk', 'Gabriel Gilder']
+ s.email = ['gabriel at gabrielgilder.com']
+ s.license = 'MIT'
+ s.homepage = 'https://github.com/commander-rb/commander'
+ s.summary = 'The complete solution for Ruby command-line executables'
+ s.description = '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.'
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
- s.require_paths = ["lib"]
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
+ s.require_paths = ['lib']
+
+ s.add_runtime_dependency('highline', '~> 1.7.2')
- s.add_runtime_dependency("highline", "~> 1.6.11")
-
- s.add_development_dependency("rspec", "~> 2")
- s.add_development_dependency("rake")
- s.add_development_dependency("simplecov")
-end
\ No newline at end of file
+ s.add_development_dependency('rspec', '~> 3.2')
+ s.add_development_dependency('rake')
+ s.add_development_dependency('simplecov')
+ s.add_development_dependency('rubocop', '~> 0.29.1')
+ if RUBY_VERSION < '2.0'
+ s.add_development_dependency('json', '< 2.0')
+ end
+end
diff --git a/lib/commander.rb b/lib/commander.rb
index ee93f7b..b0decd6 100644
--- a/lib/commander.rb
+++ b/lib/commander.rb
@@ -30,3 +30,6 @@ require 'commander/runner'
require 'commander/command'
require 'commander/help_formatters'
require 'commander/platform'
+require 'commander/delegates'
+require 'commander/methods'
+require 'commander/configure'
diff --git a/lib/commander/blank.rb b/lib/commander/blank.rb
index 68e764d..07164a4 100644
--- a/lib/commander/blank.rb
+++ b/lib/commander/blank.rb
@@ -1,8 +1,7 @@
-
module Blank
- def self.included base
+ def self.included(base)
base.class_eval do
instance_methods.each { |m| undef_method m unless m =~ /^__|object_id/ }
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/commander/command.rb b/lib/commander/command.rb
index 7a76d54..fb15816 100644
--- a/lib/commander/command.rb
+++ b/lib/commander/command.rb
@@ -1,47 +1,45 @@
-
require 'optparse'
module Commander
class Command
-
attr_accessor :name, :examples, :syntax, :description
attr_accessor :summary, :proxy_options, :options
-
+
##
# Options struct.
class Options
include Blank
-
+
def initialize
@table = {}
end
-
+
def __hash__
@table
end
-
- def method_missing meth, *args, &block
+
+ def method_missing(meth, *args)
meth.to_s =~ /=$/ ? @table[meth.to_s.chop.to_sym] = args.first : @table[meth]
end
-
- def default defaults = {}
+
+ def default(defaults = {})
@table = defaults.merge! @table
end
-
+
def inspect
- "<Commander::Command::Options #{ __hash__.map { |k,v| "#{k}=#{v.inspect}" }.join(', ') }>"
+ "<Commander::Command::Options #{ __hash__.map { |k, v| "#{k}=#{v.inspect}" }.join(', ') }>"
end
end
-
+
##
# Initialize new command with specified _name_.
-
- def initialize name
+
+ def initialize(name)
@name, @examples, @when_called = name.to_s, [], []
@options, @proxy_options = [], []
end
-
+
##
# Add a usage example for this command.
#
@@ -49,22 +47,22 @@ module Commander
# created by the help formatters.
#
# === Examples
- #
+ #
# command :something do |c|
# c.example "Should do something", "my_command something"
# end
#
-
- def example description, command
+
+ def example(description, command)
@examples << [description, command]
end
-
+
##
# Add an option.
#
# Options are parsed via OptionParser so view it
# for additional usage documentation. A block may optionally be
- # passed to handle the option, otherwise the _options_ struct seen below
+ # passed to handle the option, otherwise the _options_ struct seen below
# contains the results of this option. This handles common formats such as:
#
# -h, --help options.help # => bool
@@ -75,18 +73,18 @@ module Commander
# --date [DATE] options.date # => date or nil when optional argument not set
#
# === Examples
- #
+ #
# command :something do |c|
# c.option '--recursive', 'Do something recursively'
# c.option '--file FILE', 'Specify a file'
# c.option('--info', 'Display info') { puts "handle with block" }
# c.option '--[no-]feature', 'With or without feature'
# c.option '--list FILES', Array, 'List the files specified'
- #
+ #
# c.when_called do |args, options|
# do_something_recursively if options.recursive
# do_something_with_file options.file if options.file
- # end
+ # end
# end
#
# === Help Formatters
@@ -105,109 +103,108 @@ module Commander
# c.option '--time TIME', Time
# c.option '--date [DATE]', Date
#
-
- def option *args, &block
+
+ def option(*args, &block)
switches, description = Runner.separate_switches_from_description(*args)
proc = block || option_proc(switches)
@options << {
- :args => args,
- :proc => proc,
- :switches => switches,
- :description => description,
+ args: args,
+ proc: proc,
+ switches: switches,
+ description: description,
}
end
-
+
##
- # Handle execution of command. The handler may be a class,
+ # Handle execution of command. The handler may be a class,
# object, or block (see examples below).
#
# === Examples
- #
+ #
# # Simple block handling
# c.when_called do |args, options|
# # do something
- # end
- #
+ # end
+ #
# # Create inst of Something and pass args / options
# c.when_called MyLib::Command::Something
- #
+ #
# # Create inst of Something and use arbitrary method
# c.when_called MyLib::Command::Something, :some_method
- #
+ #
# # Pass an object to handle callback (requires method symbol)
# c.when_called SomeObject, :some_method
#
-
- def when_called *args, &block
- raise ArgumentError, 'must pass an object, class, or block.' if args.empty? and !block
+
+ def when_called(*args, &block)
+ fail ArgumentError, 'must pass an object, class, or block.' if args.empty? && !block
@when_called = block ? [block] : args
end
- alias :action :when_called
-
+ alias_method :action, :when_called
+
##
# Run the command with _args_.
#
# * parses options, call option blocks
# * invokes when_called proc
#
-
- def run *args
+
+ def run(*args)
call parse_options_and_call_procs(*args)
end
-
+
#:stopdoc:
-
+
##
- # Parses options and calls associated procs,
+ # Parses options and calls associated procs,
# returning the arguments remaining.
-
- def parse_options_and_call_procs *args
+
+ def parse_options_and_call_procs(*args)
return args if args.empty?
- @options.inject OptionParser.new do |opts, option|
+ @options.each_with_object(OptionParser.new) do |option, opts|
opts.on(*option[:args], &option[:proc])
opts
end.parse! args
end
-
+
##
# Call the commands when_called block with _args_.
-
- def call args = []
+
+ def call(args = [])
object = @when_called.shift
meth = @when_called.shift || :call
options = proxy_option_struct
case object
- when Proc ; object.call(args, options)
- when Class ; meth != :call ? object.new.send(meth, args, options) : object.new(args, options)
- else object.send(meth, args, options) if object
- end
+ when Proc then object.call(args, options)
+ when Class then meth != :call ? object.new.send(meth, args, options) : object.new(args, options)
+ else object.send(meth, args, options) if object
+ end
end
-
+
##
# Creates an Options instance populated with the option values
# collected by the #option_proc.
-
+
def proxy_option_struct
- proxy_options.inject Options.new do |options, (option, value)|
+ proxy_options.each_with_object(Options.new) do |(option, value), options|
# options that are present will evaluate to true
value = true if value.nil?
options.__send__ :"#{option}=", value
options
end
end
-
+
##
# Option proxy proc used when a block is not explicitly passed
# via the #option method. This allows commander to auto-populate
# and work with option values.
-
- def option_proc switches
- lambda { |value| proxy_options << [Runner.switch_to_sym(switches.last), value] }
+
+ def option_proc(switches)
+ ->(value) { proxy_options << [Runner.switch_to_sym(switches.last), value] }
end
-
- def inspect
+
+ def inspect
"<Commander::Command:#{name}>"
end
-
end
-end
\ No newline at end of file
+end
diff --git a/lib/commander/configure.rb b/lib/commander/configure.rb
new file mode 100644
index 0000000..eaefe25
--- /dev/null
+++ b/lib/commander/configure.rb
@@ -0,0 +1,14 @@
+module Commander
+ def configure(*configuration_opts, &configuration_block)
+ configuration_module = Module.new
+ configuration_module.extend Commander::Methods
+
+ configuration_module.class_exec(*configuration_opts, &configuration_block)
+
+ configuration_module.class_exec do
+ run!
+ end
+ end
+
+ module_function :configure
+end
diff --git a/lib/commander/core_ext.rb b/lib/commander/core_ext.rb
index 016f323..d1d9a8d 100644
--- a/lib/commander/core_ext.rb
+++ b/lib/commander/core_ext.rb
@@ -1,3 +1,2 @@
-
require 'commander/core_ext/array'
-require 'commander/core_ext/object'
\ No newline at end of file
+require 'commander/core_ext/object'
diff --git a/lib/commander/core_ext/array.rb b/lib/commander/core_ext/array.rb
index 80ac3b7..daf765a 100644
--- a/lib/commander/core_ext/array.rb
+++ b/lib/commander/core_ext/array.rb
@@ -1,6 +1,4 @@
-
class Array
-
##
# Split _string_ into an array. Used in
# conjunction with Highline's #ask, or #ask_for_array
@@ -18,9 +16,9 @@ class Array
# list = ask_for_array 'Favorite cookies: '
#
- def self.parse string
+ def self.parse(string)
# Using reverse + lookahead to work around Ruby 1.8's lack of lookbehind
+ # TODO: simplify now that we don't support Ruby 1.8
string.reverse.split(/\s(?!\\)/).reverse.map { |s| s.reverse.gsub('\\ ', ' ') }
end
-
end
diff --git a/lib/commander/core_ext/object.rb b/lib/commander/core_ext/object.rb
index 9d33f16..7319de6 100644
--- a/lib/commander/core_ext/object.rb
+++ b/lib/commander/core_ext/object.rb
@@ -1,11 +1,8 @@
-
class Object
-
##
# Return the current binding.
-
+
def get_binding
binding
end
-
end
diff --git a/lib/commander/delegates.rb b/lib/commander/delegates.rb
index f069ad5..8071803 100644
--- a/lib/commander/delegates.rb
+++ b/lib/commander/delegates.rb
@@ -1,13 +1,25 @@
-
module Commander
module Delegates
- %w( add_command command program run! global_option
- commands alias_command default_command ).each do |meth|
+ %w(
+ add_command
+ command
+ program
+ run!
+ global_option
+ alias_command
+ default_command
+ always_trace!
+ never_trace!
+ ).each do |meth|
eval <<-END, binding, __FILE__, __LINE__
- def #{meth} *args, &block
- ::Commander::Runner.instance.#{meth} *args, &block
+ def #{meth}(*args, &block)
+ ::Commander::Runner.instance.#{meth}(*args, &block)
end
END
end
+
+ def defined_commands(*args, &block)
+ ::Commander::Runner.instance.commands(*args, &block)
+ end
end
-end
\ No newline at end of file
+end
diff --git a/lib/commander/help_formatters.rb b/lib/commander/help_formatters.rb
index 00a23ff..95c9d24 100644
--- a/lib/commander/help_formatters.rb
+++ b/lib/commander/help_formatters.rb
@@ -1,13 +1,49 @@
-
module Commander
module HelpFormatter
autoload :Base, 'commander/help_formatters/base'
autoload :Terminal, 'commander/help_formatters/terminal'
autoload :TerminalCompact, 'commander/help_formatters/terminal_compact'
+ class Context
+ def initialize(target)
+ @target = target
+ end
+
+ def get_binding
+ @target.instance_eval { binding }.tap do |bind|
+ decorate_binding(bind)
+ end
+ end
+
+ # No-op, override in subclasses.
+ def decorate_binding(_bind)
+ end
+ end
+
+ class ProgramContext < Context
+ def decorate_binding(bind)
+ bind.eval("max_command_length = #{max_command_length(bind)}")
+ bind.eval("max_aliases_length = #{max_aliases_length(bind)}")
+ end
+
+ def max_command_length(bind)
+ max_key_length(bind.eval('@commands'))
+ end
+
+ def max_aliases_length(bind)
+ max_key_length(bind.eval('@aliases'))
+ end
+
+ def max_key_length(hash, default = 20)
+ longest = hash.keys.max_by(&:size)
+ longest ? longest.size : default
+ end
+ end
+
module_function
- def indent amount, text
- text.gsub("\n", "\n" + (' ' * amount))
+
+ def indent(amount, text)
+ text.to_s.gsub("\n", "\n" + (' ' * amount))
end
end
end
diff --git a/lib/commander/help_formatters/base.rb b/lib/commander/help_formatters/base.rb
index 59d120f..9227904 100644
--- a/lib/commander/help_formatters/base.rb
+++ b/lib/commander/help_formatters/base.rb
@@ -1,18 +1,24 @@
-
module Commander
-
##
# = Help Formatter
#
# Commander's help formatters control the output when
# either the help command, or --help switch are called.
# The default formatter is Commander::HelpFormatter::Terminal.
-
+
module HelpFormatter
- class Base
- def initialize runner; @runner = runner end
- def render; 'Implement global help here' end
- def render_command command; "Implement help for #{command.name} here" end
+ class Base
+ def initialize(runner)
+ @runner = runner
+ end
+
+ def render
+ 'Implement global help here'
+ end
+
+ def render_command(command)
+ "Implement help for #{command.name} here"
+ end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/commander/help_formatters/terminal.rb b/lib/commander/help_formatters/terminal.rb
index 743469f..fb6ecf0 100644
--- a/lib/commander/help_formatters/terminal.rb
+++ b/lib/commander/help_formatters/terminal.rb
@@ -1,20 +1,19 @@
-
require 'erb'
module Commander
module HelpFormatter
class Terminal < Base
def render
- template(:help).result @runner.get_binding
+ template(:help).result(ProgramContext.new(@runner).get_binding)
end
-
- def render_command command
- template(:command_help).result command.get_binding
+
+ def render_command(command)
+ template(:command_help).result(Context.new(command).get_binding)
end
-
- def template name
+
+ def template(name)
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal', "#{name}.erb")), nil, '-')
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/commander/help_formatters/terminal/command_help.erb b/lib/commander/help_formatters/terminal/command_help.erb
index 19b58df..2635907 100644
--- a/lib/commander/help_formatters/terminal/command_help.erb
+++ b/lib/commander/help_formatters/terminal/command_help.erb
@@ -29,7 +29,7 @@
<% for option in @options -%>
<%= option[:switches].join ', ' %>
- <%= option[:description] %>
+ <%= Commander::HelpFormatter.indent 8, option[:description] %>
<% end -%>
<% end -%>
diff --git a/lib/commander/help_formatters/terminal/help.erb b/lib/commander/help_formatters/terminal/help.erb
index 32b153a..7386531 100644
--- a/lib/commander/help_formatters/terminal/help.erb
+++ b/lib/commander/help_formatters/terminal/help.erb
@@ -9,13 +9,13 @@
<%= $terminal.color "COMMANDS", :bold %>:
<% for name, command in @commands.sort -%>
<% unless alias? name %>
- <%= "%-20s %s" % [command.name, command.summary || command.description] -%>
+ <%= "%-#{max_command_length}s %s" % [command.name, command.summary || command.description] -%>
<% end -%>
<% end %>
<% unless @aliases.empty? %>
<%= $terminal.color "ALIASES", :bold %>:
<% for alias_name, args in @aliases.sort %>
- <%= "%-20s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] -%>
+ <%= "%-#{max_aliases_length}s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] -%>
<% end %>
<% end %>
<% unless @options.empty? -%>
diff --git a/lib/commander/help_formatters/terminal_compact.rb b/lib/commander/help_formatters/terminal_compact.rb
index 27f1e0b..88d77ca 100644
--- a/lib/commander/help_formatters/terminal_compact.rb
+++ b/lib/commander/help_formatters/terminal_compact.rb
@@ -1,12 +1,11 @@
-
require 'erb'
module Commander
module HelpFormatter
class TerminalCompact < Terminal
- def template name
+ def template(name)
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal_compact', "#{name}.erb")), nil, '-')
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/commander/help_formatters/terminal_compact/help.erb b/lib/commander/help_formatters/terminal_compact/help.erb
index 7d5f1da..a01a432 100644
--- a/lib/commander/help_formatters/terminal_compact/help.erb
+++ b/lib/commander/help_formatters/terminal_compact/help.erb
@@ -5,13 +5,13 @@
Commands:
<% for name, command in @commands.sort -%>
<% unless alias? name -%>
- <%= "%-20s %s" % [command.name, command.summary || command.description] %>
+ <%= "%-#{max_command_length}s %s" % [command.name, command.summary || command.description] %>
<% end -%>
<% end -%>
<% unless @aliases.empty? %>
Aliases:
<% for alias_name, args in @aliases.sort -%>
- <%= "%-20s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] %>
+ <%= "%-#{max_aliases_length}s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] %>
<% end -%>
<% end %>
<% unless @options.empty? -%>
diff --git a/lib/commander/import.rb b/lib/commander/import.rb
index dab5efe..e2e846d 100644
--- a/lib/commander/import.rb
+++ b/lib/commander/import.rb
@@ -1,10 +1,5 @@
-
require 'commander'
-require 'commander/delegates'
-include Commander::UI
-include Commander::UI::AskForClass
-include Commander::Delegates
+include Commander::Methods
-$terminal.wrap_at = HighLine::SystemExtensions.terminal_size.first - 5 rescue 80 if $stdin.tty?
at_exit { run! }
diff --git a/lib/commander/methods.rb b/lib/commander/methods.rb
new file mode 100644
index 0000000..a9f2387
--- /dev/null
+++ b/lib/commander/methods.rb
@@ -0,0 +1,11 @@
+module Commander
+ module Methods
+ include Commander::UI
+ include Commander::UI::AskForClass
+ include Commander::Delegates
+
+ if $stdin.tty? && (cols = $terminal.output_cols) >= 40
+ $terminal.wrap_at = cols - 5
+ end
+ end
+end
diff --git a/lib/commander/platform.rb b/lib/commander/platform.rb
index e39f8b1..47eb827 100644
--- a/lib/commander/platform.rb
+++ b/lib/commander/platform.rb
@@ -1,4 +1,3 @@
-
module Commander
module Platform
def self.jruby?
diff --git a/lib/commander/runner.rb b/lib/commander/runner.rb
index 64d644e..1d90d5f 100644
--- a/lib/commander/runner.rb
+++ b/lib/commander/runner.rb
@@ -1,96 +1,119 @@
-
require 'optparse'
module Commander
class Runner
-
#--
# Exceptions
#++
class CommandError < StandardError; end
class InvalidCommandError < CommandError; end
-
+
##
# Array of commands.
-
+
attr_reader :commands
-
+
##
# Global options.
-
+
attr_reader :options
-
+
##
# Hash of help formatter aliases.
-
+
attr_reader :help_formatter_aliases
##
# Initialize a new command runner. Optionally
# supplying _args_ for mocking, or arbitrary usage.
-
- def initialize args = ARGV
+
+ def initialize(args = ARGV)
@args, @commands, @aliases, @options = args, {}, {}, []
@help_formatter_aliases = help_formatter_alias_defaults
@program = program_defaults
+ @always_trace = false
+ @never_trace = false
create_default_commands
end
-
+
##
# Return singleton Runner instance.
-
+
def self.instance
@singleton ||= new
end
-
+
##
# Run command parsing and execution process.
-
+
def run!
- trace = false
+ trace = @always_trace || false
require_program :version, :description
trap('INT') { abort program(:int_message) } if program(:int_message)
trap('INT') { program(:int_block).call } if program(:int_block)
global_option('-h', '--help', 'Display help documentation') do
- args = @args - %w[-h --help]
+ args = @args - %w(-h --help)
command(:help).run(*args)
return
end
- global_option('-v', '--version', 'Display version information') { say version; return }
- global_option('-t', '--trace', 'Display backtrace when an error occurs') { trace = true }
+ global_option('-v', '--version', 'Display version information') do
+ say version
+ return
+ end
+ global_option('-t', '--trace', 'Display backtrace when an error occurs') { trace = true } unless @never_trace || @always_trace
parse_global_options
remove_global_options options, @args
- unless trace
+ if trace
+ run_active_command
+ else
begin
run_active_command
rescue InvalidCommandError => e
abort "#{e}. Use --help for more information"
rescue \
- OptionParser::InvalidOption,
+ OptionParser::InvalidOption,
OptionParser::InvalidArgument,
OptionParser::MissingArgument => e
abort e.to_s
rescue => e
- abort "error: #{e}. Use --trace to view backtrace"
+ if @never_trace
+ abort "error: #{e}."
+ else
+ abort "error: #{e}. Use --trace to view backtrace"
+ end
end
- else
- run_active_command
end
end
-
+
##
# Return program version.
-
+
def version
- '%s %s' % [program(:name), program(:version)]
+ format('%s %s', program(:name), program(:version))
end
-
+
+ ##
+ # Enable tracing on all executions (bypasses --trace)
+
+ def always_trace!
+ @always_trace = true
+ @never_trace = false
+ end
+
+ ##
+ # Hide the trace option from the help menus and don't add it as a global option
+
+ def never_trace!
+ @never_trace = true
+ @always_trace = false
+ end
+
##
# Assign program information.
#
# === Examples
- #
+ #
# # Set data
# program :name, 'Commander'
# program :version, Commander::VERSION
@@ -100,7 +123,7 @@ module Commander
# program :int_message 'Bye bye!'
# program :help_formatter, :compact
# program :help_formatter, Commander::HelpFormatter::TerminalCompact
- #
+ #
# # Get data
# program :name # => 'Commander'
#
@@ -113,9 +136,9 @@ module Commander
# :help Allows addition of arbitrary global help blocks
# :int_message Message to display when interrupted (CTRL + C)
#
-
- def program key, *args, &block
- if key == :help and !args.empty?
+
+ def program(key, *args, &block)
+ if key == :help && !args.empty?
@program[:help] ||= {}
@program[:help][args.first] = args.at(1)
elsif key == :help_formatter && !args.empty?
@@ -129,150 +152,154 @@ module Commander
@program[key]
end
end
-
+
##
# Creates and yields a command instance when a block is passed.
# Otherwise attempts to return the command, raising InvalidCommandError when
# it does not exist.
#
# === Examples
- #
+ #
# command :my_command do |c|
# c.when_called do |args|
# # Code
# end
# end
#
-
- def command name, &block
+
+ def command(name, &block)
yield add_command(Commander::Command.new(name)) if block
@commands[name.to_s]
end
-
+
##
# Add a global option; follows the same syntax as Command#option
# This would be used for switches such as --version, --trace, etc.
-
- def global_option *args, &block
- switches, description = Runner.separate_switches_from_description *args
+
+ def global_option(*args, &block)
+ switches, description = Runner.separate_switches_from_description(*args)
@options << {
- :args => args,
- :proc => block,
- :switches => switches,
- :description => description,
+ args: args,
+ proc: block,
+ switches: switches,
+ description: description,
}
end
-
+
##
# Alias command _name_ with _alias_name_. Optionally _args_ may be passed
# as if they were being passed straight to the original command via the command-line.
-
- def alias_command alias_name, name, *args
+
+ def alias_command(alias_name, name, *args)
@commands[alias_name.to_s] = command name
@aliases[alias_name.to_s] = args
end
-
+
##
# Default command _name_ to be used when no other
# command is found in the arguments.
-
- def default_command name
+
+ def default_command(name)
@default_command = name
end
-
+
##
# Add a command object to this runner.
-
- def add_command command
+
+ def add_command(command)
@commands[command.name] = command
end
-
+
##
# Check if command _name_ is an alias.
-
- def alias? name
+
+ def alias?(name)
@aliases.include? name.to_s
end
-
+
##
# Check if a command _name_ exists.
-
- def command_exists? name
+
+ def command_exists?(name)
@commands[name.to_s]
end
-
+
#:stopdoc:
-
+
##
# Get active command within arguments passed to this runner.
-
+
def active_command
@__active_command ||= command(command_name_from_args)
end
-
+
##
# Attempts to locate a command name from within the arguments.
# Supports multi-word commands, using the largest possible match.
-
+
def command_name_from_args
@__command_name_from_args ||= (valid_command_names_from(*@args.dup).sort.last || @default_command)
end
-
+
##
# Returns array of valid command names found within _args_.
-
- def valid_command_names_from *args
+
+ def valid_command_names_from(*args)
arg_string = args.delete_if { |value| value =~ /^-/ }.join ' '
commands.keys.find_all { |name| name if /^#{name}\b/.match arg_string }
end
-
+
##
# Help formatter instance.
-
+
def help_formatter
@__help_formatter ||= program(:help_formatter).new self
end
-
+
##
# Return arguments without the command name.
-
+
def args_without_command_name
removed = []
parts = command_name_from_args.split rescue []
@args.dup.delete_if do |arg|
- removed << arg if parts.include?(arg) and not removed.include?(arg)
+ removed << arg if parts.include?(arg) && !removed.include?(arg)
end
end
-
+
##
# Returns hash of help formatter alias defaults.
-
+
def help_formatter_alias_defaults
- return :compact => HelpFormatter::TerminalCompact
+ {
+ compact: HelpFormatter::TerminalCompact,
+ }
end
-
+
##
# Returns hash of program defaults.
-
+
def program_defaults
- return :help_formatter => HelpFormatter::Terminal,
- :name => File.basename($0)
+ {
+ help_formatter: HelpFormatter::Terminal,
+ name: File.basename($PROGRAM_NAME),
+ }
end
-
+
##
- # Creates default commands such as 'help' which is
+ # Creates default commands such as 'help' which is
# essentially the same as using the --help switch.
-
+
def create_default_commands
command :help do |c|
c.syntax = 'commander help [command]'
- c.description = 'Display global or [command] help documentation.'
+ c.description = 'Display global or [command] help documentation'
c.example 'Display global help', 'command help'
c.example "Display help for 'foo'", 'command help foo'
- c.when_called do |args, options|
- enable_paging
+ c.when_called do |args, _options|
+ UI.enable_paging
if args.empty?
- say help_formatter.render
+ say help_formatter.render
else
command = command args.join(' ')
begin
@@ -285,33 +312,35 @@ module Commander
end
end
end
-
+
##
# Raises InvalidCommandError when a _command_ is not found.
-
- def require_valid_command command = active_command
- raise InvalidCommandError, 'invalid command', caller if command.nil?
+
+ def require_valid_command(command = active_command)
+ fail InvalidCommandError, 'invalid command', caller if command.nil?
end
-
+
##
# Removes global _options_ from _args_. This prevents an invalid
# option error from occurring when options are parsed
# again for the command.
-
- def remove_global_options options, args
+
+ def remove_global_options(options, args)
# TODO: refactor with flipflop, please TJ ! have time to refactor me !
options.each do |option|
switches = option[:switches].dup
next if switches.empty?
- if switchHasArg = switches.any? { |s| s =~ /[ =]/ }
+ if (switch_has_arg = switches.any? { |s| s =~ /[ =]/ })
switches.map! { |s| s[0, s.index('=') || s.index(' ') || s.length] }
end
+ switches = expand_optionally_negative_switches(switches)
+
past_switch, arg_removed = false, false
args.delete_if do |arg|
- if switches.any? { |s| arg[0, s.length] == s }
- arg_removed = !switchHasArg
+ if switches.any? { |s| s[0, arg.length] == arg }
+ arg_removed = !switch_has_arg
past_switch = true
elsif past_switch && !arg_removed && arg !~ /^-/
arg_removed = true
@@ -322,14 +351,27 @@ module Commander
end
end
end
-
+
+ # expand switches of the style '--[no-]blah' into both their
+ # '--blah' and '--no-blah' variants, so that they can be
+ # properly detected and removed
+ def expand_optionally_negative_switches(switches)
+ switches.reduce([]) do |memo, val|
+ if val =~ /\[no-\]/
+ memo << val.gsub(/\[no-\]/, '')
+ memo << val.gsub(/\[no-\]/, 'no-')
+ else
+ memo << val
+ end
+ end
+ end
+
##
# Parse global command options.
-
- def parse_global_options
+ def parse_global_options
parser = options.inject(OptionParser.new) do |options, option|
- options.on *option[:args], &global_option_proc(option[:switches], &option[:proc])
+ options.on(*option[:args], &global_option_proc(option[:switches], &option[:proc]))
end
options = @args.dup
@@ -341,44 +383,44 @@ module Commander
retry
end
end
-
+
##
# Returns a proc allowing for commands to inherit global options.
# This functionality works whether a block is present for the global
# option or not, so simple switches such as --verbose can be used
# without a block, and used throughout all commands.
-
- def global_option_proc switches, &block
+
+ def global_option_proc(switches, &block)
lambda do |value|
unless active_command.nil?
active_command.proxy_options << [Runner.switch_to_sym(switches.last), value]
end
- yield value if block and !value.nil?
+ yield value if block && !value.nil?
end
end
-
+
##
# Raises a CommandError when the program any of the _keys_ are not present, or empty.
-
- def require_program *keys
+
+ def require_program(*keys)
keys.each do |key|
- raise CommandError, "program #{key} required" if program(key).nil? or program(key).empty?
+ fail CommandError, "program #{key} required" if program(key).nil? || program(key).empty?
end
end
-
+
##
# Return switches and description separated from the _args_ passed.
- def self.separate_switches_from_description *args
- switches = args.find_all { |arg| arg.to_s =~ /^-/ }
- description = args.last unless !args.last.is_a? String or args.last.match(/^-/)
- return switches, description
+ def self.separate_switches_from_description(*args)
+ switches = args.find_all { |arg| arg.to_s =~ /^-/ }
+ description = args.last if args.last.is_a?(String) && !args.last.match(/^-/)
+ [switches, description]
end
-
+
##
# Attempts to generate a method name symbol from +switch+.
# For example:
- #
+ #
# -h # => :h
# --trace # => :trace
# --some-switch # => :some_switch
@@ -386,26 +428,25 @@ module Commander
# --file FILE # => :file
# --list of,things # => :list
#
-
- def self.switch_to_sym switch
+
+ def self.switch_to_sym(switch)
switch.scan(/[\-\]](\w+)/).join('_').to_sym rescue nil
end
-
+
##
# Run the active command.
-
+
def run_active_command
require_valid_command
if alias? command_name_from_args
- active_command.run *(@aliases[command_name_from_args.to_s] + args_without_command_name)
+ active_command.run(*(@aliases[command_name_from_args.to_s] + args_without_command_name))
else
- active_command.run *args_without_command_name
- end
- end
-
- def say *args #:nodoc:
- $terminal.say *args
+ active_command.run(*args_without_command_name)
+ end
end
+ def say(*args) #:nodoc:
+ $terminal.say(*args)
+ end
end
end
diff --git a/lib/commander/user_interaction.rb b/lib/commander/user_interaction.rb
index 653d482..08b5923 100644
--- a/lib/commander/user_interaction.rb
+++ b/lib/commander/user_interaction.rb
@@ -2,22 +2,20 @@ require 'tempfile'
require 'shellwords'
module Commander
-
##
# = User Interaction
#
# Commander's user interaction module mixes in common
- # methods which extend HighLine's functionality such
+ # methods which extend HighLine's functionality such
# as a #password method rather than calling #ask directly.
-
+
module UI
-
module_function
-
+
#--
# Auto include growl when available.
#++
-
+
begin
require 'growl'
rescue LoadError
@@ -25,26 +23,26 @@ module Commander
else
include Growl
end
-
+
##
# Ask the user for a password. Specify a custom
- # _message_ other than 'Password: ' or override the
+ # _message_ other than 'Password: ' or override the
# default _mask_ of '*'.
-
- def password message = 'Password: ', mask = '*'
+
+ def password(message = 'Password: ', mask = '*')
pass = ask(message) { |q| q.echo = mask }
pass = password message, mask if pass.nil? || pass.empty?
pass
end
-
+
##
# Choose from a set array of _choices_.
-
- def choose message, *choices
- say message
- super(*choices)
+
+ def choose(message = nil, *choices, &block)
+ say message if message
+ super(*choices, &block)
end
-
+
##
# 'Log' an _action_ to the terminal. This is typically used
# for verbose output regarding actions performed. For example:
@@ -53,9 +51,9 @@ module Commander
# remove path/to/old_file.rb
# remove path/to/old_file2.rb
#
-
- def log action, *args
- say '%15s %s' % [action, args.join(' ')]
+
+ def log(action, *args)
+ say format('%15s %s', action, args.join(' '))
end
##
@@ -66,7 +64,7 @@ module Commander
# say_ok 'It is ok', 'This is ok too'
#
- def say_ok *args
+ def say_ok(*args)
args.each do |arg|
say $terminal.color(arg, :green)
end
@@ -80,7 +78,7 @@ module Commander
# say_warning 'Be careful', 'Think about it'
#
- def say_warning *args
+ def say_warning(*args)
args.each do |arg|
say $terminal.color(arg, :yellow)
end
@@ -94,7 +92,7 @@ module Commander
# say_error 'It is not ok', 'This is not ok too'
#
- def say_error *args
+ def say_error(*args)
args.each do |arg|
say $terminal.color(arg, :red)
end
@@ -120,28 +118,28 @@ module Commander
##
# Speak _message_ using _voice_ at a speaking rate of _rate_
- #
+ #
# Voice defaults to 'Alex', which is one of the better voices.
# Speaking rate defaults to 175 words per minute
#
# === Examples
- #
+ #
# speak 'What is your favorite food? '
# food = ask 'favorite food?: '
- # speak "Wow, I like #{food} too. We have so much in common."
+ # speak "Wow, I like #{food} too. We have so much in common."
# speak "I like #{food} as well!", "Victoria", 190
#
# === Notes
#
# * MacOS only
#
-
- def speak message, voice = :Alex, rate = 175
+
+ def speak(message, voice = :Alex, rate = 175)
Thread.new { applescript "say #{message.inspect} using #{voice.to_s.inspect} speaking rate #{rate}" }
end
-
+
##
- # Converse with speech recognition.
+ # Converse with speech recognition.
#
# Currently a "poorman's" DSL to utilize applescript and
# the MacOS speech recognition server.
@@ -149,7 +147,7 @@ module Commander
# === Examples
#
# case converse 'What is the best food?', :cookies => 'Cookies', :unknown => 'Nothing'
- # when :cookies
+ # 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'
@@ -164,31 +162,36 @@ module Commander
#
# * MacOS only
#
-
- def converse prompt, responses = {}
- i, commands = 0, responses.map { |key, value| value.inspect }.join(',')
- statement = responses.inject '' do |statement, (key, value)|
- statement << (((i += 1) == 1 ?
- %(if response is "#{value}" then\n):
- %(else if response is "#{value}" then\n))) <<
- %(do shell script "echo '#{key}'"\n)
+
+ def converse(prompt, responses = {})
+ i, commands = 0, responses.map { |_key, value| value.inspect }.join(',')
+ statement = responses.inject '' do |inner_statement, (key, value)|
+ inner_statement <<
+ (
+ (i += 1) == 1 ?
+ %(if response is "#{value}" then\n) :
+ %(else if response is "#{value}" then\n)
+ ) <<
+ %(do shell script "echo '#{key}'"\n)
end
- applescript(%(
- tell application "SpeechRecognitionServer"
+ applescript(
+ %(
+ tell application "SpeechRecognitionServer"
set response to listen for {#{commands}} with prompt "#{prompt}"
#{statement}
end if
end tell
- )).strip.to_sym
+ ),
+ ).strip.to_sym
end
-
+
##
# Execute apple _script_.
-
- def applescript script
+
+ def applescript(script)
`osascript -e "#{ script.gsub('"', '\"') }"`
end
-
+
##
# Normalize IO streams, allowing for redirection of
# +input+ and/or +output+, for example:
@@ -213,19 +216,18 @@ module Commander
# end
# end
#
-
- def io input = nil, output = nil, &block
+
+ def io(input = nil, output = nil, &block)
$stdin = File.new(input) if input
$stdout = File.new(output, 'r+') if output
- if block
- yield
- reset_io
- end
+ return unless block
+ yield
+ reset_io
end
-
+
##
# Reset IO to initial constant streams.
-
+
def reset_io
$stdin, $stdout = STDIN, STDOUT
end
@@ -234,12 +236,12 @@ module Commander
# Find an editor available in path. Optionally supply the _preferred_
# editor. Returns the name as a string, nil if none is available.
- def available_editor preferred = nil
- [preferred, ENV['EDITOR'], 'mate -w', 'vim', 'vi', 'emacs', 'nano', 'pico'].
- compact.
- find {|name| system("hash #{name.split.first} 2>&-") }
+ def available_editor(preferred = nil)
+ [preferred, ENV['EDITOR'], 'mate -w', 'vim', 'vi', 'emacs', 'nano', 'pico']
+ .compact
+ .find { |name| system("hash #{name.split.first} 2>&-") }
end
-
+
##
# Prompt an editor for input. Optionally supply initial
# _input_ which is written to the editor.
@@ -252,8 +254,8 @@ module Commander
# ask_editor('foo') # => prompts EDITOR with default text of 'foo'
# ask_editor('foo', 'mate -w') # => prompts TextMate with default text of 'foo'
#
-
- def ask_editor input = nil, preferred_editor = nil
+
+ def ask_editor(input = nil, preferred_editor = nil)
editor = available_editor preferred_editor
program = Commander::Runner.instance.program(:name).downcase rescue 'commander'
tmpfile = Tempfile.new program
@@ -265,10 +267,10 @@ module Commander
tmpfile.unlink
end
end
-
+
##
# Enable paging of output after called.
-
+
def enable_paging
return unless $stdout.tty?
return unless Process.respond_to? :fork
@@ -279,19 +281,21 @@ module Commander
# configurations that don't support it, but versions before 1.9 don't
# seem to do this reliably and instead raise a NotImplementedError
# (which is rescued below).
-
+
if Kernel.fork
$stdin.reopen read
- write.close; read.close
+ write.close
+ read.close
Kernel.select [$stdin]
- ENV['LESS'] = 'FSRX'
+ ENV['LESS'] = 'FSRX' unless ENV.key? 'LESS'
pager = ENV['PAGER'] || 'less'
exec pager rescue exec '/bin/sh', '-c', pager
else
# subprocess
$stdout.reopen write
$stderr.reopen write if $stderr.tty?
- write.close; read.close
+ write.close
+ read.close
end
rescue NotImplementedError
ensure
@@ -310,40 +314,42 @@ module Commander
# end
#
- def progress arr, options = {}, &block
+ def progress(arr, options = {})
bar = ProgressBar.new arr.length, options
bar.show
arr.each { |v| bar.increment yield(v) }
end
-
+
##
# Implements ask_for_CLASS methods.
-
+
module AskForClass
# All special cases in HighLine::Question#convert, except those that implement #parse
- ([Float, Integer, String, Symbol, Regexp, Array, File, Pathname] +
- # All Classes that respond to #parse
- Object.constants.map do |const|
- # const_get(:Config) issues a deprecation warning on ruby 1.8.7
- Object.const_get(const) unless const == :Config
- end.select do |const|
- const.class == Class && const.respond_to?(:parse)
- end).each do |klass|
+ (
+ [Float, Integer, String, Symbol, Regexp, Array, File, Pathname] +
+ # All Classes that respond to #parse
+ Object.constants.map do |const|
+ # Ignore constants that trigger deprecation warnings
+ Object.const_get(const) unless [:Config, :TimeoutError, :MissingSourceFile].include?(const)
+ end.select do |const|
+ const.class == Class && const.respond_to?(:parse)
+ end
+ ).each do |klass|
define_method "ask_for_#{klass.to_s.downcase}" do |prompt|
$terminal.ask(prompt, klass)
end
end
end
-
+
##
# Substitute _hash_'s keys with their associated values in _str_.
-
- def replace_tokens str, hash #:nodoc:
- hash.inject str do |str, (key, value)|
- str.gsub ":#{key}", value.to_s
+
+ def replace_tokens(str, hash) #:nodoc:
+ hash.inject(str) do |string, (key, value)|
+ string.gsub ":#{key}", value.to_s
end
end
-
+
##
# = Progress Bar
#
@@ -352,12 +358,12 @@ module Commander
# be incremented. Note that a hash of tokens may be passed to
# #increment, (or returned when using Object#progress).
#
- # uris = %w(
+ # uris = %w(
# http://vision-media.ca
# http://yahoo.com
# http://google.com
# )
- #
+ #
# bar = Commander::UI::ProgressBar.new uris.length, options
# threads = []
# uris.each do |uri|
@@ -381,12 +387,11 @@ module Commander
#
class ProgressBar
-
##
# Creates a new progress bar.
#
# === Options
- #
+ #
# :title Title, defaults to "Progress"
# :width Width of :progress_bar
# :progress_str Progress string, defaults to "="
@@ -397,7 +402,7 @@ module Commander
#
# === Tokens
#
- # :title
+ # :title
# :percent_complete
# :progress_bar
# :step
@@ -407,7 +412,7 @@ module Commander
# :time_remaining
#
- def initialize total, options = {}
+ def initialize(total, options = {})
@total_steps, @step, @start_time = total, 0, Time.now
@title = options.fetch :title, 'Progress'
@width = options.fetch :width, 25
@@ -417,10 +422,10 @@ module Commander
@format = options.fetch :format, ':title |:progress_bar| :percent_complete% complete '
@tokens = options.fetch :tokens, {}
end
-
+
##
# Completion percentage.
-
+
def percent_complete
if @total_steps.zero?
100
@@ -428,69 +433,67 @@ module Commander
@step * 100 / @total_steps
end
end
-
+
##
# Time that has elapsed since the operation started.
-
+
def time_elapsed
Time.now - @start_time
end
-
+
##
# Estimated time remaining.
-
+
def time_remaining
(time_elapsed / @step) * steps_remaining
end
-
+
##
# Number of steps left.
-
+
def steps_remaining
@total_steps - @step
end
-
+
##
# Formatted progress bar.
-
+
def progress_bar
(@progress_str * (@width * percent_complete / 100)).ljust @width, @incomplete_str
end
-
+
##
# Generates tokens for this step.
-
+
def generate_tokens
{
- :title => @title,
- :percent_complete => percent_complete,
- :progress_bar => progress_bar,
- :step => @step,
- :steps_remaining => steps_remaining,
- :total_steps => @total_steps,
- :time_elapsed => "%0.2fs" % time_elapsed,
- :time_remaining => @step > 0 ? "%0.2fs" % time_remaining : '',
- }.
- merge! @tokens
+ title: @title,
+ percent_complete: percent_complete,
+ progress_bar: progress_bar,
+ step: @step,
+ steps_remaining: steps_remaining,
+ total_steps: @total_steps,
+ time_elapsed: format('%0.2fs', time_elapsed),
+ time_remaining: @step > 0 ? format('%0.2fs', time_remaining) : '',
+ }.merge! @tokens
end
##
# Output the progress bar.
def show
- unless finished?
- erase_line
- if completed?
- $terminal.say UI.replace_tokens(@complete_message, generate_tokens) if @complete_message.is_a? String
- else
- $terminal.say UI.replace_tokens(@format, generate_tokens) << ' '
- end
+ return if finished?
+ erase_line
+ if completed?
+ $terminal.say UI.replace_tokens(@complete_message, generate_tokens) if @complete_message.is_a? String
+ else
+ $terminal.say UI.replace_tokens(@format, generate_tokens) << ' '
end
end
-
+
##
# Whether or not the operation is complete, and we have finished.
-
+
def finished?
@step == @total_steps + 1
end
@@ -506,7 +509,7 @@ module Commander
# Increment progress. Optionally pass _tokens_ which
# can be displayed in the output format.
- def increment tokens = {}
+ def increment(tokens = {})
@step += 1
@tokens.merge! tokens if tokens.is_a? Hash
show
diff --git a/lib/commander/version.rb b/lib/commander/version.rb
index baeffbd..faa019f 100644
--- a/lib/commander/version.rb
+++ b/lib/commander/version.rb
@@ -1,3 +1,3 @@
module Commander
- VERSION = '4.1.5'
+ VERSION = '4.4.1'
end
diff --git a/metadata.yml b/metadata.yml
deleted file mode 100644
index ba801dc..0000000
--- a/metadata.yml
+++ /dev/null
@@ -1,157 +0,0 @@
---- !ruby/object:Gem::Specification
-name: commander
-version: !ruby/object:Gem::Version
- version: 4.1.5
- prerelease:
-platform: ruby
-authors:
-- TJ Holowaychuk
-- Gabriel Gilder
-autorequire:
-bindir: bin
-cert_chain: []
-date: 2013-08-11 00:00:00.000000000 Z
-dependencies:
-- !ruby/object:Gem::Dependency
- name: highline
- requirement: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ~>
- - !ruby/object:Gem::Version
- version: 1.6.11
- type: :runtime
- prerelease: false
- version_requirements: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ~>
- - !ruby/object:Gem::Version
- version: 1.6.11
-- !ruby/object:Gem::Dependency
- name: rspec
- requirement: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ~>
- - !ruby/object:Gem::Version
- version: '2'
- type: :development
- prerelease: false
- version_requirements: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ~>
- - !ruby/object:Gem::Version
- version: '2'
-- !ruby/object:Gem::Dependency
- name: rake
- requirement: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ! '>='
- - !ruby/object:Gem::Version
- version: '0'
- type: :development
- prerelease: false
- version_requirements: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ! '>='
- - !ruby/object:Gem::Version
- version: '0'
-- !ruby/object:Gem::Dependency
- name: simplecov
- requirement: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ! '>='
- - !ruby/object:Gem::Version
- version: '0'
- type: :development
- prerelease: false
- version_requirements: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ! '>='
- - !ruby/object:Gem::Version
- version: '0'
-description: 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.
-email:
-- ggilder at tractionco.com
-executables:
-- commander
-extensions: []
-extra_rdoc_files: []
-files:
-- .gitignore
-- .travis.yml
-- DEVELOPMENT
-- Gemfile
-- History.rdoc
-- Manifest
-- README.rdoc
-- Rakefile
-- bin/commander
-- commander.gemspec
-- lib/commander.rb
-- lib/commander/blank.rb
-- lib/commander/command.rb
-- lib/commander/core_ext.rb
-- lib/commander/core_ext/array.rb
-- lib/commander/core_ext/object.rb
-- lib/commander/delegates.rb
-- lib/commander/help_formatters.rb
-- lib/commander/help_formatters/base.rb
-- lib/commander/help_formatters/terminal.rb
-- lib/commander/help_formatters/terminal/command_help.erb
-- lib/commander/help_formatters/terminal/help.erb
-- lib/commander/help_formatters/terminal_compact.rb
-- lib/commander/help_formatters/terminal_compact/command_help.erb
-- lib/commander/help_formatters/terminal_compact/help.erb
-- lib/commander/import.rb
-- lib/commander/platform.rb
-- lib/commander/runner.rb
-- lib/commander/user_interaction.rb
-- lib/commander/version.rb
-- spec/command_spec.rb
-- spec/core_ext/array_spec.rb
-- spec/core_ext/object_spec.rb
-- spec/help_formatters/terminal_spec.rb
-- spec/runner_spec.rb
-- spec/spec_helper.rb
-- spec/ui_spec.rb
-homepage: http://visionmedia.github.com/commander
-licenses: []
-post_install_message:
-rdoc_options: []
-require_paths:
-- lib
-required_ruby_version: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ! '>='
- - !ruby/object:Gem::Version
- version: '0'
-required_rubygems_version: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ! '>='
- - !ruby/object:Gem::Version
- version: '0'
-requirements: []
-rubyforge_project: commander
-rubygems_version: 1.8.22
-signing_key:
-specification_version: 3
-summary: The complete solution for Ruby command-line executables
-test_files:
-- spec/command_spec.rb
-- spec/core_ext/array_spec.rb
-- spec/core_ext/object_spec.rb
-- spec/help_formatters/terminal_spec.rb
-- spec/runner_spec.rb
-- spec/spec_helper.rb
-- spec/ui_spec.rb
diff --git a/spec/command_spec.rb b/spec/command_spec.rb
index 2026f3d..75c2296 100644
--- a/spec/command_spec.rb
+++ b/spec/command_spec.rb
@@ -1,157 +1,157 @@
require 'spec_helper'
describe Commander::Command do
-
+ include Commander::Methods
+
before :each do
mock_terminal
create_test_command
end
-
+
describe 'Options' do
before :each do
- @options = Commander::Command::Options.new
+ @options = Commander::Command::Options.new
end
-
- it "should act like an open struct" do
+
+ it 'should act like an open struct' do
@options.send = 'mail'
@options.call = true
- @options.send.should eq('mail')
- @options.call.should eq(true)
+ expect(@options.send).to eq('mail')
+ expect(@options.call).to eq(true)
end
-
- it "should allow __send__ to function as always" do
+
+ it 'should allow __send__ to function as always' do
@options.send = 'foo'
- @options.__send__(:send).should eq('foo')
+ expect(@options.__send__(:send)).to eq('foo')
end
end
-
- describe "#option" do
- it "should add options" do
- lambda { @command.option '--recursive' }.should change(@command.options, :length).from(1).to(2)
+
+ describe '#option' do
+ it 'should add options' do
+ expect { @command.option '--recursive' }.to change(@command.options, :length).from(1).to(2)
end
-
- it "should allow procs as option handlers" do
- @command.option('--recursive') { |recursive| recursive.should be_true }
+
+ it 'should allow procs as option handlers' do
+ @command.option('--recursive') { |recursive| expect(recursive).to be true }
@command.run '--recursive'
end
-
- it "should allow usage of common method names" do
+
+ it 'should allow usage of common method names' do
@command.option '--open file'
- @command.when_called { |_, options| options.open.should eq('foo') }
+ @command.when_called { |_, options| expect(options.open).to eq('foo') }
@command.run '--open', 'foo'
end
end
-
- describe "#run" do
- describe "should invoke #when_called" do
- it "with arguments seperated from options" do
- @command.when_called { |args, options| args.join(' ').should eq('just some args') }
+
+ describe '#run' do
+ describe 'should invoke #when_called' do
+ it 'with arguments seperated from options' do
+ @command.when_called { |args, _options| expect(args.join(' ')).to eq('just some args') }
@command.run '--verbose', 'just', 'some', 'args'
end
-
- it "calling the #call method by default when an object is called" do
- object = mock 'Object'
- object.should_receive(:call).once
+
+ it 'calling the #call method by default when an object is called' do
+ object = double 'Object'
+ expect(object).to receive(:call).once
@command.when_called object
- @command.run 'foo'
+ @command.run 'foo'
end
-
- it "should allow #action as an alias to #when_called" do
- object = mock 'Object'
- object.should_receive(:call).once
+
+ it 'should allow #action as an alias to #when_called' do
+ object = double 'Object'
+ expect(object).to receive(:call).once
@command.action object
@command.run 'foo'
end
-
- it "calling an arbitrary method when an object is called" do
- object = mock 'Object'
- object.should_receive(:foo).once
+
+ it 'calling an arbitrary method when an object is called' do
+ object = double 'Object'
+ expect(object).to receive(:foo).once
@command.when_called object, :foo
- @command.run 'foo'
+ @command.run 'foo'
end
-
- it "should raise an error when no handler is present" do
- lambda { @command.when_called }.should raise_error(ArgumentError)
+
+ it 'should raise an error when no handler is present' do
+ expect { @command.when_called }.to raise_error(ArgumentError)
end
end
-
- describe "should populate options with" do
- it "boolean values" do
+
+ describe 'should populate options with' do
+ it 'boolean values' do
@command.option '--[no-]toggle'
- @command.when_called { |_, options| options.toggle.should be_true }
+ @command.when_called { |_, options| expect(options.toggle).to be true }
@command.run '--toggle'
- @command.when_called { |_, options| options.toggle.should be_false }
+ @command.when_called { |_, options| expect(options.toggle).to be false }
@command.run '--no-toggle'
end
- it "mandatory arguments" do
+ it 'mandatory arguments' do
@command.option '--file FILE'
- @command.when_called { |_, options| options.file.should eq('foo') }
+ @command.when_called { |_, options| expect(options.file).to eq('foo') }
@command.run '--file', 'foo'
- lambda { @command.run '--file' }.should raise_error(OptionParser::MissingArgument)
+ expect { @command.run '--file' }.to raise_error(OptionParser::MissingArgument)
end
- describe "optional arguments" do
+ describe 'optional arguments' do
before do
@command.option '--use-config [file] '
end
- it "should return the argument when provided" do
- @command.when_called { |_, options| options.use_config.should eq('foo') }
+ it 'should return the argument when provided' do
+ @command.when_called { |_, options| expect(options.use_config).to eq('foo') }
@command.run '--use-config', 'foo'
end
- it "should return true when present without an argument" do
- @command.when_called { |_, options| options.use_config.should be_true }
+ it 'should return true when present without an argument' do
+ @command.when_called { |_, options| expect(options.use_config).to be true }
@command.run '--use-config'
end
- it "should return nil when not present" do
- @command.when_called { |_, options| options.use_config.should be_nil }
+ it 'should return nil when not present' do
+ @command.when_called { |_, options| expect(options.use_config).to be_nil }
@command.run
end
end
- describe "typed arguments" do
+ describe 'typed arguments' do
before do
@command.option '--interval N', Integer
end
- it "should parse valid values" do
- @command.when_called { |_, options| options.interval.should eq(5) }
+ it 'should parse valid values' do
+ @command.when_called { |_, options| expect(options.interval).to eq(5) }
@command.run '--interval', '5'
end
- it "should reject invalid values" do
- lambda { @command.run '--interval', 'invalid' }.should raise_error(OptionParser::InvalidArgument)
+ it 'should reject invalid values' do
+ expect { @command.run '--interval', 'invalid' }.to raise_error(OptionParser::InvalidArgument)
end
end
- it "lists" do
+ it 'lists' do
@command.option '--fav COLORS', Array
- @command.when_called { |_, options| options.fav.should eq(['red', 'green', 'blue']) }
+ @command.when_called { |_, options| expect(options.fav).to eq(%w(red green blue)) }
@command.run '--fav', 'red,green,blue'
end
-
- it "lists with multi-word items" do
+
+ it 'lists with multi-word items' do
@command.option '--fav MOVIES', Array
- @command.when_called { |_, options| options.fav.should eq(['super\ bad', 'nightmare']) }
- @command.run '--fav', 'super\ bad,nightmare'
+ @command.when_called { |_, options| expect(options.fav).to eq(['super\ bad', 'nightmare']) }
+ @command.run '--fav', 'super\ bad,nightmare'
end
-
- it "defaults" do
+
+ it 'defaults' do
@command.option '--files LIST', Array
@command.option '--interval N', Integer
@command.when_called do |_, options|
options.default \
- :files => ['foo', 'bar'],
- :interval => 5
- options.files.should eq(['foo', 'bar'])
- options.interval.should eq(15)
+ files: %w(foo bar),
+ interval: 5
+ expect(options.files).to eq(%w(foo bar))
+ expect(options.interval).to eq(15)
end
@command.run '--interval', '15'
end
end
end
-
end
diff --git a/spec/configure_spec.rb b/spec/configure_spec.rb
new file mode 100644
index 0000000..5426ade
--- /dev/null
+++ b/spec/configure_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+require 'commander/configure'
+
+describe Commander do
+ describe '.configure' do
+ it 'calls the given block' do
+ expect { Commander.configure { throw :block_called } }.to throw_symbol(:block_called)
+ end
+
+ describe 'called block' do
+ before(:each) do
+ allow(Commander::Runner.instance).to receive(:run!)
+ end
+
+ it 'provides Commander configuration methods' do
+ Commander.configure do
+ program :name, 'test'
+ end
+
+ expect(Commander::Runner.instance.program(:name)).to eq('test')
+ end
+
+ it 'passes all arguments to the block' do
+ Commander.configure('foo') do |first_arg|
+ program :name, first_arg
+ end
+
+ expect(Commander::Runner.instance.program(:name)).to eq('foo')
+ end
+ end
+
+ it 'calls Runner#run! after calling the configuration block' do
+ expect(Commander::Runner.instance).to receive(:run!)
+ Commander.configure {}
+ end
+ end
+end
diff --git a/spec/core_ext/array_spec.rb b/spec/core_ext/array_spec.rb
index 64c6987..16f7174 100644
--- a/spec/core_ext/array_spec.rb
+++ b/spec/core_ext/array_spec.rb
@@ -1,20 +1,18 @@
require 'spec_helper'
describe Array do
-
- describe "#parse" do
- it "should seperate a list of words into an array" do
- Array.parse('just a test').should eq(['just', 'a', 'test'])
+ describe '#parse' do
+ it 'should seperate a list of words into an array' do
+ expect(Array.parse('just a test')).to eq(%w(just a test))
end
- it "should preserve escaped whitespace" do
- Array.parse('just a\ test').should eq(['just', 'a test'])
+ it 'should preserve escaped whitespace' do
+ expect(Array.parse('just a\ test')).to eq(['just', 'a test'])
end
- it "should match %w behavior with multiple backslashes" do
+ it 'should match %w behavior with multiple backslashes' do
str = 'just a\\ test'
- Array.parse(str).should eq(eval("%w(#{str})"))
+ expect(Array.parse(str)).to eq(eval("%w(#{str})"))
end
end
-
end
diff --git a/spec/core_ext/object_spec.rb b/spec/core_ext/object_spec.rb
index b6c0f41..852823b 100644
--- a/spec/core_ext/object_spec.rb
+++ b/spec/core_ext/object_spec.rb
@@ -1,21 +1,19 @@
require 'spec_helper'
describe Object do
-
- describe "#get_binding" do
- it "should return the objects binding" do
- lambda {}.get_binding.should be_instance_of(Binding)
+ describe '#get_binding' do
+ it 'should return the objects binding' do
+ expect(-> {}.get_binding).to be_instance_of(Binding)
end
end
- describe "#method_missing" do
- it "should preserve its original behavior for missing methods" do
- lambda { i_am_a_missing_method() }.should raise_error(NoMethodError)
+ describe '#method_missing' do
+ it 'should preserve its original behavior for missing methods' do
+ expect { send(:i_am_a_missing_method) }.to raise_error(NoMethodError)
end
- it "should preserve its original behavior for missing variables" do
- lambda { i_am_a_missing_variable }.should raise_error(NameError)
+ it 'should preserve its original behavior for missing variables' do
+ expect { i_am_a_missing_variable }.to raise_error(NameError)
end
end
-
end
diff --git a/spec/help_formatters/terminal_compact_spec.rb b/spec/help_formatters/terminal_compact_spec.rb
new file mode 100644
index 0000000..ca9eb5c
--- /dev/null
+++ b/spec/help_formatters/terminal_compact_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe Commander::HelpFormatter::TerminalCompact do
+ include Commander::Methods
+
+ before :each do
+ mock_terminal
+ end
+
+ describe 'global help' do
+ before :each do
+ new_command_runner 'help' do
+ program :help_formatter, :compact
+ command :'install gem' do |c|
+ c.syntax = 'foo install gem [options]'
+ c.summary = 'Install some gem'
+ end
+ end.run!
+ @global_help = @output.string
+ end
+
+ describe 'should display' do
+ it 'the command name' do
+ expect(@global_help).to include('install gem')
+ end
+
+ it 'the summary' do
+ expect(@global_help).to include('Install some gem')
+ end
+ end
+ end
+
+ describe 'command help' do
+ before :each do
+ new_command_runner 'help', 'install', 'gem' do
+ program :help_formatter, :compact
+ command :'install gem' do |c|
+ c.syntax = 'foo install gem [options]'
+ c.summary = 'Install some gem'
+ c.description = 'Install some gem, blah blah blah'
+ c.example 'one', 'two'
+ c.example 'three', 'four'
+ end
+ end.run!
+ @command_help = @output.string
+ end
+
+ describe 'should display' do
+ it 'the command name' do
+ expect(@command_help).to include('install gem')
+ end
+
+ it 'the description' do
+ expect(@command_help).to include('Install some gem, blah blah blah')
+ end
+
+ it 'all examples' do
+ expect(@command_help).to include('# one')
+ expect(@command_help).to include('two')
+ expect(@command_help).to include('# three')
+ expect(@command_help).to include('four')
+ end
+
+ it 'the syntax' do
+ expect(@command_help).to include('foo install gem [options]')
+ end
+ end
+ end
+end
diff --git a/spec/help_formatters/terminal_spec.rb b/spec/help_formatters/terminal_spec.rb
index ee0ce29..c0f5810 100644
--- a/spec/help_formatters/terminal_spec.rb
+++ b/spec/help_formatters/terminal_spec.rb
@@ -1,12 +1,13 @@
require 'spec_helper'
describe Commander::HelpFormatter::Terminal do
-
+ include Commander::Methods
+
before :each do
mock_terminal
end
-
- describe "global help" do
+
+ describe 'global help' do
before :each do
new_command_runner 'help' do
command :'install gem' do |c|
@@ -16,19 +17,19 @@ describe Commander::HelpFormatter::Terminal do
end.run!
@global_help = @output.string
end
-
- describe "should display" do
- it "the command name" do
- @global_help.should include('install gem')
+
+ describe 'should display' do
+ it 'the command name' do
+ expect(@global_help).to include('install gem')
end
-
- it "the summary" do
- @global_help.should include('Install some gem')
+
+ it 'the summary' do
+ expect(@global_help).to include('Install some gem')
end
end
end
-
- describe "command help" do
+
+ describe 'command help' do
before :each do
new_command_runner 'help', 'install', 'gem' do
command :'install gem' do |c|
@@ -41,27 +42,26 @@ describe Commander::HelpFormatter::Terminal do
end.run!
@command_help = @output.string
end
-
- describe "should display" do
- it "the command name" do
- @command_help.should include('install gem')
+
+ describe 'should display' do
+ it 'the command name' do
+ expect(@command_help).to include('install gem')
end
-
- it "the description" do
- @command_help.should include('Install some gem, blah blah blah')
+
+ it 'the description' do
+ expect(@command_help).to include('Install some gem, blah blah blah')
end
-
- it "all examples" do
- @command_help.should include('# one')
- @command_help.should include('two')
- @command_help.should include('# three')
- @command_help.should include('four')
+
+ it 'all examples' do
+ expect(@command_help).to include('# one')
+ expect(@command_help).to include('two')
+ expect(@command_help).to include('# three')
+ expect(@command_help).to include('four')
end
-
- it "the syntax" do
- @command_help.should include('foo install gem [options]')
+
+ it 'the syntax' do
+ expect(@command_help).to include('foo install gem [options]')
end
end
end
-
end
diff --git a/spec/methods_spec.rb b/spec/methods_spec.rb
new file mode 100644
index 0000000..853d32c
--- /dev/null
+++ b/spec/methods_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+require 'commander/methods'
+
+describe Commander::Methods do
+ it 'includes Commander::UI' do
+ expect(subject.ancestors).to include(Commander::UI)
+ end
+
+ it 'includes Commander::UI::AskForClass' do
+ expect(subject.ancestors).to include(Commander::UI::AskForClass)
+ end
+
+ it 'includes Commander::Delegates' do
+ expect(subject.ancestors).to include(Commander::Delegates)
+ end
+
+ it 'does not change the Object ancestors' do
+ expect(Object.ancestors).not_to include(Commander::UI)
+ end
+end
diff --git a/spec/runner_spec.rb b/spec/runner_spec.rb
index 620aec5..828f308 100644
--- a/spec/runner_spec.rb
+++ b/spec/runner_spec.rb
@@ -1,116 +1,140 @@
require 'spec_helper'
describe Commander do
+ include Commander::Methods
+
before :each do
$stderr = StringIO.new
mock_terminal
create_test_command
end
-
- describe "#program" do
- it "should set / get program information" do
+
+ describe '#program' do
+ it 'should set / get program information' do
program :name, 'test'
- program(:name).should eq('test')
+ expect(program(:name)).to eq('test')
end
-
- it "should allow arbitrary blocks of global help documentation" do
+
+ it 'should allow arbitrary blocks of global help documentation' do
program :help, 'Copyright', 'TJ Holowaychuk'
- program(:help)['Copyright'].should eq('TJ Holowaychuk')
+ expect(program(:help)['Copyright']).to eq('TJ Holowaychuk')
end
-
- it "should raise an error when required info has not been set" do
+
+ it 'should raise an error when required info has not been set' do
new_command_runner '--help'
program :version, ''
- lambda { run! }.should raise_error(Commander::Runner::CommandError)
+ expect { run! }.to raise_error(Commander::Runner::CommandError)
end
-
- it "should allow aliases of help formatters" do
+
+ it 'should allow aliases of help formatters' do
program :help_formatter, :compact
- program(:help_formatter).should eq(Commander::HelpFormatter::TerminalCompact)
+ expect(program(:help_formatter)).to eq(Commander::HelpFormatter::TerminalCompact)
end
end
-
- describe "#command" do
- it "should return a command instance when only the name is passed" do
- command(:test).should be_instance_of(Commander::Command)
+
+ describe '#command' do
+ it 'should return a command instance when only the name is passed' do
+ expect(command(:test)).to be_instance_of(Commander::Command)
end
-
- it "should return nil when the command does not exist" do
- command(:im_not_real).should be_nil
+
+ it 'should return nil when the command does not exist' do
+ expect(command(:im_not_real)).to be_nil
end
end
-
- describe "#separate_switches_from_description" do
- it "should seperate switches and description returning both" do
+
+ describe '#separate_switches_from_description' do
+ it 'should seperate switches and description returning both' do
switches, description = *Commander::Runner.separate_switches_from_description('-h', '--help', 'display help')
- switches.should eq(['-h', '--help'])
- description.should eq('display help')
+ expect(switches).to eq(['-h', '--help'])
+ expect(description).to eq('display help')
end
end
-
- describe "#switch_to_sym" do
- it "should return a symbol based on the switch name" do
- Commander::Runner.switch_to_sym('--trace').should eq(:trace)
- Commander::Runner.switch_to_sym('--foo-bar').should eq(:foo_bar)
- Commander::Runner.switch_to_sym('--[no-]feature"').should eq(:feature)
- Commander::Runner.switch_to_sym('--[no-]feature ARG').should eq(:feature)
- Commander::Runner.switch_to_sym('--file [ARG]').should eq(:file)
- Commander::Runner.switch_to_sym('--colors colors').should eq(:colors)
+
+ describe '#switch_to_sym' do
+ it 'should return a symbol based on the switch name' do
+ expect(Commander::Runner.switch_to_sym('--trace')).to eq(:trace)
+ expect(Commander::Runner.switch_to_sym('--foo-bar')).to eq(:foo_bar)
+ expect(Commander::Runner.switch_to_sym('--[no-]feature"')).to eq(:feature)
+ expect(Commander::Runner.switch_to_sym('--[no-]feature ARG')).to eq(:feature)
+ expect(Commander::Runner.switch_to_sym('--file [ARG]')).to eq(:file)
+ expect(Commander::Runner.switch_to_sym('--colors colors')).to eq(:colors)
end
end
-
- describe "#alias_command" do
- it "should alias a command" do
+
+ describe '#alias_command' do
+ it 'should alias a command' do
alias_command :foo, :test
- command(:foo).should eq(command(:test))
+ expect(command(:foo)).to eq(command(:test))
end
-
- it "should pass arguments passed to the alias when called" do
+
+ it 'should pass arguments passed to the alias when called' do
gem_name = ''
new_command_runner 'install', 'gem', 'commander' do
command :install do |c|
c.option '--gem-name NAME', 'Install a gem'
c.when_called { |_, options| gem_name = options.gem_name }
- end
+ end
alias_command :'install gem', :install, '--gem-name'
end.run!
- gem_name.should eq('commander')
+ expect(gem_name).to eq('commander')
end
end
-
- describe "#global_option" do
- it "should be invoked when used in the args list" do
+
+ describe '#global_option' do
+ it 'should be invoked when used in the args list' do
file = ''
new_command_runner 'test', '--config', 'foo' do
global_option('--config FILE') { |f| file = f }
end.run!
- file.should eq('foo')
+ expect(file).to eq('foo')
end
-
- it "should be inherited by commands" do
+
+ it 'should be inherited by commands' do
quiet = nil
new_command_runner 'foo', '--quiet' do
global_option('--quiet', 'Suppress output')
command :foo do |c|
- c.when_called { |_, options| quiet = options.quiet }
+ c.when_called { |_, options| quiet = options.quiet }
end
end.run!
- quiet.should be_true
+ expect(quiet).to be true
end
-
- it "should be inherited by commands even when a block is present" do
+
+ it 'should be inherited by commands even when a block is present' do
quiet = nil
new_command_runner 'foo', '--quiet' do
global_option('--quiet', 'Suppress output') {}
command :foo do |c|
- c.when_called { |_, options| quiet = options.quiet }
+ c.when_called { |_, options| quiet = options.quiet }
+ end
+ end.run!
+ expect(quiet).to be true
+ end
+
+ it 'should be inherited by commands when the positive form of a [no-] option' do
+ quiet = nil
+ new_command_runner 'foo', '--quiet' do
+ global_option('--[no-]quiet', 'Suppress output') {}
+ command :foo do |c|
+ c.when_called { |_, options| quiet = options.quiet }
end
end.run!
- quiet.should be_true
+ expect(quiet).to be true
+ end
+
+ it 'should be inherited by commands when the negative form of a [no-] option' do
+ quiet = nil
+ new_command_runner 'foo', '--no-quiet' do
+ global_option('--[no-]quiet', 'Suppress output') {}
+ command :foo do |c|
+ c.when_called { |_, options| quiet = options.quiet }
+ end
+ end.run!
+ expect(quiet).to be false
end
end
- describe "#parse_global_options" do
+ describe '#parse_global_options' do
it 'should parse global options before command' do
global_option = nil
new_command_runner('--testing-global', 'foo') do
@@ -120,19 +144,19 @@ describe Commander do
c.when_called {}
end
end.run!
- global_option.should eq('MAGIC')
+ expect(global_option).to eq('MAGIC')
end
it 'should parse global options after command' do
global_option = nil
- new_command_runner('foo','--testing-global') do
+ new_command_runner('foo', '--testing-global') do
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.when_called {}
end
end.run!
- global_option.should eq('MAGIC')
+ expect(global_option).to eq('MAGIC')
end
it 'should parse global options placed before command options' do
@@ -146,7 +170,7 @@ describe Commander do
end
end.run!
- global_option.should eq('MAGIC')
+ expect(global_option).to eq('MAGIC')
end
it 'should parse global options placed after command options' do
@@ -160,7 +184,7 @@ describe Commander do
end
end.run!
- global_option.should eq('MAGIC')
+ expect(global_option).to eq('MAGIC')
end
it 'should parse global options surrounded by command options' do
@@ -175,7 +199,7 @@ describe Commander do
end
end.run!
- global_option.should eq('MAGIC')
+ expect(global_option).to eq('MAGIC')
end
it 'should not parse command options' do
@@ -190,8 +214,8 @@ describe Commander do
end
end.parse_global_options
- command_option.should be_nil
- global_option.should eq('MAGIC')
+ expect(command_option).to be_nil
+ expect(global_option).to eq('MAGIC')
end
it 'should not affect command arguments with values' do
@@ -206,8 +230,8 @@ describe Commander do
end
end.run!
- command_option.should eq('bar')
- global_option.should eq('MAGIC')
+ expect(command_option).to eq('bar')
+ expect(global_option).to eq('MAGIC')
end
it 'should not affect global arguments with values' do
@@ -216,14 +240,14 @@ describe Commander do
global_option('--testing-global VALUE') { |v| global_option = v }
command :foo do |c|
- c.option('--testing-command') { }
+ c.option('--testing-command') {}
c.when_called {}
end
end.run!
- global_option.should eq('bar')
+ expect(global_option).to eq('bar')
end
-
+
it 'should allow global arguments with values before command arguments (github issue #8)' do
global_option = nil
command_option = nil
@@ -236,297 +260,370 @@ describe Commander do
end
end.run!
- global_option.should eq('path')
- command_option.should eq('bar')
+ expect(global_option).to eq('path')
+ expect(command_option).to eq('bar')
end
end
-
- describe "#remove_global_options" do
- it "should remove only specified switches" do
+ describe '#remove_global_options' do
+ it 'should remove only specified switches' do
options, args = [], []
- options << { :switches => ['-t', '--trace'] }
- options << { :switches => ['--help'] }
- options << { :switches => ['--paths PATHS'] }
+ options << { switches: ['-t', '--trace'] }
+ options << { switches: ['--help'] }
+ options << { switches: ['--paths PATHS'] }
args << '-t'
args << '--help'
args << '--command'
args << '--command-with-arg' << 'rawr'
args << '--paths' << '"lib/**/*.js","spec/**/*.js"'
command_runner.remove_global_options options, args
- args.should eq(['--command', '--command-with-arg', 'rawr'])
+ expect(args).to eq(['--command', '--command-with-arg', 'rawr'])
end
- it "should not swallow an argument unless it expects an argument" do
+ it 'should not swallow an argument unless it expects an argument' do
options, args = [], []
- options << { :switches => ['-n', '--no-arg'] }
- options << { :switches => ['-y', '--yes ARG'] }
- options << { :switches => ['-a', '--alternative=ARG'] }
+ options << { switches: ['-n', '--no-arg'] }
+ options << { switches: ['-y', '--yes ARG'] }
+ options << { switches: ['-a', '--alternative=ARG'] }
args << '-n' << 'alpha'
args << '--yes' << 'deleted'
args << '-a' << 'deleted'
args << 'beta'
command_runner.remove_global_options options, args
- args.should eq(['alpha', 'beta'])
+ expect(args).to eq(%w(alpha beta))
+ end
+
+ it 'should remove a switch that is the positive form of the [no-] option' do
+ options, args = [], []
+ options << { switches: ['-g', '--[no-]good'] }
+ options << { switches: ['-y', '--yes ARG'] }
+ options << { switches: ['-a', '--alternative=ARG'] }
+ args << '--good' << 'alpha'
+ args << '--yes' << 'deleted'
+ args << '-a' << 'deleted'
+ args << 'beta'
+ command_runner.remove_global_options options, args
+ expect(args).to eq(%w(alpha beta))
+ end
+
+ it 'should remove a switch that is the negative form of the [no-] option' do
+ options, args = [], []
+ options << { switches: ['-g', '--[no-]good'] }
+ options << { switches: ['-y', '--yes ARG'] }
+ options << { switches: ['-a', '--alternative=ARG'] }
+ args << '--no-good' << 'alpha'
+ args << '--yes' << 'deleted'
+ args << '-a' << 'deleted'
+ args << 'beta'
+ command_runner.remove_global_options options, args
+ expect(args).to eq(%w(alpha beta))
+ end
+
+ it 'should not remove options that start with a global option name' do
+ options, args = [], []
+ options << { switches: ['-v', '--version'] }
+ args << '--versionCode' << 'something'
+ command_runner.remove_global_options options, args
+ expect(args).to eq(%w(--versionCode something))
end
end
-
- describe "--trace" do
- it "should display pretty errors by default" do
- pending("JRuby's Kernel.abort implementation is not testable") if Commander::Platform::jruby?
- lambda {
+
+ describe '--trace' do
+ it 'should display pretty errors by default' do
+ expect do
new_command_runner 'foo' do
- command(:foo) { |c| c.when_called { raise 'cookies!' } }
+ command(:foo) { |c| c.when_called { fail 'cookies!' } }
end.run!
- }.should raise_error(SystemExit, /error: cookies!. Use --trace/)
+ end.to raise_error(SystemExit, /error: cookies!. Use --trace/)
end
-
- it "should display callstack when using this switch" do
- lambda {
+
+ it 'should display callstack when using this switch' do
+ expect do
new_command_runner 'foo', '--trace' do
- command(:foo) { |c| c.when_called { raise 'cookies!' } }
- end.run!
- }.should raise_error(RuntimeError)
+ command(:foo) { |c| c.when_called { fail 'cookies!' } }
+ end.run!
+ end.to raise_error(RuntimeError)
end
end
-
- describe "--version" do
- it "should output program version" do
- run('--version').should eq("test 1.2.3\n")
+
+ describe '#always_trace!' do
+ it 'should enable tracing globally, regardless of whether --trace was passed or not' do
+ expect do
+ new_command_runner 'foo' do
+ always_trace!
+ command(:foo) { |c| c.when_called { fail 'cookies!' } }
+ end.run!
+ end.to raise_error(RuntimeError)
end
end
-
- describe "--help" do
- it "should not output an invalid command message" do
- run('--help').should_not == "invalid command. Use --help for more information\n"
+
+ describe '#never_trace!' do
+ it 'should disable tracing globally, regardless of whether --trace was passed or not' do
+ expect do
+ new_command_runner 'help', '--trace' do
+ never_trace!
+ end.run!
+ end.to raise_error(SystemExit, /invalid option: --trace/)
+ end
+
+ it 'should not prompt to use --trace switch on errors' do
+ msg = nil
+ begin
+ new_command_runner 'foo' do
+ never_trace!
+ command(:foo) { |c| c.when_called { fail 'cookies!' } }
+ end.run!
+ rescue SystemExit => e
+ msg = e.message
+ end
+ expect(msg).to match(/error: cookies!/)
+ expect(msg).not_to match(/--trace/)
end
-
- it "can be used before or after the command and options" do
- run('test', '--help').should eq("Implement help for test here\n")
+ end
+
+ context 'conflict between #always_trace! and #never_trace!' do
+ it 'respects the last used command' do
+ expect do
+ new_command_runner 'foo' do
+ never_trace!
+ always_trace!
+ command(:foo) { |c| c.when_called { fail 'cookies!' } }
+ end.run!
+ end.to raise_error(RuntimeError)
end
end
-
- describe "with invalid options" do
- it "should output an invalid option message" do
- pending("JRuby's Kernel.abort implementation is not testable") if Commander::Platform::jruby?
- lambda {
- run('test', '--invalid-option')
- }.should raise_error(SystemExit, /invalid option: --invalid-option/)
+
+ describe '--version' do
+ it 'should output program version' do
+ expect(run('--version')).to eq("test 1.2.3\n")
end
end
-
- describe "with invalid command passed" do
- it "should output an invalid command message" do
- pending("JRuby's Kernel.abort implementation is not testable") if Commander::Platform::jruby?
- lambda {
- run('foo')
- }.should raise_error(SystemExit, /invalid command. Use --help for more information/)
+
+ describe '--help' do
+ it 'should not output an invalid command message' do
+ expect(run('--help')).not_to eq("invalid command. Use --help for more information\n")
+ end
+
+ it 'can be used before or after the command and options' do
+ expect(run('test', '--help')).to eq("Implement help for test here\n")
end
end
-
- describe "with invalid command passed to help" do
- it "should output an invalid command message" do
- pending("JRuby's Kernel.abort implementation is not testable") if Commander::Platform::jruby?
- lambda {
+
+ describe 'with invalid options' do
+ it 'should output an invalid option message' do
+ expect do
+ run('test', '--invalid-option')
+ end.to raise_error(SystemExit, /invalid option: --invalid-option/)
+ end
+ end
+
+ describe 'with invalid command passed' do
+ it 'should output an invalid command message' do
+ expect do
+ run('foo')
+ end.to raise_error(SystemExit, /invalid command. Use --help for more information/)
+ end
+ end
+
+ describe 'with invalid command passed to help' do
+ it 'should output an invalid command message' do
+ expect do
run('help', 'does_not_exist')
- }.should raise_error(SystemExit, /invalid command. Use --help for more information/)
+ end.to raise_error(SystemExit, /invalid command. Use --help for more information/)
end
end
-
- describe "with invalid command passed to --help" do
- it "should output an invalid command message" do
- pending("JRuby's Kernel.abort implementation is not testable") if Commander::Platform::jruby?
- lambda {
+
+ describe 'with invalid command passed to --help' do
+ it 'should output an invalid command message' do
+ expect do
run('--help', 'does_not_exist')
- }.should raise_error(SystemExit, /invalid command. Use --help for more information/)
+ end.to raise_error(SystemExit, /invalid command. Use --help for more information/)
end
end
- describe "with invalid option passed to --help" do
- it "should output an invalid option message" do
- pending("JRuby's Kernel.abort implementation is not testable") if Commander::Platform::jruby?
- lambda {
+ describe 'with invalid option passed to --help' do
+ it 'should output an invalid option message' do
+ expect do
run('--help', 'test', '--invalid-option')
- }.should raise_error(SystemExit, /invalid option: --invalid-option/)
+ end.to raise_error(SystemExit, /invalid option: --invalid-option/)
end
end
-
- describe "#valid_command_names_from" do
- it "should return array of valid command names" do
+
+ describe '#valid_command_names_from' do
+ it 'should return array of valid command names' do
new_command_runner do
command('foo bar') {}
command('foo bar foo') {}
- command_runner.valid_command_names_from('foo', 'bar', 'foo').sort.should eq(['foo bar', 'foo bar foo'])
+ expect(command_runner.valid_command_names_from('foo', 'bar', 'foo').sort).to eq(['foo bar', 'foo bar foo'])
end
end
-
- it "should return empty array when no possible command names exist" do
+
+ it 'should return empty array when no possible command names exist' do
new_command_runner do
- command_runner.valid_command_names_from('fake', 'command', 'name').should eq([])
+ expect(command_runner.valid_command_names_from('fake', 'command', 'name')).to eq([])
end
end
- it "should match exact commands only" do
+ it 'should match exact commands only' do
new_command_runner do
command('foo') {}
- command_runner.valid_command_names_from('foobar').should eq([])
+ expect(command_runner.valid_command_names_from('foobar')).to eq([])
end
end
end
-
- describe "#command_name_from_args" do
- it "should locate command within arbitrary arguments passed" do
+
+ describe '#command_name_from_args' do
+ it 'should locate command within arbitrary arguments passed' do
new_command_runner '--help', '--arbitrary', 'test'
- command_runner.command_name_from_args.should eq('test')
+ expect(command_runner.command_name_from_args).to eq('test')
end
-
- it "should support multi-word commands" do
+
+ it 'should support multi-word commands' do
new_command_runner '--help', '--arbitrary', 'some', 'long', 'command', 'foo'
command('some long command') {}
- command_runner.command_name_from_args.should eq('some long command')
+ expect(command_runner.command_name_from_args).to eq('some long command')
end
-
- it "should match the longest possible command" do
+
+ it 'should match the longest possible command' do
new_command_runner '--help', '--arbitrary', 'foo', 'bar', 'foo'
command('foo bar') {}
command('foo bar foo') {}
- command_runner.command_name_from_args.should eq('foo bar foo' )
+ expect(command_runner.command_name_from_args).to eq('foo bar foo')
end
-
- it "should use the left-most command name when multiple are present" do
+
+ it 'should use the left-most command name when multiple are present' do
new_command_runner 'help', 'test'
- command_runner.command_name_from_args.should eq('help' )
+ expect(command_runner.command_name_from_args).to eq('help')
end
end
-
- describe "#active_command" do
- it "should resolve the active command" do
+
+ describe '#active_command' do
+ it 'should resolve the active command' do
new_command_runner '--help', 'test'
- command_runner.active_command.should be_instance_of(Commander::Command)
+ expect(command_runner.active_command).to be_instance_of(Commander::Command)
end
-
- it "should resolve active command when invalid options are passed" do
+
+ it 'should resolve active command when invalid options are passed' do
new_command_runner '--help', 'test', '--arbitrary'
- command_runner.active_command.should be_instance_of(Commander::Command)
+ expect(command_runner.active_command).to be_instance_of(Commander::Command)
end
-
- it "should return nil when the command is not found" do
+
+ it 'should return nil when the command is not found' do
new_command_runner 'foo'
- command_runner.active_command.should be_nil
+ expect(command_runner.active_command).to be_nil
end
end
-
- describe "#default_command" do
- it "should allow you to default any command when one is not explicitly passed" do
+
+ describe '#default_command' do
+ it 'should allow you to default any command when one is not explicitly passed' do
new_command_runner '--trace' do
default_command :test
- command(:test).should_receive(:run).once
- command_runner.active_command.should eq(command(:test))
+ expect(command(:test)).to receive(:run).once
+ expect(command_runner.active_command).to eq(command(:test))
end.run!
end
-
- it "should not prevent other commands from being called" do
+
+ it 'should not prevent other commands from being called' do
new_command_runner 'foo', 'bar', '--trace' do
default_command :test
- command(:'foo bar'){}
- command(:'foo bar').should_receive(:run).once
- command_runner.active_command.should eq(command(:'foo bar'))
+ command(:'foo bar') {}
+ expect(command(:'foo bar')).to receive(:run).once
+ expect(command_runner.active_command).to eq(command(:'foo bar'))
end.run!
end
-
- it "should not prevent longer commands to use the same words as the default" do
+
+ it 'should not prevent longer commands to use the same words as the default' do
new_command_runner 'foo', 'bar', 'something'
default_command :'foo bar'
- command(:'foo bar'){}
- command(:'foo bar something'){}
- command_runner.active_command.should eq(command(:'foo bar something'))
+ command(:'foo bar') {}
+ command(:'foo bar something') {}
+ expect(command_runner.active_command).to eq(command(:'foo bar something'))
end
-
- it "should allow defaulting of command aliases" do
+
+ it 'should allow defaulting of command aliases' do
new_command_runner '--trace' do
default_command :foobar
alias_command :foobar, :test
- command(:test).should_receive(:run).once
+ expect(command(:test)).to receive(:run).once
end.run!
end
end
-
- describe "should function correctly" do
- it "when options are passed before the command name" do
+
+ describe 'should function correctly' do
+ it 'when options are passed before the command name' do
new_command_runner '--verbose', 'test', 'foo', 'bar' do
@command.when_called do |args, options|
- args.should eq(['foo', 'bar'])
- options.verbose.should be_true
+ expect(args).to eq(%w(foo bar))
+ expect(options.verbose).to be true
end
end.run!
end
- it "when options are passed after the command name" do
+ it 'when options are passed after the command name' do
new_command_runner 'test', '--verbose', 'foo', 'bar' do
@command.when_called do |args, options|
- args.should eq(['foo', 'bar'])
- options.verbose.should be_true
+ expect(args).to eq(%w(foo bar))
+ expect(options.verbose).to be true
end
end.run!
end
- it "when an argument passed is the same name as the command" do
+ it 'when an argument passed is the same name as the command' do
new_command_runner 'test', '--verbose', 'foo', 'test', 'bar' do
@command.when_called do |args, options|
- args.should eq(['foo', 'test', 'bar'])
- options.verbose.should be_true
+ expect(args).to eq(%w(foo test bar))
+ expect(options.verbose).to be true
end
end.run!
end
-
- it "when using multi-word commands" do
+
+ it 'when using multi-word commands' do
new_command_runner '--verbose', 'my', 'command', 'something', 'foo', 'bar' do
command('my command') { |c| c.option('--verbose') }
- command_runner.command_name_from_args.should eq('my command')
- command_runner.args_without_command_name.should eq(['--verbose', 'something', 'foo', 'bar'])
+ expect(command_runner.command_name_from_args).to eq('my command')
+ expect(command_runner.args_without_command_name).to eq(['--verbose', 'something', 'foo', 'bar'])
end.run!
end
- it "when using multi-word commands with parts of the command name as arguments" do
+ it 'when using multi-word commands with parts of the command name as arguments' do
new_command_runner '--verbose', 'my', 'command', 'something', 'my', 'command' do
command('my command') { |c| c.option('--verbose') }
- command_runner.command_name_from_args.should eq('my command')
- command_runner.args_without_command_name.should eq(['--verbose', 'something', 'my', 'command'])
+ expect(command_runner.command_name_from_args).to eq('my command')
+ expect(command_runner.args_without_command_name).to eq(['--verbose', 'something', 'my', 'command'])
end.run!
end
-
- it "when using multi-word commands with other commands using the same words" do
+
+ it 'when using multi-word commands with other commands using the same words' do
new_command_runner '--verbose', 'my', 'command', 'something', 'my', 'command' do
command('my command') {}
command('my command something') { |c| c.option('--verbose') }
- command_runner.command_name_from_args.should eq('my command something')
- command_runner.args_without_command_name.should eq(['--verbose', 'my', 'command'])
+ expect(command_runner.command_name_from_args).to eq('my command something')
+ expect(command_runner.args_without_command_name).to eq(['--verbose', 'my', 'command'])
end.run!
end
end
- describe "options with optional arguments" do
- it "should return the argument when it is specified" do
+ describe 'options with optional arguments' do
+ it 'should return the argument when it is specified' do
new_command_runner 'foo', '--optional', 'arg1' do
command('foo') do |c|
c.option('--optional [argument]')
c.when_called do |_, options|
- options.optional.should eq('arg1')
+ expect(options.optional).to eq('arg1')
end
end
end.run!
end
- it "should return true when no argument is specified for the option" do
+ it 'should return true when no argument is specified for the option' do
new_command_runner 'foo', '--optional' do
command('foo') do |c|
c.option('--optional [argument]')
c.when_called do |_, options|
- options.optional.should be_true
+ expect(options.optional).to be true
end
end
end.run!
end
end
-
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c302ab6..83ed668 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,29 +1,17 @@
require 'rubygems'
require 'stringio'
require 'simplecov'
-SimpleCov.start
+SimpleCov.start do
+ add_filter '/spec/'
+end
# Unshift so that local files load instead of something in gems
-$:.unshift File.dirname(__FILE__) + '/../lib'
+$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
# This basically replicates the behavior of `require 'commander/import'`
# but without adding an `at_exit` hook, which interferes with exit code
require 'commander'
-require 'commander/delegates'
-
-include Commander::UI
-include Commander::UI::AskForClass
-include Commander::Delegates
-
-# prevent paging from actually occurring in test environment
-
-module Commander
- module UI
- def enable_paging
- return
- end
- end
-end
+require 'commander/methods'
# Mock terminal IO streams so we can spec against them
@@ -37,13 +25,13 @@ end
def create_test_command
command :test do |c|
- c.syntax = "test [options] <file>"
- c.description = "test description"
- c.example "description", "command"
- c.example "description 2", "command 2"
- c.option '-v', "--verbose", "verbose description"
- c.when_called do |args, options|
- "test %s" % args.join
+ c.syntax = 'test [options] <file>'
+ c.description = 'test description'
+ c.example 'description', 'command'
+ c.example 'description 2', 'command 2'
+ c.option '-v', '--verbose', 'verbose description'
+ c.when_called do |args, _options|
+ format('test %s', args.join)
end
end
@command = command :test
@@ -51,7 +39,7 @@ end
# Create a new command runner
-def new_command_runner *args, &block
+def new_command_runner(*args, &block)
Commander::Runner.instance_variable_set :"@singleton", Commander::Runner.new(args)
program :name, 'test'
program :version, '1.2.3'
@@ -67,9 +55,23 @@ def command_runner
Commander::Runner.instance
end
-def run *args
+def run(*args)
new_command_runner(*args) do
program :help_formatter, Commander::HelpFormatter::Base
- end.run!
+ end.run!
@output.string
-end
\ No newline at end of file
+end
+
+RSpec.configure do |c|
+ c.expect_with(:rspec) do |e|
+ e.syntax = :expect
+ end
+
+ c.mock_with(:rspec) do |m|
+ m.syntax = :expect
+ end
+
+ c.before(:each) do
+ allow(Commander::UI).to receive(:enable_paging)
+ end
+end
diff --git a/spec/ui_spec.rb b/spec/ui_spec.rb
index f4d3fea..a3b5fb7 100644
--- a/spec/ui_spec.rb
+++ b/spec/ui_spec.rb
@@ -1,30 +1,30 @@
require 'spec_helper'
describe Commander::UI do
-
- describe ".replace_tokens" do
- it "should replace tokens within a string, with hash values" do
- result = Commander::UI.replace_tokens 'Welcome :name, enjoy your :object'.freeze, :name => 'TJ', :object => 'cookie'
- result.should eq('Welcome TJ, enjoy your cookie')
+ include Commander::Methods
+
+ describe '.replace_tokens' do
+ it 'should replace tokens within a string, with hash values' do
+ result = Commander::UI.replace_tokens 'Welcome :name, enjoy your :object'.freeze, name: 'TJ', object: 'cookie'
+ expect(result).to eq('Welcome TJ, enjoy your cookie')
end
end
- describe "progress" do
- it "should not die on an empty list" do
+ describe 'progress' do
+ it 'should not die on an empty list' do
exception = false
begin
progress([]) {}
rescue
exception = true
end
- exception.should_not be_true
+ expect(exception).not_to be true
end
end
-
- describe ".available_editor" do
- it "should not fail on available editors with shell arguments" do
- Commander::UI.available_editor('sh -c').should eq('sh -c')
+
+ describe '.available_editor' do
+ it 'should not fail on available editors with shell arguments' do
+ expect(Commander::UI.available_editor('sh -c')).to eq('sh -c')
end
end
-
end
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-commander.git
More information about the Pkg-ruby-extras-commits
mailing list