commander-4.6.0/ 0000755 0000041 0000041 00000000000 14053714220 013514 5 ustar www-data www-data commander-4.6.0/.travis.yml 0000644 0000041 0000041 00000000242 14053714220 015623 0 ustar www-data www-data language: ruby
cache: bundler
before_install:
- gem update --system
- gem update bundler
rvm:
- 2.4
- 2.5
- 2.6
- 2.7
- 3.0
- jruby
- ruby-head
commander-4.6.0/.rspec 0000644 0000041 0000041 00000000036 14053714220 014630 0 ustar www-data www-data --color
--require spec_helper
commander-4.6.0/README.md 0000644 0000041 0000041 00000030267 14053714220 015003 0 ustar www-data www-data [
](https://travis-ci.org/commander-rb/commander)
[](https://inch-ci.org/github/commander-rb/commander)
# Commander
The complete solution for Ruby command-line executables.
Commander bridges the gap between other terminal related libraries
you know and love (OptionParser, HighLine), while providing many new
features, and an elegant API.
## Features
* Easier than baking cookies
* Parses options using OptionParser
* Auto-populates struct with options ( no more `{ |v| options[:recursive] = v }` )
* Auto-generates help documentation via pluggable help formatters
* Optional default command when none is present
* Global / Command level options
* Packaged with two help formatters (Terminal, TerminalCompact)
* Imports the highline gem for interacting with the terminal
* Adds additional user interaction functionality
* Highly customizable progress bar with intuitive, simple usage
* Multi-word command name support such as `drupal module install MOD`, rather than `drupal module_install MOD`
* Sexy paging for long bodies of text
* Support for MacOS text-to-speech
* Command aliasing (very powerful, as both switches and arguments can be used)
* Growl notification support for MacOS
* Use the `commander` executable to initialize a commander driven program
## Installation
$ gem install commander
## Quick Start
To generate a quick template for a commander app, run:
$ commander init yourfile.rb
To generate a quick modular style template for a commander app, run:
$ commander init --modular yourfile.rb
## Example
For more option examples view the `Commander::Command#option` method. Also
an important feature to note is that action may be a class to instantiate,
as well as an object, specifying a method to call, so view the RDoc for more information.
### Classic style
```ruby
require 'rubygems'
require 'commander/import'
# :name is optional, otherwise uses the basename of this executable
program :name, 'Foo Bar'
program :version, '1.0.0'
program :description, 'Stupid command that prints foo or bar.'
command :foo do |c|
c.syntax = 'foobar foo'
c.description = 'Displays foo'
c.action do |args, options|
say 'foo'
end
end
command :bar do |c|
c.syntax = 'foobar bar [options]'
c.description = 'Display bar with optional prefix and suffix'
c.option '--prefix STRING', String, 'Adds a prefix to bar'
c.option '--suffix STRING', String, 'Adds a suffix to bar'
c.action do |args, options|
options.default :prefix => '(', :suffix => ')'
say "#{options.prefix}bar#{options.suffix}"
end
end
```
Example output:
```
$ foobar bar
# => (bar)
$ foobar bar --suffix '}' --prefix '{'
# => {bar}
```
### Modular style
**NOTE:** Make sure to use `require 'commander'` rather than `require 'commander/import'`, otherwise Commander methods will still be imported into the global namespace.
```ruby
require 'rubygems'
require 'commander'
class MyApplication
include Commander::Methods
def run
program :name, 'Foo Bar'
program :version, '1.0.0'
program :description, 'Stupid command that prints foo or bar.'
command :foo do |c|
c.syntax = 'foobar foo'
c.description = 'Displays foo'
c.action do |args, options|
say 'foo'
end
end
run!
end
end
MyApplication.new.run if $0 == __FILE__
```
### Block style
```ruby
require 'rubygems'
require 'commander'
Commander.configure do
program :name, 'Foo Bar'
program :version, '1.0.0'
program :description, 'Stupid command that prints foo or bar.'
# see classic style example for options
end
```
## HighLine
As mentioned above, the highline gem is imported into the global scope. Here
are some quick examples for how to utilize highline in your commands:
```ruby
# Ask for password masked with '*' character
ask("Password: ") { |q| q.echo = "*" }
# Ask for password
ask("Password: ") { |q| q.echo = false }
# Ask if the user agrees (yes or no)
agree("Do something?")
# Asks on a single line (note the space after ':')
ask("Name: ")
# Asks with new line after "Description:"
ask("Description:")
# Calls Date#parse to parse the date string passed
ask("Birthday? ", Date)
# Ensures Integer is within the range specified
ask("Age? ", Integer) { |q| q.in = 0..105 }
# Asks for a list of strings, converts to array
ask("Fav colors?", Array)
```
## HighLine & Interaction Additions
In addition to highline's fantastic choice of methods, commander adds the
following methods to simplify common tasks:
```ruby
# Ask for password
password
# Ask for password with specific message and mask character
password "Enter your password please:", '-'
# Ask for CLASS, which may be any valid class responding to #parse. Date, Time, Array, etc
names = ask_for_array 'Names: '
bday = ask_for_date 'Birthday?: '
# Simple progress bar (Commander::UI::ProgressBar)
uris = %w[
http://vision-media.ca
http://google.com
http://yahoo.com
]
progress uris do |uri|
res = open uri
# Do something with response
end
# 'Log' action to stdout
log "create", "path/to/file.rb"
# Enable paging of output after this point
enable_paging
# Ask editor for input (EDITOR environment variable or whichever is available: TextMate, vim, vi, emacs, nano, pico)
ask_editor
# Ask editor, supplying initial text
ask_editor 'previous data to update'
# Ask editor, preferring a specific editor
ask_editor 'previous data', 'vim'
# Choose from an array of elements
choice = choose("Favorite language?", :ruby, :perl, :js)
# Alter IO for the duration of the block
io new_input, new_output do
new_input_contents = $stdin.read
puts new_input_contents # outputs to new_output stream
end
# $stdin / $stdout reset back to original streams
# Speech synthesis
speak 'What is your favorite food? '
food = ask 'favorite food?: '
speak "Wow, I like #{food} too. We have so much in common."
speak "I like #{food} as well!", "Victoria", 190
# Execute arbitrary applescript
applescript 'foo'
# Converse with speech recognition server
case converse 'What is the best food?', :cookies => 'Cookies', :unknown => 'Nothing'
when :cookies
speak 'o.m.g. you are awesome!'
else
case converse 'That is lame, shall I convince you cookies are the best?', :yes => 'Ok', :no => 'No', :maybe => 'Maybe another time'
when :yes
speak 'Well you see, cookies are just fantastic, they melt in your mouth.'
else
speak 'Ok then, bye.'
end
end
```
## Growl Notifications
Commander provides methods for displaying Growl notifications. To use these
methods you need to install https://github.com/tj/growl which utilizes
the [growlnotify](https://growl.info/extras.php#growlnotify) executable. Note that
growl is auto-imported by Commander when available, no need to require.
```ruby
# Display a generic Growl notification
notify 'Something happened'
# Display an 'info' status notification
notify_info 'You have #{emails.length} new email(s)'
# Display an 'ok' status notification
notify_ok 'Gems updated'
# Display a 'warning' status notification
notify_warning '1 gem failed installation'
# Display an 'error' status notification
notify_error "Gem #{name} failed"
```
## Commander Goodies
### Option Defaults
The options struct passed to `#action` provides a `#default` method, allowing you
to set defaults in a clean manner for options which have not been set.
```ruby
command :foo do |c|
c.option '--interval SECONDS', Integer, 'Interval in seconds'
c.option '--timeout SECONDS', Integer, 'Timeout in seconds'
c.action do |args, options|
options.default \
:interval => 2,
:timeout => 60
end
end
```
### Command Aliasing
Aliases can be created using the `#alias_command` method like below:
```ruby
command :'install gem' do |c|
c.action { puts 'foo' }
end
alias_command :'gem install', :'install gem'
```
Or more complicated aliases can be made, passing any arguments
as if it was invoked via the command line:
```ruby
command :'install gem' do |c|
c.syntax = 'install gem [options]'
c.option '--dest DIR', String, 'Destination directory'
c.action { |args, options| puts "installing #{args.first} to #{options.dest}" }
end
alias_command :update, :'install gem', 'rubygems', '--dest', 'some_path'
```
```
$ foo update
# => installing rubygems to some_path
```
### Command Defaults
Although working with a command executable framework provides many
benefits over a single command implementation, sometimes you still
want the ability to create a terse syntax for your command. With that
in mind we may use `#default_command` to help with this. Considering
our previous `:'install gem'` example:
```ruby
default_command :update
```
```
$ foo
# => installing rubygems to some_path
```
Keeping in mind that commander searches for the longest possible match
when considering a command, so if you were to pass arguments to foo
like below, expecting them to be passed to `:update`, this would be incorrect,
and would end up calling `:'install gem'`, so be careful that the users do
not need to use command names within the arguments.
```
$ foo install gem
# => installing to
```
### Long descriptions
If you need to have a long command description, keep your short description under `summary`, and consider multi-line strings for `description`:
```ruby
program :summary, 'Stupid command that prints foo or bar.'
program :description, %q(
#{c.summary}
More information about that stupid command that prints foo or bar.
And more
)
```
### Additional Global Help
Arbitrary help can be added using the following `#program` symbol:
```ruby
program :help, 'Author', 'TJ Holowaychuk '
```
Which will output the rest of the help doc, along with:
AUTHOR:
TJ Holowaychuk
### Global Options
Although most switches will be at the command level, several are available by
default at the global level, such as `--version`, and `--help`. Using
`#global_option` you can add additional global options:
```ruby
global_option('-c', '--config FILE', 'Load config data for your commands to use') { |file| ... }
```
This method accepts the same syntax as `Commander::Command#option` so check it out for documentation.
All global options regardless of providing a block are accessable at the command level. This
means that instead of the following:
```ruby
global_option('--verbose') { $verbose = true }
...
c.action do |args, options|
say 'foo' if $verbose
...
```
You may:
```ruby
global_option '--verbose'
...
c.action do |args, options|
say 'foo' if options.verbose
...
```
### Formatters
Two core formatters are currently available, the default `Terminal` formatter
as well as `TerminalCompact`. To utilize a different formatter simply use
`:help_formatter` like below:
```ruby
program :help_formatter, Commander::HelpFormatter::TerminalCompact
```
Or utilize the help formatter aliases:
```ruby
program :help_formatter, :compact
```
This abstraction could be utilized to generate HTML documentation for your executable.
### Tracing
By default the `-t` and `--trace` global options are provided to allow users to get a backtrace to aid debugging.
You can disable these options:
```ruby
never_trace!
```
Or make it always on:
```ruby
always_trace!
```
## Tips
When adding a global or command option, OptionParser implicitly adds a small
switch even when not explicitly created, for example `-c` will be the same as
`--config` in both examples, however `-c` will only appear in the documentation
when explicitly assigning it.
```ruby
global_option '-c', '--config FILE'
global_option '--config FILE'
```
## ASCII Tables
For feature rich ASCII tables for your terminal app check out the terminal-table gem at https://github.com/tj/terminal-table
+----------+-------+----+--------+-----------------------+
| Terminal | Table | Is | Wicked | Awesome |
+----------+-------+----+--------+-----------------------+
| | | | | get it while its hot! |
+----------+-------+----+--------+-----------------------+
## Running Specifications
$ rake spec
OR
$ spec --color spec
## Contrib
Feel free to fork and request a pull, or submit a ticket
https://github.com/commander-rb/commander/issues
## License
This project is available under the MIT license. See LICENSE for details.
commander-4.6.0/bin/ 0000755 0000041 0000041 00000000000 14053714220 014264 5 ustar www-data www-data commander-4.6.0/bin/commander 0000755 0000041 0000041 00000006537 14053714220 016172 0 ustar www-data www-data #!/usr/bin/env ruby
# frozen_string_literal: true
require 'rubygems'
require 'commander/import'
program :name, 'commander'
program :version, Commander::VERSION
program :description, 'Commander utility program.'
command :init do |c|
c.syntax = 'commander init [option] '
c.summary = 'Initialize a commander template'
c.description = 'Initialize an empty with a commander template,
allowing very quick creation of commander executables.'
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
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}/, '')
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
end
File.chmod 0755, file
say "Initialized template in #{file}"
end
rescue StandardError => e
abort e
end
end
end
commander-4.6.0/spec/ 0000755 0000041 0000041 00000000000 14053714220 014446 5 ustar www-data www-data commander-4.6.0/spec/core_ext/ 0000755 0000041 0000041 00000000000 14053714220 016256 5 ustar www-data www-data commander-4.6.0/spec/core_ext/array_spec.rb 0000644 0000041 0000041 00000001004 14053714220 020726 0 ustar www-data www-data # frozen_string_literal: true
require 'spec_helper'
describe Array do
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
expect(Array.parse('just a\ test')).to eq(['just', 'a test'])
end
it 'should match %w behavior with multiple backslashes' do
str = 'just a\\ test'
expect(Array.parse(str)).to eq(['just', 'a test'])
end
end
end
commander-4.6.0/spec/core_ext/object_spec.rb 0000644 0000041 0000041 00000001066 14053714220 021066 0 ustar www-data www-data # frozen_string_literal: true
require 'spec_helper'
describe Object do
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
expect { send(:i_am_a_missing_method) }.to raise_error(NoMethodError)
end
it 'should preserve its original behavior for missing variables' do
expect { i_am_a_missing_variable }.to raise_error(NameError)
end
end
end
commander-4.6.0/spec/methods_spec.rb 0000644 0000041 0000041 00000003111 14053714220 017444 0 ustar www-data www-data # frozen_string_literal: true
require 'spec_helper'
require 'commander/methods'
describe Commander::Methods do
it 'includes Commander::UI' do
expect(subject.ancestors).to include(Commander::UI)
end
describe 'AskForClass' do
it 'includes Commander::UI::AskForClass' do
expect(subject.ancestors).to include(Commander::UI::AskForClass)
end
describe 'defining methods' do
let(:terminal) { double }
before do
allow(terminal).to receive(:ask)
@old_highline = HighLine.default_instance
HighLine.default_instance = terminal
end
after do
HighLine.default_instance = @old_highline
end
subject do
Class.new do
include Commander::UI::AskForClass
end.new
end
it 'defines common "ask_for_*" methods' do
expect(subject.respond_to?(:ask_for_float)).to be_truthy
end
it 'responds to "ask_for_*" methods for classes that implement #parse' do
expect(subject.respond_to?(:ask_for_datetime)).to be_truthy
end
it 'fails "ask_for_*" method invocations without a prompt' do
expect do
subject.ask_for_datetime
end.to raise_error(ArgumentError)
end
it 'implements "ask_for_*"' do
expect(terminal).to receive(:ask)
subject.ask_for_datetime('hi')
end
end
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
commander-4.6.0/spec/runner_spec.rb 0000644 0000041 0000041 00000061712 14053714220 017325 0 ustar www-data www-data # frozen_string_literal: true
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
program :name, 'test'
expect(program(:name)).to eq('test')
end
it 'should allow arbitrary blocks of global help documentation' do
program :help, 'Copyright', 'TJ Holowaychuk'
expect(program(:help)['Copyright']).to eq('TJ Holowaychuk')
end
it 'should raise an error when required info has not been set' do
new_command_runner '--help'
program :version, ''
expect { run! }.to raise_error(Commander::Runner::CommandError)
end
it 'should allow aliases of help formatters' do
program :help_formatter, :compact
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
expect(command(:test)).to be_instance_of(Commander::Command)
end
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
switches, description = *Commander::Runner.separate_switches_from_description('-h', '--help', '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
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
alias_command :foo, :test
expect(command(:foo)).to eq(command(:test))
end
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
alias_command :'install gem', :install, '--gem-name'
end.run!
expect(gem_name).to eq('commander')
end
end
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!
expect(file).to eq('foo')
end
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 }
end
end.run!
expect(quiet).to be true
end
it 'should be inherited by commands when provided before the command name' do
option = nil
new_command_runner '--global-option', 'option-value', 'command_name' do
global_option('--global-option=GLOBAL', 'A global option')
command :command_name do |c|
c.when_called { |_, options| option = options.global_option }
end
end.run!
expect(option).to eq('option-value')
end
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 }
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!
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
it 'should allow command arguments before the global option' do
config = nil
args = nil
new_command_runner 'foo', '--config', 'config-value', 'arg1', 'arg2' do
global_option('-c', '--config CONFIG', String)
command :foo do |c|
c.when_called do |arguments, options|
options.default(config: 'default')
args = arguments
config = options.config
end
end
end.run!
expect(config).to eq('config-value')
expect(args).to eq(%w(arg1 arg2))
end
it 'should allow command arguments after the global option' do
config = nil
args = nil
new_command_runner 'foo', 'arg1', 'arg2', '--config', 'config-value' do
global_option('-c', '--config CONFIG', String)
command :foo do |c|
c.when_called do |arguments, options|
options.default(config: 'default')
args = arguments
config = options.config
end
end
end.run!
expect(config).to eq('config-value')
expect(args).to eq(%w(arg1 arg2))
end
it 'allows global options in the form option=value' do
config = nil
args = nil
new_command_runner 'test', 'arg1', '--config=config-value', 'arg2' do
global_option('-c', '--config CONFIG', String)
command :test do |c|
c.when_called do |arguments, options|
options.default(config: 'default')
args = arguments
config = options.config
end
end
end.run!
expect(config).to eq('config-value')
expect(args).to eq(%w[arg1 arg2])
end
end
describe '#parse_global_options' do
it 'should parse global options before command' do
global_option = nil
new_command_runner('--testing-global', 'foo') do
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.when_called {}
end
end.run!
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
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.when_called {}
end
end.run!
expect(global_option).to eq('MAGIC')
end
it 'should parse global options placed before command options' do
global_option = nil
new_command_runner('foo', '--testing-global', '--testing-command') do
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.option('--testing-command') {}
c.when_called {}
end
end.run!
expect(global_option).to eq('MAGIC')
end
it 'should parse global options placed after command options' do
global_option = nil
new_command_runner('foo', '--testing-command', '--testing-global') do
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.option('--testing-command') {}
c.when_called {}
end
end.run!
expect(global_option).to eq('MAGIC')
end
it 'should parse global options surrounded by command options' do
global_option = nil
new_command_runner('foo', '--testing-command', '--testing-global', '--other-command') do
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.option('--testing-command') {}
c.option('--other-command') {}
c.when_called {}
end
end.run!
expect(global_option).to eq('MAGIC')
end
it 'should not parse command options' do
global_option = nil
command_option = nil
new_command_runner('foo', '--testing-command', '--testing-global') do
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.option('--testing-command') { command_option = 'NO!' }
c.when_called {}
end
end.parse_global_options
expect(command_option).to be_nil
expect(global_option).to eq('MAGIC')
end
it 'should not affect command arguments with values' do
global_option = nil
command_option = nil
new_command_runner('foo', '--testing-command', 'bar', '--testing-global') do
global_option('--testing-global') { global_option = 'MAGIC' }
command :foo do |c|
c.option('--testing-command VALUE') { |v| command_option = v }
c.when_called {}
end
end.run!
expect(command_option).to eq('bar')
expect(global_option).to eq('MAGIC')
end
it 'should not affect global arguments with values' do
global_option = nil
new_command_runner('foo', '--testing-command', '--testing-global', 'bar') do
global_option('--testing-global VALUE') { |v| global_option = v }
command :foo do |c|
c.option('--testing-command') {}
c.when_called {}
end
end.run!
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
new_command_runner('foo', '--config', 'path', 'bar') do
global_option('--config VALUE') { |v| global_option = v }
command :foo do |c|
c.option('bar') { command_option = 'bar' }
c.when_called {}
end
end.run!
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
options, args = [], []
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
expect(args).to eq(['--command', '--command-with-arg', 'rawr'])
end
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'] }
args << '-n' << '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 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
it 'should remove specified switches value provided via equals' do
options = [{ switches: ['--global GLOBAL'] }]
args = ['--command', '--global=option-value', 'arg']
command_runner.remove_global_options options, args
expect(args).to eq(['--command', 'arg'])
end
it 'should not remove extra values after switches' do
options = [{ switches: ['--global GLOBAL'] }]
args = ['--global', '--command', 'arg']
command_runner.remove_global_options options, args
expect(args).to eq(['--command', 'arg'])
end
end
describe '--trace' do
it 'should display pretty errors by default' do
expect do
new_command_runner 'foo' do
command(:foo) { |c| c.when_called { fail 'cookies!' } }
end.run!
end.to raise_error(TestSystemExit, /error: cookies!. Use --trace/)
end
it 'should display callstack when using this switch' do
expect do
new_command_runner 'foo', '--trace' do
command(:foo) { |c| c.when_called { fail 'cookies!' } }
end.run!
end.to raise_error(RuntimeError)
end
end
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 '#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(TestSystemExit, /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 TestSystemExit => e
msg = e.message
end
expect(msg).to match(/error: cookies!/)
expect(msg).not_to match(/--trace/)
end
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 '--version' do
it 'should output program version' do
expect(run('--version')).to eq("test 1.2.3\n")
end
end
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
it 'can be used after the command and command arguments' do
expect(run('test', 'command-arg', '--help')).to eq("Implement help for test here\n")
end
it 'can be used before a single-word command with command arguments' do
expect(run('help', 'test', 'command-arg')).to eq("Implement help for test here\n")
end
it 'can be used before a multi-word command with command arguments' do
expect(
run('help', 'module', 'install', 'command-arg') do
command('module install') { |c| c.when_called { say 'whee!' } }
end
).to eq("Implement help for module install here\n")
end
describe 'help_paging program information' do
it 'enables paging when enabled' do
run('--help') { program :help_paging, true }
expect(Commander::UI).to have_received(:enable_paging)
end
it 'is enabled by default' do
run('--help')
expect(Commander::UI).to have_received(:enable_paging)
end
it 'does not enable paging when disabled' do
run('--help') { program :help_paging, false }
expect(Commander::UI).not_to have_received(:enable_paging)
end
end
end
describe 'with invalid options' do
it 'should output an invalid option message' do
expect do
run('test', '--invalid-option')
end.to raise_error(TestSystemExit, /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(TestSystemExit, /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')
end.to raise_error(TestSystemExit, /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')
end.to raise_error(TestSystemExit, /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
expect do
run('--help', 'test', '--invalid-option')
end.to raise_error(TestSystemExit, /invalid option: --invalid-option/)
end
end
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') {}
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
new_command_runner do
expect(command_runner.valid_command_names_from('fake', 'command', 'name')).to eq([])
end
end
it 'should match exact commands only' do
new_command_runner do
command('foo') {}
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
new_command_runner '--help', '--arbitrary', 'test'
expect(command_runner.command_name_from_args).to eq('test')
end
it 'should locate command when provided after a global argument with value' do
new_command_runner '--global-option', 'option-value', 'test' do
global_option('--global-option=GLOBAL', 'A global option')
end
expect(command_runner.command_name_from_args).to eq('test')
end
it 'should support multi-word commands' do
new_command_runner '--help', '--arbitrary', 'some', 'long', 'command', 'foo'
command('some long command') {}
expect(command_runner.command_name_from_args).to eq('some long command')
end
it 'should match the longest possible command' do
new_command_runner '--help', '--arbitrary', 'foo', 'bar', 'foo'
command('foo bar') {}
command('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
new_command_runner 'help', 'test'
expect(command_runner.command_name_from_args).to eq('help')
end
end
describe '#active_command' do
it 'should resolve the active command' do
new_command_runner '--help', 'test'
expect(command_runner.active_command).to be_instance_of(Commander::Command)
end
it 'should resolve active command when invalid options are passed' do
new_command_runner '--help', 'test', '--arbitrary'
expect(command_runner.active_command).to be_instance_of(Commander::Command)
end
it 'should return nil when the command is not found' do
new_command_runner 'foo'
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
new_command_runner '--trace' do
default_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
new_command_runner 'foo', 'bar', '--trace' do
default_command :test
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
new_command_runner 'foo', 'bar', 'something'
default_command :'foo bar'
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
new_command_runner '--trace' do
default_command :foobar
alias_command :foobar, :test
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
new_command_runner '--verbose', 'test', 'foo', 'bar' do
@command.when_called do |args, options|
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
new_command_runner 'test', '--verbose', 'foo', 'bar' do
@command.when_called do |args, options|
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
new_command_runner 'test', '--verbose', 'foo', 'test', 'bar' do
@command.when_called do |args, options|
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
new_command_runner '--verbose', 'my', 'command', 'something', 'foo', 'bar' do
command('my command') { |c| c.option('--verbose') }
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
new_command_runner '--verbose', 'my', 'command', 'something', 'my', 'command' do
command('my command') { |c| c.option('--verbose') }
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
new_command_runner '--verbose', 'my', 'command', 'something', 'my', 'command' do
command('my command') {}
command('my command something') { |c| c.option('--verbose') }
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
new_command_runner 'foo', '--optional', 'arg1' do
command('foo') do |c|
c.option('--optional [argument]')
c.when_called do |_, options|
expect(options.optional).to eq('arg1')
end
end
end.run!
end
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|
expect(options.optional).to be true
end
end
end.run!
end
end
describe 'with double dash' do
it 'should interpret the remainder as arguments' do
new_command_runner 'foo', '--', '-x' do
command('foo') do |c|
c.option '-x', 'Switch'
c.when_called do |args, options|
expect(args).to eq(%w(-x))
expect(options.x).to be_nil
end
end
end.run!
end
end
end
commander-4.6.0/spec/ui_spec.rb 0000644 0000041 0000041 00000001477 14053714220 016433 0 ustar www-data www-data # frozen_string_literal: true
require 'spec_helper'
describe Commander::UI do
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', 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
exception = false
begin
progress([]) {}
rescue StandardError
exception = true
end
expect(exception).not_to be true
end
end
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
commander-4.6.0/spec/command_spec.rb 0000644 0000041 0000041 00000014474 14053714220 017435 0 ustar www-data www-data # frozen_string_literal: true
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
end
it 'should act like an open struct' do
@options.send = 'mail'
@options.call = true
expect(@options.send).to eq('mail')
expect(@options.call).to eq(true)
end
it 'should allow __send__ to function as always' do
@options.send = 'foo'
expect(@options.__send__(:send)).to eq('foo')
end
end
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| expect(recursive).to be true }
@command.run '--recursive'
end
it 'should allow usage of common method names' do
@command.option '--open file'
@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| 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 = double 'Object'
expect(object).to receive(:call).once
@command.when_called object
@command.run 'foo'
end
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 = double 'Object'
expect(object).to receive(:foo).once
@command.when_called object, :foo
@command.run 'foo'
end
it 'should raise an error when no handler is present' do
expect { @command.when_called }.to raise_error(ArgumentError)
end
it 'should be able to be run more than once' do
expect(@command.run('once')).to eql('test once')
expect(@command.run('twice')).to eql('test twice')
end
it 'should not accumulate entries in @proxy_options when run twice' do
expect(@command.run('--verbose')).to eql('test ')
expect(@command.proxy_options).to eq([[:verbose, true]])
expect(@command.run('foo')).to eql('test foo')
expect(@command.proxy_options).to eq([])
end
end
describe 'should populate options with' do
it 'boolean values' do
@command.option '--[no-]toggle'
@command.when_called { |_, options| expect(options.toggle).to be true }
@command.run '--toggle'
@command.when_called { |_, options| expect(options.toggle).to be false }
@command.run '--no-toggle'
end
it 'mandatory arguments' do
@command.option '--file FILE'
@command.when_called { |_, options| expect(options.file).to eq('foo') }
@command.run '--file', 'foo'
expect { @command.run '--file' }.to raise_error(OptionParser::MissingArgument)
end
describe 'optional arguments' do
before do
@command.option '--use-config [file] '
end
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| expect(options.use_config).to be true }
@command.run '--use-config'
end
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
before do
@command.option '--interval N', Integer
end
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
expect { @command.run '--interval', 'invalid' }.to raise_error(OptionParser::InvalidArgument)
end
end
it 'lists' do
@command.option '--fav COLORS', Array
@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
@command.option '--fav MOVIES', Array
@command.when_called { |_, options| expect(options.fav).to eq(['super\ bad', 'nightmare']) }
@command.run '--fav', 'super\ bad,nightmare'
end
it 'defaults' do
@command.option '--files LIST', Array
@command.option '--interval N', Integer
@command.when_called do |_, options|
options.default \
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
describe 'given a global option' do
before do
@command.global_options << [:global_option, 'gvalue']
end
describe 'and no command specific arguments' do
it 'provides the global option to the command action' do
@command.when_called { |_, options| expect(options.global_option).to eq('gvalue') }
@command.run
end
end
describe 'and a command specific option' do
it 'provides the global option to the command action' do
@command.when_called { |_, options| expect(options.global_option).to eq('gvalue') }
@command.run '--verbose'
end
end
describe 'and a command specific argument' do
it 'provides the global option to the command action' do
@command.when_called { |_, options| expect(options.global_option).to eq('gvalue') }
@command.run 'argument'
end
end
end
end
end
end
commander-4.6.0/spec/spec_helper.rb 0000644 0000041 0000041 00000003774 14053714220 017277 0 ustar www-data www-data # frozen_string_literal: true
require 'rubygems'
require 'stringio'
require 'simplecov'
SimpleCov.start do
add_filter '/spec/'
end
# Unshift so that local files load instead of something in gems
$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/methods'
# Mock terminal IO streams so we can spec against them
def mock_terminal
@input = StringIO.new
@output = StringIO.new
HighLine.default_instance = HighLine.new(@input, @output)
end
# Stub Kernel.abort
TestSystemExit = Class.new(RuntimeError)
module Commander
class Runner
def abort(message)
fail TestSystemExit, message
end
end
end
# Create test command for usage within several specs
def create_test_command
command :test do |c|
c.syntax = 'test [options] '
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
end
# Create a new command runner
def new_command_runner(*args, &block)
Commander::Runner.instance_variable_set :@instance, Commander::Runner.new(args)
program :name, 'test'
program :version, '1.2.3'
program :description, 'something'
create_test_command
yield if block
Commander::Runner.instance
end
# Comply with how specs were previously written
def command_runner
Commander::Runner.instance
end
def run(*args)
new_command_runner(*args) do
program :help_formatter, Commander::HelpFormatter::Base
yield if block_given?
end.run!
@output.string
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
commander-4.6.0/spec/configure_spec.rb 0000644 0000041 0000041 00000001771 14053714220 017774 0 ustar www-data www-data # frozen_string_literal: true
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
commander-4.6.0/spec/help_formatters/ 0000755 0000041 0000041 00000000000 14053714220 017644 5 ustar www-data www-data commander-4.6.0/spec/help_formatters/terminal_compact_spec.rb 0000644 0000041 0000041 00000003447 14053714220 024534 0 ustar www-data www-data # frozen_string_literal: true
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
commander-4.6.0/spec/help_formatters/terminal_spec.rb 0000644 0000041 0000041 00000003314 14053714220 023017 0 ustar www-data www-data # frozen_string_literal: true
require 'spec_helper'
describe Commander::HelpFormatter::Terminal do
include Commander::Methods
before :each do
mock_terminal
end
describe 'global help' do
before :each do
new_command_runner 'help' do
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
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
commander-4.6.0/History.rdoc 0000644 0000041 0000041 00000033640 14053714220 016034 0 ustar www-data www-data === 4.6.0 / 2021-04-09
* Fix error with SortedSet on Ruby 3.0 (#98).
* Remove `#reset_io` as it didn't do anything.
* Drop support for Ruby < 2.4.
=== 4.5.2 / 2020-03-12
* Fix bug handling global options provided in option=value form (#47). (@orien)
* Fix ERB warnings under Ruby 2.7. (@esotericpig)
* Fix bug handling global options placed before command name (#32). (@orien)
=== 4.5.1 / 2020-03-08
* Fix bug causing global options to be ignored when arguments are present (#86). (@orien)
=== 4.5.0 / 2020-01-21
* Drop support for Ruby < 2.3.
* Fix bug parsing double dash (#75).
=== 4.4.7 / 2018-10-22
* Update HighLine dependency to 2.0.0. (@rohitpaulk)
=== 4.4.6 / 2018-07-31
* Fix unexpected internal behavior change introduced in 4.4.5.
=== 4.4.5 / 2018-05-22
* Make internal command state less mutable. (@doriantaylor)
=== 4.4.4 / 2018-01-18
* Fix deprecated constant warnings on Ruby 2.5. (@mattbrictson)
=== 4.4.3 / 2016-12-28
* Fix deprecated constant warnings on Ruby 2.4.
=== 4.4.2 / 2016-12-20
* Add `help_paging` program flag so that help paging may be disabled. (@gogiel)
=== 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)
=== 4.1.4 / 2013-07-21
* Improve help formatting for multiline program and command descriptions
* Add ability to set speaking rate (@kethomassen)
* Clean up examples in docs (@parkr)
=== 4.1.3 / 2012-12-15
* Remove use of eval in Array.parse
* Make generated template executable and set better defaults (@suan)
* Fixed valid_command_names_from to match exact commands only (@fgalassi)
=== 4.1.2 / 2012-02-17
* Improvement to `ask_editor` to be more portable across *nix variants. (thanks to Federico Galassi)
=== 4.1.1 / 2012-02-16
* Update `ask_editor` to work with any *nix editor - emacs, vim, etc. (thanks to Federico Galassi)
=== 4.1.0 / 2012-02-12
* Update highline dependency.
* Make optional arguments true when present (issue #2).
=== 4.0.7 / 2012-01-23
* Improved support for JRuby and Windows (and any other platforms that don't support Kernel.fork).
* Fixed bug #33 - support `--help` after commands.
* Reorganized help output to display synopsis before description (issue #12).
=== 4.0.6 / 2011-09-15
* Improved load time on Ruby 1.9. (thanks to Jonathon M. Abbott)
* Updated documentation.
=== 4.0.5 / 2011-08-09
* Updated documentation to fix inaccuracies and unclear information.
* Improved rake tasks for gem development.
* Added say_ok, say_warning and say_error methods to print messages in green, yellow or red. (thanks to Simon Courtois)
* Fixed; Allow global options to be passed in any order, even mixed with command options. (thanks to Rich Grundy)
* Fixed; Global options can be passed before or after the command, they can even be mixed with command options. Closes #8. (thanks to Rich Grundy)
* Fixed; Platform test should now correctly identify JRuby. (thanks to Justin Lynn)
* Fixed; Add to_s to exceptions as option parser no longer does implicit conversion. (thanks to Justin Lynn)
=== 4.0.4 / 2011-04-04
* Fixed program(:key) behavior for non-Array keys like name, version, description under Ruby 1.9
* All specs should pass under Ruby 1.9 now
=== 4.0.3 / 2010-04-06
* Fixed global_option which was consuming arguments when not expected. Closes #22
=== 4.0.2 / 2010-01-19
* Added program(:int_block) to allow a block to be run on interrupt.
* Fixed; ProgressBar immediately shows, and doesn't die on empty lists.
=== 4.0.1 / 2010-01-14
* Fixed commander when using JRuby
* Fixed template; should require "commander/import"
=== 4.0.0 / 2009-10-10
* Changed; Aliased #when_called as #action [#9]
* Changed; Sort commands and aliases alphabetically.
* Changed; Sort aliases alphabetically
* Changed; Sort commands alphabetically.
* Changed; require user to require 'commander/import' for dsl
* Fixed broken regexp; Changed :int_message, only traps INT when available
* Fixed Ruby 1.9 warning caused by removing object_id from Object
* Removed #eval const hack
* Moving to Gemcutter (GRRRR Github)
=== 3.3.0 / 2009-05-12
* Added #choose
* Added aliasing for help formatters [#24]
* Added UI.replace_tokens
* Added #converse
* Added #speak
* Added #applescript
* Added #reset_io
* Added #io
* Removed String#tokenize
* Removed #delete_switches
=== 3.2.9 / 2009-04-09
* Fixed bug in removal of global options
=== 3.2.8 / 2009-04-09
* Added auto-loading support of visionmedia-growl convenience methods when the gem is available
* Changed; growl related methods are now part of visionmedia-growl
* Fixed doc typos
=== 3.2.7 / 2009-04-08
* Added #notify, #notify_ok, #notify_warning, #notify_info and #notify_error
These methods all utilize the MacOS growlnotify binary, very cool stuff check it out!
=== 3.2.6 / 2009-04-08
* Added Commander::UI::AskForClass
* Added support to #remove_global_options for options with arguments
* Removed .re directory used for visionmedia-release
* Fixed bug preventing --trace from working
=== 3.2.5 / 2009-04-02
* Added #ask_editor
=== 3.2.4 / 2009-04-02
* Added #enable_paging [#9]
=== 3.2.3 / 2009-04-01
* Added new pager using less [#9]
=== 3.2.2 / 2009-04-01
* Github's gem builder timed out ? ...
=== 3.2.1 / 2009-04-01
* Added Commander::HelpFormatter::TerminalCompact
* Fix; updated gemspec / manifest removing test/* causing issue [#26]
=== 3.2.0 / 2009-03-26
* Added implied small switches so they appear in help (-h, -v, etc)
* Added #inspect back to Commander::Command::Options [#1]
* Added inheritance of global options for commands [#7]
* Added #require_valid_command
* Renamed #call_active_command to #run_active_command
* Changed; using same option format as command options for globals [#18]
* Changed; program :name is now optional, and is auto-defined when not specified [#21]
* Moved #switch_to_sym from Command to Commander::Runner
* Moved #separate_switches_from_description into Commander::Runner [#22]
* Removed program :name from commander init template since its not required anymore
=== 3.1.8 / 2009-03-25
* Utilizing abort and $stderr instead of using #say [#16]
* Fixed INT trapping issue (purely cosmetic) [#14]
* Removed todo, use lighthouse now for commander at:
http://visionmedia.lighthouseapp.com/projects/27643-commander/overview
=== 3.1.7 / 2009-03-24
* Added global --trace option
=== 3.1.6 / 2009-03-22
* Changed Options struct to always use symbols
=== 3.1.5 / 2009-03-22
* Added Options#__hash__ to access the internal hash table
* Refactored Options struct to function much like an OpenStruct
* Updated commander exec init help description
=== 3.1.4 / 2009-03-20
* Gemspec typo
=== 3.1.3 / 2009-03-20
* Added #remove_global_options
* Added core global option descriptions
* Added display of global options
* Removed small core switches (-v, -h) because they are implicitly set
* Fixed issue with option switchs failing when named as common methods like --send, or --password
* Fixed bug causing InvalidOption error when global options do not abort the process.
This was due to these options remaining in the arguments array, in turn being parsed
by the command's option parser, issuing the error. This is fixed by #remove_global_options.
=== 3.1.2 / 2009-03-16
* Added support for global options via #global_option
* Added #call_active_command and #say to clean things up internally
* Misc refactoring
=== 3.1.1 / 2009-03-13
* Fixed some terminal formatter spacing issues
=== 3.1.0 / 2009-03-13
* Added Command#inspect
* Added displaying of aliases in global help
* Added support for alias args
* Added #default_command
=== 3.0.3 / 2009-03-12
* Added #alias_command
=== 3.0.2 / 2009-03-12
* Added terminal formatter specs
* Fixed bug preventing command names passed to help from working
=== 3.0.1 / 2009-03-12
* Fixed bug in #command_name_from_args preventing the left-most match for a command name to be used
* Fixed bug in Command#example preventing the formatter from outputting them correctly
=== 3.0.0 / 2009-03-12
* Added sub command help support when using the --help switch
* #delete_switches is now mutative
* Added #valid_command_names_from
* #when_called now raises argument error when neither a block, object, or class is passed
* Added options#default method and specs
* Added support for multi-word list parsing in Array#parse
* Added summary to commander template
* Added optional block param for #new_command_runner spec helper
* Added .re (metadata for visionmedia-release gem)
* Moved delgation of Kernel methods to Object
* Refactored multi-word command name specs
* Refactored Object#method_missing; using call chain to implement
* Refactored all specs
* Change #color calls in formatters to $terminal#color for now
* Using highlines $terminal.output for IO stream with the progressbar
* Replaced #ensure_program_key_set with #require_program, taking an array of keys
* Renamed #args_without_command to #args_without_command_name
* Renamed #populate_options_to_when_called to #option_proc
* Renamed #sym_from_switch to #switch_to_sym
* Removed #get_command, use #command without supplying a block
* Removed Command#inspect
* Removed command description aliases of short_description, long_description. Use description / summary
* Removed VerboseFileUtils
* Removed String#camelcase as its not really needed (was only used in commander's executable for creating templates)
* Removed commander/import for now
* Removed LOG_FORMAT
* Removed Kernel ext which only had #color
=== 2.5.7 / 2009-03-11
* Fixed paren warnings in import spec
* Fixed Kernel#method_missing to preserve its original behavior (Raise errors for missing methods or variables)
=== 2.5.6 / 2009-03-06
* Replaced Commander::VERSION::STRING with Commander::VERSION (for release gem)
* Refactored progress bar
* Fixed String#tokenize
=== 2.4.5 / 2009-03-03
* Fixed bug which was not allowing switch arguments which are strings
such as --eval 'something here'
=== 2.4.4 / 2009-01-15
* Fixed bug which was not allowing multi-word commands to view help
=== 2.4.3 / 2009-01-15
* Fixed bug in command_name_from_args, preventing multi-word commands
=== 2.4.2 / 2009-01-12
* Github! build me!
=== 2.4.1 / 2009-01-11
* Added ask_for_CLASS, which may be any class name such as ask_for_date, ask_for_array, etc
* Changed doc to *.rdoc for pretty markup on github
=== 2.3.0 / 2008-12-16
* Removed input, output in favour of HighLines $terminal
* Autoloading terminal formatter since it may not always be used
* Added wrapping of text with 10 padding, defaults to 80
* Added friendly interruption message by default, overridable with trap or int_message
* Fixed description now showing as summary when no summary is available
=== 2.2.1 / 2008-12-09
* Fixed typo in String#tokenize, preventing progress bar from working
* Fixed some small formatting issues with help output
=== 2.2.0 / 2008-12-09
* Additional documentation
* Added support for arbitrary help 'blocks' using program :help, 'Your block', 'Your blocks contents'
* Added support for description, summary, short_description, and large_description, which are displaying conditionally within help docs
* Allowing uncaught exceptions to reach stderr, for debugging purposes
=== 2.1.1 / 2008-12-01
* Changed #password, now requires that the user must enter a non-empty? value
=== 2.1.0 / 2008-12-01
* Added progress bar
* Added auto-inclusion of FileUtils module
* Added stdout logging method
* Fixed issue with options placed before command
=== 2.0.1 / 2008-11-24
* Fixed new line after command options
* Fixed padding for command list
=== 2.0.0 / 2008-11-24
* Rewrite of entire gem
* Added auto-parsing and struct population of options
* Added better documentation
=== 1.2.2 / 2008-11-06
* Forgot to add array.rb
=== 1.2.0 / 2008-11-06
* Added paging ability (similar to 'less')
* Added coloring to default help generator
=== 1.1.0 / 2008-11-06
* Added dependency for Highline gem, which replaces Commander's user interaction lib
=== 1.0.4 / 2008-11-04
* Added support for --help and --version flags
=== 1.0.3 / 2008-11-01
* Typo causing the gem to fail build on github
=== 1.0.2 / 2008-11-01
* Added gemspec for github
=== 1.0.1 / 2008-10-31
* Added shebang line to commander init
* Added require 'rubygems'
=== 1.0.0 / 2008-10-31
* Initial release
commander-4.6.0/.rubocop.yml 0000644 0000041 0000041 00000002262 14053714220 015770 0 ustar www-data www-data inherit_from: .rubocop_todo.yml
AllCops:
TargetRubyVersion: 2.4
NewCops: enable
SuggestExtensions: false
# not Ruby 1.9.3 compatible
Style/PercentLiteralDelimiters:
Enabled: false
# Enforce trailing comma after last item of multiline arrays.
Style/TrailingCommaInArrayLiteral:
EnforcedStyleForMultiline: comma
# Enforce trailing comma after last item of multiline hashes.
Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: comma
Metrics/BlockLength:
Enabled: false
Style/SignalException:
EnforcedStyle: only_fail
Style/ParallelAssignment:
Enabled: false
Style/NumericLiteralPrefix:
EnforcedOctalStyle: zero_only
Style/MissingRespondToMissing:
Enabled: false
Layout/SpaceInsideStringInterpolation:
Enabled: false
Layout/MultilineOperationIndentation:
Enabled: false
Style/EmptyMethod:
EnforcedStyle: expanded
Metrics/ModuleLength:
CountComments: false # count full line comments?
Max: 150
Lint/EmptyBlock:
Enabled: false
Style/FormatStringToken:
Enabled: false
Style/MixinUsage:
Enabled: false
Lint/ErbNewArguments:
Enabled: false
Style/DocumentDynamicEvalDefinition:
Enabled: false
Naming/HeredocDelimiterNaming:
Enabled: false
commander-4.6.0/.gitignore 0000644 0000041 0000041 00000000101 14053714220 015474 0 ustar www-data www-data *.gem
.bundle
Gemfile.lock
pkg/*
.rvmrc
.ruby-version
coverage/*
commander-4.6.0/LICENSE 0000644 0000041 0000041 00000002123 14053714220 014517 0 ustar www-data www-data The MIT License (MIT)
Copyright (c) 2008-2013 TJ Holowaychuk
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.
commander-4.6.0/commander.gemspec 0000644 0000041 0000041 00000003012 14053714220 017022 0 ustar www-data www-data # frozen_string_literal: true
$LOAD_PATH.push File.expand_path('lib', __dir__)
require 'commander/version'
Gem::Specification.new do |s|
s.name = 'commander'
s.version = Commander::VERSION
s.authors = ['TJ Holowaychuk', 'Gabriel Gilder']
s.email = ['gabriel@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.metadata = {
'bug_tracker_uri' => "#{s.homepage}/issues",
'changelog_uri' => "#{s.homepage}/blob/master/History.rdoc",
'documentation_uri' => "https://www.rubydoc.info/gems/commander/#{s.version}",
'homepage_uri' => s.homepage,
'source_code_uri' => "#{s.homepage}/tree/v#{s.version}",
}
s.required_ruby_version = '>= 2.4'
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.add_runtime_dependency('highline', '~> 2.0.0')
s.add_development_dependency('rake')
s.add_development_dependency('rspec', '~> 3.2')
s.add_development_dependency('rubocop', '~> 1.12.1')
s.add_development_dependency('simplecov')
end
commander-4.6.0/.rubocop_todo.yml 0000644 0000041 0000041 00000003204 14053714220 017012 0 ustar www-data www-data # 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
Security/Eval:
Enabled: false
# Offense count: 2
Lint/SuppressedException:
Enabled: false
# Offense count: 5
Metrics/AbcSize:
Max: 30
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ClassLength:
Enabled: false
# Offense count: 4
Metrics/CyclomaticComplexity:
Max: 13
# Offense count: 89
# Configuration parameters: AllowURI, URISchemes.
Layout/LineLength:
Max: 242
# Offense count: 7
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 36
# Offense count: 4
Metrics/PerceivedComplexity:
Max: 14
# Offense count: 1
Naming/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
commander-4.6.0/DEVELOPMENT 0000644 0000041 0000041 00000000424 14053714220 015221 0 ustar www-data www-data To run the development rake tasks, you need bundler installed.
Before you push any changes, run the RSpec suite:
$ rake spec
To build a new version of the gem:
$ rake build
To push the new version to Rubygems:
$ rake release
(http://rubygems.org/gems/commander) commander-4.6.0/Manifest 0000644 0000041 0000041 00000002011 14053714220 015177 0 ustar www-data www-data DEVELOPMENT
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.opts
spec/spec_helper.rb
spec/ui_spec.rb
tasks/dev_setup.rake
tasks/docs.rake
tasks/gemspec.rake
commander-4.6.0/Rakefile 0000644 0000041 0000041 00000000442 14053714220 015161 0 ustar www-data www-data # frozen_string_literal: true
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
require 'rubocop/rake_task'
desc 'Run specs'
RSpec::Core::RakeTask.new do |t|
t.verbose = false
t.rspec_opts = '--color --order random'
end
RuboCop::RakeTask.new
task default: %i[spec rubocop]
commander-4.6.0/lib/ 0000755 0000041 0000041 00000000000 14053714220 014262 5 ustar www-data www-data commander-4.6.0/lib/commander/ 0000755 0000041 0000041 00000000000 14053714220 016227 5 ustar www-data www-data commander-4.6.0/lib/commander/core_ext/ 0000755 0000041 0000041 00000000000 14053714220 020037 5 ustar www-data www-data commander-4.6.0/lib/commander/core_ext/array.rb 0000644 0000041 0000041 00000001360 14053714220 021502 0 ustar www-data www-data # frozen_string_literal: true
class Array
##
# Split _string_ into an array. Used in
# conjunction with HighLine's #ask, or #ask_for_array
# methods, which must respond to #parse.
#
# This method allows escaping of whitespace. For example
# the arguments foo bar\ baz will become ['foo', 'bar baz']
#
# === Example
#
# # ask invokes Array#parse
# list = ask 'Favorite cookies:', Array
#
# # or use ask_for_CLASS
# list = ask_for_array 'Favorite cookies: '
#
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
commander-4.6.0/lib/commander/core_ext/object.rb 0000644 0000041 0000041 00000000172 14053714220 021632 0 ustar www-data www-data # frozen_string_literal: true
class Object
##
# Return the current binding.
def get_binding
binding
end
end
commander-4.6.0/lib/commander/runner.rb 0000644 0000041 0000041 00000031502 14053714220 020066 0 ustar www-data www-data # frozen_string_literal: true
require 'optparse'
module Commander
class Runner
#--
# Exceptions
#++
class CommandError < StandardError; end
class InvalidCommandError < CommandError; end
attr_reader :commands, :options, :help_formatter_aliases
##
# Initialize a new command runner. Optionally
# supplying _args_ for mocking, or arbitrary usage.
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
@instance ||= new
end
##
# Run command parsing and execution process.
def run!
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)
command(:help).run(*args)
return
end
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
if trace
run_active_command
else
begin
run_active_command
rescue InvalidCommandError => e
abort "#{e}. Use --help for more information"
rescue \
OptionParser::InvalidOption,
OptionParser::InvalidArgument,
OptionParser::MissingArgument => e
abort e.to_s
rescue StandardError => e
if @never_trace
abort "error: #{e}."
else
abort "error: #{e}. Use --trace to view backtrace"
end
end
end
end
##
# Return program version.
def 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
# program :description, 'Commander utility program.'
# program :help, 'Copyright', '2008 TJ Holowaychuk'
# program :help, 'Anything', 'You want'
# program :int_message 'Bye bye!'
# program :help_formatter, :compact
# program :help_formatter, Commander::HelpFormatter::TerminalCompact
#
# # Get data
# program :name # => 'Commander'
#
# === Keys
#
# :version (required) Program version triple, ex: '0.0.1'
# :description (required) Program description
# :name Program name, defaults to basename of executable
# :help_formatter Defaults to Commander::HelpFormatter::Terminal
# :help Allows addition of arbitrary global help blocks
# :help_paging Flag for toggling help paging
# :int_message Message to display when interrupted (CTRL + C)
#
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?
@program[key] = (@help_formatter_aliases[args.first] || args.first)
elsif block
@program[key] = block
else
unless args.empty?
@program[key] = args.count == 1 ? args[0] : args
end
@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)
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)
@options << {
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)
@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)
@default_command = name
end
##
# Add a command object to this runner.
def add_command(command)
@commands[command.name] = command
end
##
# Check if command _name_ is an alias.
def alias?(name)
@aliases.include? name.to_s
end
##
# Check if a command _name_ exists.
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.
# Returns the default command, if no valid commands found in the args.
def command_name_from_args
@command_name_from_args ||= (longest_valid_command_name_from(@args) || @default_command)
end
##
# Returns array of valid command names found within _args_.
def valid_command_names_from(*args)
remove_global_options options, args
arg_string = args.delete_if { |value| value =~ /^-/ }.join ' '
commands.keys.find_all { |name| name if arg_string =~ /^#{name}\b/ }
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) && !removed.include?(arg)
end
end
##
# Returns hash of help formatter alias defaults.
def help_formatter_alias_defaults
{
compact: HelpFormatter::TerminalCompact,
}
end
##
# Returns hash of program defaults.
def program_defaults
{
help_formatter: HelpFormatter::Terminal,
name: File.basename($PROGRAM_NAME),
help_paging: true,
}
end
##
# 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.example 'Display global help', 'command help'
c.example "Display help for 'foo'", 'command help foo'
c.when_called do |args, _options|
UI.enable_paging if program(:help_paging)
if args.empty?
say help_formatter.render
else
command = command(longest_valid_command_name_from(args))
begin
require_valid_command command
rescue InvalidCommandError => e
abort "#{e}. Use --help for more information"
end
say help_formatter.render_command(command)
end
end
end
end
##
# Raises InvalidCommandError when a _command_ is not found.
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)
options.each do |option|
switches = option[:switches]
next if switches.empty?
option_takes_argument = switches.any? { |s| s =~ /[ =]/ }
switches = expand_optionally_negative_switches(switches)
option_argument_needs_removal = false
args.delete_if do |token|
break if token == '--'
# Use just the portion of the token before the = when
# comparing switches.
index_of_equals = token.index('=') if option_takes_argument
token = token[0, index_of_equals] if index_of_equals
token_contains_option_argument = !index_of_equals.nil?
if switches.any? { |s| s[0, token.length] == token }
option_argument_needs_removal =
option_takes_argument && !token_contains_option_argument
true
elsif option_argument_needs_removal && token !~ /^-/
option_argument_needs_removal = false
true
else
option_argument_needs_removal = false
false
end
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
parser = options.inject(OptionParser.new) do |options, option|
options.on(*option[:args], &global_option_proc(option[:switches], &option[:proc]))
end
options = @args.dup
begin
parser.parse!(options)
rescue OptionParser::InvalidOption => e
# Remove the offending args and retry.
options = options.reject { |o| e.args.include?(o) }
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)
lambda do |value|
unless active_command.nil?
active_command.global_options << [Runner.switch_to_sym(switches.last), value]
end
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)
keys.each do |key|
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 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
# --[no-]feature # => :feature
# --file FILE # => :file
# --list of,things # => :list
#
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))
else
active_command.run(*args_without_command_name)
end
end
def say(*args) #:nodoc:
HighLine.default_instance.say(*args)
end
private
##
# Attempts to locate a command name from within the provided arguments.
# Supports multi-word commands, using the largest possible match.
def longest_valid_command_name_from(args)
valid_command_names_from(*args.dup).max
end
end
end
commander-4.6.0/lib/commander/version.rb 0000644 0000041 0000041 00000000110 14053714220 020231 0 ustar www-data www-data # frozen_string_literal: true
module Commander
VERSION = '4.6.0'
end
commander-4.6.0/lib/commander/methods.rb 0000644 0000041 0000041 00000000464 14053714220 020223 0 ustar www-data www-data # frozen_string_literal: true
module Commander
module Methods
include Commander::UI
include Commander::UI::AskForClass
include Commander::Delegates
if $stdin.tty? && (cols = HighLine.default_instance.output_cols) >= 40
HighLine.default_instance.wrap_at = cols - 5
end
end
end
commander-4.6.0/lib/commander/platform.rb 0000644 0000041 0000041 00000000240 14053714220 020374 0 ustar www-data www-data # frozen_string_literal: true
module Commander
module Platform
def self.jruby?
defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
end
end
end
commander-4.6.0/lib/commander/core_ext.rb 0000644 0000041 0000041 00000000146 14053714220 020365 0 ustar www-data www-data # frozen_string_literal: true
require 'commander/core_ext/array'
require 'commander/core_ext/object'
commander-4.6.0/lib/commander/user_interaction.rb 0000644 0000041 0000041 00000036127 14053714220 022142 0 ustar www-data www-data # frozen_string_literal: true
require 'tempfile'
require 'shellwords'
module Commander
##
# = User Interaction
#
# Commander's user interaction module mixes in common
# 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
# Do nothing
else
include Growl
end
##
# Ask the user for a password. Specify a custom
# _message_ other than 'Password: ' or override the
# default _mask_ of '*'.
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 = 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:
#
# create path/to/file.rb
# remove path/to/old_file.rb
# remove path/to/old_file2.rb
#
def log(action, *args)
say format('%15s %s', action, args.join(' '))
end
##
# 'Say' something using the OK color (green).
#
# === Examples
# say_ok 'Everything is fine'
# say_ok 'It is ok', 'This is ok too'
#
def say_ok(*args)
args.each do |arg|
say HighLine.default_instance.color(arg, :green)
end
end
##
# 'Say' something using the WARNING color (yellow).
#
# === Examples
# say_warning 'This is a warning'
# say_warning 'Be careful', 'Think about it'
#
def say_warning(*args)
args.each do |arg|
say HighLine.default_instance.color(arg, :yellow)
end
end
##
# 'Say' something using the ERROR color (red).
#
# === Examples
# say_error 'Everything is not fine'
# say_error 'It is not ok', 'This is not ok too'
#
def say_error(*args)
args.each do |arg|
say HighLine.default_instance.color(arg, :red)
end
end
##
# 'Say' something using the specified color
#
# === Examples
# color 'I am blue', :blue
# color 'I am bold', :bold
# color 'White on Red', :white, :on_red
#
# === Notes
# You may use:
# * color: black blue cyan green magenta red white yellow
# * style: blink bold clear underline
# * highligh: on_
def color(*args)
say HighLine.default_instance.color(*args)
end
##
# 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 "I like #{food} as well!", "Victoria", 190
#
# === Notes
#
# * MacOS only
#
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.
#
# Currently a "poorman's" DSL to utilize applescript and
# the MacOS speech recognition server.
#
# === Examples
#
# 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.'
# else
# speak 'Ok then, bye.'
# end
# end
#
# === Notes
#
# * MacOS only
#
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"
set response to listen for {#{commands}} with prompt "#{prompt}"
#{statement}
end if
end tell
)
).strip.to_sym
end
##
# Execute apple _script_.
def applescript(script)
`osascript -e "#{ script.gsub('"', '\"') }"`
end
##
# Normalize IO streams, allowing for redirection of
# +input+ and/or +output+, for example:
#
# $ foo # => read from terminal I/O
# $ foo in # => read from 'in' file, output to terminal output stream
# $ foo in out # => read from 'in' file, output to 'out' file
# $ foo < in > out # => equivalent to above (essentially)
#
# Optionally a +block+ may be supplied, in which case
# IO will be reset once the block has executed.
#
# === Examples
#
# command :foo do |c|
# c.syntax = 'foo [input] [output]'
# c.when_called do |args, options|
# # or io(args.shift, args.shift)
# io *args
# str = $stdin.gets
# puts 'input was: ' + str.inspect
# end
# end
#
def io(input = nil, output = nil, &block)
orig_stdin, orig_stdout = $stdin, $stdout
$stdin = File.new(input) if input
$stdout = File.new(output, 'r+') if output
return unless block
yield
$stdin, $stdout = orig_stdin, orig_stdout
reset_io
end
##
# 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>&-") }
end
##
# Prompt an editor for input. Optionally supply initial
# _input_ which is written to the editor.
#
# _preferred_editor_ can be hinted.
#
# === Examples
#
# ask_editor # => prompts EDITOR with no input
# 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)
editor = available_editor preferred_editor
program = Commander::Runner.instance.program(:name).downcase rescue 'commander'
tmpfile = Tempfile.new program
begin
tmpfile.write input if input
tmpfile.close
system("#{editor} #{tmpfile.path.shellescape}") ? IO.read(tmpfile.path) : nil
ensure
tmpfile.unlink
end
end
##
# Enable paging of output after called.
def enable_paging
return unless $stdout.tty?
return unless Process.respond_to? :fork
read, write = IO.pipe
# Kernel.fork is not supported on all platforms and configurations.
# As of Ruby 1.9, `Process.respond_to? :fork` should return false on
# 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
Kernel.select [$stdin]
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
end
rescue NotImplementedError
ensure
write.close if write && !write.closed?
read.close if read && !read.closed?
end
##
# Output progress while iterating _arr_.
#
# === Examples
#
# uris = %w( http://vision-media.ca http://google.com )
# progress uris, :format => "Remaining: :time_remaining" do |uri|
# res = open uri
# end
#
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
DEPRECATED_CONSTANTS = %i[Config TimeoutError MissingSourceFile NIL TRUE FALSE Fixnum Bignum Data].freeze
# define methods for common classes
[Float, Integer, String, Symbol, Regexp, Array, File, Pathname].each do |klass|
define_method "ask_for_#{klass.to_s.downcase}" do |prompt|
HighLine.default_instance.ask(prompt, klass)
end
end
def method_missing(method_name, *arguments, &block)
if method_name.to_s =~ /^ask_for_(.*)/
if arguments.count != 1
fail ArgumentError, "wrong number of arguments (given #{arguments.count}, expected 1)"
end
prompt = arguments.first
requested_class = Regexp.last_match[1]
# All Classes that respond to #parse
# Ignore constants that trigger deprecation warnings
available_classes = (Object.constants - DEPRECATED_CONSTANTS).map do |const|
begin
Object.const_get(const)
rescue RuntimeError
# Rescue errors in Ruby 3 for SortedSet:
# The `SortedSet` class has been extracted from the `set` library.
end
end.compact.select do |const|
const.instance_of?(Class) && const.respond_to?(:parse)
end
klass = available_classes.find { |k| k.to_s.downcase == requested_class }
if klass
HighLine.default_instance.ask(prompt, klass)
else
super
end
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
method_name.to_s.start_with?('ask_for_') || super
end
end
##
# Substitute _hash_'s keys with their associated values in _str_.
def replace_tokens(str, hash) #:nodoc:
hash.inject(str) do |string, (key, value)|
string.gsub ":#{key}", value.to_s
end
end
##
# = Progress Bar
#
# Terminal progress bar utility. In its most basic form
# requires that the developer specifies when the bar should
# be incremented. Note that a hash of tokens may be passed to
# #increment, (or returned when using Object#progress).
#
# 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|
# threads << Thread.new do
# begin
# res = open uri
# bar.increment :uri => uri
# rescue Exception => e
# bar.increment :uri => "#{uri} failed"
# end
# end
# end
# threads.each { |t| t.join }
#
# The Object method #progress is also available:
#
# progress uris, :width => 10 do |uri|
# res = open uri
# { :uri => uri } # Can now use :uri within :format option
# end
#
class ProgressBar
##
# Creates a new progress bar.
#
# === Options
#
# :title Title, defaults to "Progress"
# :width Width of :progress_bar
# :progress_str Progress string, defaults to "="
# :incomplete_str Incomplete bar string, defaults to '.'
# :format Defaults to ":title |:progress_bar| :percent_complete% complete "
# :tokens Additional tokens replaced within the format string
# :complete_message Defaults to "Process complete"
#
# === Tokens
#
# :title
# :percent_complete
# :progress_bar
# :step
# :steps_remaining
# :total_steps
# :time_elapsed
# :time_remaining
#
def initialize(total, options = {})
@total_steps, @step, @start_time = total, 0, Time.now
@title = options.fetch :title, 'Progress'
@width = options.fetch :width, 25
@progress_str = options.fetch :progress_str, '='
@incomplete_str = options.fetch :incomplete_str, '.'
@complete_message = options.fetch :complete_message, 'Process complete'
@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
else
@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: format('%0.2fs', time_elapsed),
time_remaining: @step.positive? ? format('%0.2fs', time_remaining) : '',
}.merge! @tokens
end
##
# Output the progress bar.
def show
return if finished?
erase_line
if completed?
HighLine.default_instance.say UI.replace_tokens(@complete_message, generate_tokens) if @complete_message.is_a? String
else
HighLine.default_instance.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
##
# Whether or not the operation has completed.
def completed?
@step == @total_steps
end
##
# Increment progress. Optionally pass _tokens_ which
# can be displayed in the output format.
def increment(tokens = {})
@step += 1
@tokens.merge! tokens if tokens.is_a? Hash
show
end
##
# Erase previous terminal line.
def erase_line
# highline does not expose the output stream
HighLine.default_instance.instance_variable_get('@output').print "\r\e[K"
end
end
end
end
commander-4.6.0/lib/commander/import.rb 0000644 0000041 0000041 00000000141 14053714220 020062 0 ustar www-data www-data # frozen_string_literal: true
require 'commander'
include Commander::Methods
at_exit { run! }
commander-4.6.0/lib/commander/command.rb 0000644 0000041 0000041 00000014254 14053714220 020200 0 ustar www-data www-data # frozen_string_literal: true
require 'optparse'
module Commander
class Command
attr_accessor :name, :examples, :syntax, :description, :summary, :proxy_options, :options
attr_reader :global_options
##
# Options struct.
class Options
include Blank
def initialize
@table = {}
end
def __hash__
@table
end
def method_missing(meth, *args)
meth.to_s =~ /=$/ ? @table[meth.to_s.chop.to_sym] = args.first : @table[meth]
end
def default(defaults = {})
@table = defaults.merge! @table
end
def inspect
""
end
end
##
# Initialize new command with specified _name_.
def initialize(name)
@name, @examples, @when_called = name.to_s, [], []
@options, @proxy_options = [], []
@global_options = []
end
##
# Add a usage example for this command.
#
# Usage examples are later displayed in help documentation
# created by the help formatters.
#
# === Examples
#
# command :something do |c|
# c.example "Should do something", "my_command something"
# end
#
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
# contains the results of this option. This handles common formats such as:
#
# -h, --help options.help # => bool
# --[no-]feature options.feature # => bool
# --large-switch options.large_switch # => bool
# --file FILE options.file # => file passed
# --list WORDS options.list # => array
# --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
#
# === Help Formatters
#
# This method also parses the arguments passed in order to determine
# which were switches, and which were descriptions for the
# option which can later be used within help formatters
# using option[:switches] and option[:description].
#
# === Input Parsing
#
# Since Commander utilizes OptionParser you can pre-parse and evaluate
# option arguments. Simply require 'optparse/time', or 'optparse/date', as these
# objects must respond to #parse.
#
# c.option '--time TIME', Time
# c.option '--date [DATE]', Date
#
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,
}
end
##
# 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
#
# # 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)
fail ArgumentError, 'must pass an object, class, or block.' if args.empty? && !block
@when_called = block ? [block] : args
end
alias action when_called
##
# Run the command with _args_.
#
# * parses options, call option blocks
# * invokes when_called proc
#
def run(*args)
call parse_options_and_call_procs(*args)
end
#:stopdoc:
##
# Parses options and calls associated procs,
# returning the arguments remaining.
def parse_options_and_call_procs(*args)
return args if args.empty?
# empty proxy_options before populating via OptionParser
# prevents duplication of options if the command is run twice
proxy_options.clear
@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 = [])
object, meth = @when_called[0, 2]
meth ||= :call
options = proxy_option_struct
case object
when Proc then object.call(args, options)
when Class then meth == :call ? object.new(args, options) : object.new.send(meth, args, options)
else object&.send(meth, args, options)
end
end
##
# Creates an Options instance populated with the option values
# collected by the #option_proc.
def proxy_option_struct
(global_options + 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)
->(value) { proxy_options << [Runner.switch_to_sym(switches.last), value] }
end
def inspect
""
end
end
end
commander-4.6.0/lib/commander/configure.rb 0000644 0000041 0000041 00000000567 14053714220 020545 0 ustar www-data www-data # frozen_string_literal: true
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
commander-4.6.0/lib/commander/blank.rb 0000644 0000041 0000041 00000000276 14053714220 017650 0 ustar www-data www-data # frozen_string_literal: true
module Blank
def self.included(base)
base.class_eval do
instance_methods.each { |m| undef_method m unless m =~ /^__|object_id/ }
end
end
end
commander-4.6.0/lib/commander/delegates.rb 0000644 0000041 0000041 00000001046 14053714220 020512 0 ustar www-data www-data # frozen_string_literal: true
module Commander
module Delegates
%w(
add_command
command
program
run!
global_option
alias_command
default_command
always_trace!
never_trace!
).each do |meth|
eval <<-END, binding, __FILE__, __LINE__ + 1
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
commander-4.6.0/lib/commander/help_formatters.rb 0000644 0000041 0000041 00000002327 14053714220 021756 0 ustar www-data www-data # frozen_string_literal: true
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.to_s.gsub("\n", "\n#{' ' * amount}")
end
end
end
commander-4.6.0/lib/commander/help_formatters/ 0000755 0000041 0000041 00000000000 14053714220 021425 5 ustar www-data www-data commander-4.6.0/lib/commander/help_formatters/terminal.rb 0000644 0000041 0000041 00000001210 14053714220 023557 0 ustar www-data www-data # frozen_string_literal: true
require 'erb'
module Commander
module HelpFormatter
class Terminal < Base
def render
template(:help).result(ProgramContext.new(@runner).get_binding)
end
def render_command(command)
template(:command_help).result(Context.new(command).get_binding)
end
def template(name)
if RUBY_VERSION < '2.6'
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal', "#{name}.erb")), nil, '-')
else
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal', "#{name}.erb")), trim_mode: '-')
end
end
end
end
end
commander-4.6.0/lib/commander/help_formatters/terminal_compact.rb 0000644 0000041 0000041 00000000711 14053714220 025272 0 ustar www-data www-data # frozen_string_literal: true
require 'erb'
module Commander
module HelpFormatter
class TerminalCompact < Terminal
def template(name)
if RUBY_VERSION < '2.6'
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal_compact', "#{name}.erb")), nil, '-')
else
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal_compact', "#{name}.erb")), trim_mode: '-')
end
end
end
end
end
commander-4.6.0/lib/commander/help_formatters/base.rb 0000644 0000041 0000041 00000001032 14053714220 022660 0 ustar www-data www-data # frozen_string_literal: true
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
end
end
end
commander-4.6.0/lib/commander/help_formatters/terminal/ 0000755 0000041 0000041 00000000000 14053714220 023240 5 ustar www-data www-data commander-4.6.0/lib/commander/help_formatters/terminal/help.erb 0000644 0000041 0000041 00000002145 14053714220 024664 0 ustar www-data www-data <%= HighLine.default_instance.color "NAME", :bold %>:
<%= program :name %>
<%= HighLine.default_instance.color "DESCRIPTION", :bold %>:
<%= Commander::HelpFormatter.indent 4, program(:description) %>
<%= HighLine.default_instance.color "COMMANDS", :bold %>:
<% for name, command in @commands.sort -%>
<% unless alias? name %>
<%= "%-#{max_command_length}s %s" % [command.name, command.summary || command.description] -%>
<% end -%>
<% end %>
<% unless @aliases.empty? %>
<%= HighLine.default_instance.color "ALIASES", :bold %>:
<% for alias_name, args in @aliases.sort %>
<%= "%-#{max_aliases_length}s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] -%>
<% end %>
<% end %>
<% unless @options.empty? -%>
<%= HighLine.default_instance.color "GLOBAL OPTIONS", :bold %>:
<% for option in @options -%>
<%= option[:switches].join ', ' %>
<%= option[:description] %>
<% end -%>
<% end -%>
<% if program :help -%>
<% for title, body in program(:help) %>
<%= HighLine.default_instance.color title.to_s.upcase, :bold %>:
<%= body %>
<% end -%>
<% end -%>
commander-4.6.0/lib/commander/help_formatters/terminal/command_help.erb 0000644 0000041 0000041 00000001452 14053714220 026362 0 ustar www-data www-data
<%= HighLine.default_instance.color "NAME", :bold %>:
<%= @name %>
<% if @syntax -%>
<%= HighLine.default_instance.color "SYNOPSIS", :bold %>:
<%= @syntax -%>
<% end -%>
<%= HighLine.default_instance.color "DESCRIPTION", :bold %>:
<%= Commander::HelpFormatter.indent 4, (@description || @summary || 'No description.') -%>
<% unless @examples.empty? -%>
<%= HighLine.default_instance.color "EXAMPLES", :bold %>:
<% for description, command in @examples -%>
# <%= description %>
<%= command %>
<% end -%>
<% end -%>
<% unless @options.empty? -%>
<%= HighLine.default_instance.color "OPTIONS", :bold %>:
<% for option in @options -%>
<%= option[:switches].join ', ' %>
<%= Commander::HelpFormatter.indent 8, option[:description] %>
<% end -%>
<% end -%>
commander-4.6.0/lib/commander/help_formatters/terminal_compact/ 0000755 0000041 0000041 00000000000 14053714220 024746 5 ustar www-data www-data commander-4.6.0/lib/commander/help_formatters/terminal_compact/help.erb 0000644 0000041 0000041 00000001374 14053714220 026375 0 ustar www-data www-data <%= program :name %>
<%= program :description %>
Commands:
<% for name, command in @commands.sort -%>
<% unless alias? name -%>
<%= "%-#{max_command_length}s %s" % [command.name, command.summary || command.description] %>
<% end -%>
<% end -%>
<% unless @aliases.empty? %>
Aliases:
<% for alias_name, args in @aliases.sort -%>
<%= "%-#{max_aliases_length}s %s %s" % [alias_name, command(alias_name).name, args.join(' ')] %>
<% end -%>
<% end %>
<% unless @options.empty? -%>
Global Options:
<% for option in @options -%>
<%= "%-20s %s" % [option[:switches].join(', '), option[:description]] -%>
<% end -%>
<% end -%>
<% if program :help -%>
<% for title, body in program(:help) %>
<%= title %>:
<%= body %>
<% end %>
<% end -%>
commander-4.6.0/lib/commander/help_formatters/terminal_compact/command_help.erb 0000644 0000041 0000041 00000000742 14053714220 030071 0 ustar www-data www-data
<%= @name %>
<% if @syntax -%>
Usage: <%= @syntax %>
<% end -%>
<% if @description || @summary -%>
<%= @description || @summary %>
<% end -%>
<% unless @examples.empty? -%>
Examples:
<% for description, command in @examples -%>
# <%= description %>
<%= command %>
<% end -%>
<% end -%>
<% unless @options.empty? -%>
Options:
<% for option in @options -%>
<%= "%-20s %s" % [option[:switches].join(', '), option[:description]] %>
<% end -%>
<% end -%>
commander-4.6.0/lib/commander.rb 0000644 0000041 0000041 00000002753 14053714220 016563 0 ustar www-data www-data # frozen_string_literal: true
#--
# Copyright (c) 2008-2009 TJ Holowaychuk
#
# 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.
#++
require 'highline/import'
require 'commander/version'
require 'commander/blank'
require 'commander/user_interaction'
require 'commander/core_ext'
require 'commander/runner'
require 'commander/command'
require 'commander/help_formatters'
require 'commander/platform'
require 'commander/delegates'
require 'commander/methods'
require 'commander/configure'
commander-4.6.0/Gemfile 0000644 0000041 0000041 00000000106 14053714220 015004 0 ustar www-data www-data # frozen_string_literal: true
source 'https://rubygems.org'
gemspec