murano-cli-commander 4.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +44 -0
- data/.rubocop_todo.yml +77 -0
- data/.travis.yml +14 -0
- data/DEVELOPMENT +15 -0
- data/Gemfile +3 -0
- data/History.rdoc +446 -0
- data/LICENSE +22 -0
- data/Manifest +38 -0
- data/README.md +475 -0
- data/Rakefile +13 -0
- data/bin/murano-cli-commander +104 -0
- data/lib/murano-cli-commander.rb +35 -0
- data/lib/murano-cli-commander/blank.rb +7 -0
- data/lib/murano-cli-commander/command.rb +214 -0
- data/lib/murano-cli-commander/configure.rb +14 -0
- data/lib/murano-cli-commander/core_ext.rb +2 -0
- data/lib/murano-cli-commander/core_ext/array.rb +24 -0
- data/lib/murano-cli-commander/core_ext/object.rb +8 -0
- data/lib/murano-cli-commander/delegates.rb +25 -0
- data/lib/murano-cli-commander/help_formatters.rb +49 -0
- data/lib/murano-cli-commander/help_formatters/base.rb +24 -0
- data/lib/murano-cli-commander/help_formatters/terminal.rb +19 -0
- data/lib/murano-cli-commander/help_formatters/terminal/command_help.erb +35 -0
- data/lib/murano-cli-commander/help_formatters/terminal/help.erb +36 -0
- data/lib/murano-cli-commander/help_formatters/terminal_compact.rb +11 -0
- data/lib/murano-cli-commander/help_formatters/terminal_compact/command_help.erb +27 -0
- data/lib/murano-cli-commander/help_formatters/terminal_compact/help.erb +29 -0
- data/lib/murano-cli-commander/import.rb +5 -0
- data/lib/murano-cli-commander/methods.rb +11 -0
- data/lib/murano-cli-commander/platform.rb +7 -0
- data/lib/murano-cli-commander/runner.rb +455 -0
- data/lib/murano-cli-commander/user_interaction.rb +551 -0
- data/lib/murano-cli-commander/version.rb +3 -0
- data/murano-cli-commander.gemspec +36 -0
- data/spec/command_spec.rb +169 -0
- data/spec/configure_spec.rb +37 -0
- data/spec/core_ext/array_spec.rb +18 -0
- data/spec/core_ext/object_spec.rb +19 -0
- data/spec/help_formatters/terminal_compact_spec.rb +69 -0
- data/spec/help_formatters/terminal_spec.rb +67 -0
- data/spec/methods_spec.rb +61 -0
- data/spec/runner_spec.rb +646 -0
- data/spec/spec_helper.rb +78 -0
- data/spec/ui_spec.rb +30 -0
- metadata +163 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
4
|
+
require 'murano-cli-commander/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'murano-cli-commander'
|
8
|
+
s.version = Commander::VERSION
|
9
|
+
# (lb); Original thanks to:
|
10
|
+
# s.authors = ['TJ Holowaychuk', 'Gabriel Gilder']
|
11
|
+
# s.email = ['gabriel@gabrielgilder.com']
|
12
|
+
# s.homepage = 'https://github.com/commander-rb/commander'
|
13
|
+
s.authors = ['Exosite LLC']
|
14
|
+
s.email = ['murano-cli-commander@exosite.com']
|
15
|
+
s.license = 'MIT'
|
16
|
+
s.homepage = 'https://github.com/exosite/murano-cli-commander'
|
17
|
+
s.summary = 'The complete solution for Ruby command-line executables'
|
18
|
+
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.'
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
23
|
+
s.require_paths = ['lib']
|
24
|
+
|
25
|
+
s.add_runtime_dependency('highline', '~> 1.7.2')
|
26
|
+
|
27
|
+
s.add_development_dependency('rspec', '~> 3.2')
|
28
|
+
s.add_development_dependency('rake')
|
29
|
+
s.add_development_dependency('simplecov')
|
30
|
+
if RUBY_VERSION < '2.0'
|
31
|
+
s.add_development_dependency('rubocop', '~> 0.41.1')
|
32
|
+
s.add_development_dependency('json', '< 2.0')
|
33
|
+
else
|
34
|
+
s.add_development_dependency('rubocop', '~> 0.49.1')
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Commander::Command do
|
4
|
+
include Commander::Methods
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
mock_terminal
|
8
|
+
create_test_command
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'Options' do
|
12
|
+
before :each do
|
13
|
+
@options = Commander::Command::Options.new
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should act like an open struct' do
|
17
|
+
@options.send = 'mail'
|
18
|
+
@options.call = true
|
19
|
+
expect(@options.send).to eq('mail')
|
20
|
+
expect(@options.call).to eq(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should allow __send__ to function as always' do
|
24
|
+
@options.send = 'foo'
|
25
|
+
expect(@options.__send__(:send)).to eq('foo')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#option' do
|
30
|
+
it 'should add options' do
|
31
|
+
expect { @command.option '--recursive' }.to change(@command.options, :length).from(1).to(2)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should allow procs as option handlers' do
|
35
|
+
@command.option('--recursive') { |recursive| expect(recursive).to be true }
|
36
|
+
@command.run '--recursive'
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should allow usage of common method names' do
|
40
|
+
@command.option '--open file'
|
41
|
+
@command.when_called { |_, options| expect(options.open).to eq('foo') }
|
42
|
+
@command.run '--open', 'foo'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#run' do
|
47
|
+
describe 'should invoke #when_called' do
|
48
|
+
it 'with arguments seperated from options' do
|
49
|
+
@command.when_called { |args, _options| expect(args.join(' ')).to eq('just some args') }
|
50
|
+
@command.run '--verbose', 'just', 'some', 'args'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'calling the #call method by default when an object is called' do
|
54
|
+
object = double 'Object'
|
55
|
+
expect(object).to receive(:call).once
|
56
|
+
@command.when_called object
|
57
|
+
@command.run 'foo'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should allow #action as an alias to #when_called' do
|
61
|
+
object = double 'Object'
|
62
|
+
expect(object).to receive(:call).once
|
63
|
+
@command.action object
|
64
|
+
@command.run 'foo'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'calling an arbitrary method when an object is called' do
|
68
|
+
object = double 'Object'
|
69
|
+
expect(object).to receive(:foo).once
|
70
|
+
@command.when_called object, :foo
|
71
|
+
@command.run 'foo'
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should raise an error when no handler is present' do
|
75
|
+
expect { @command.when_called }.to raise_error(ArgumentError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should be able to be run more than once' do
|
79
|
+
expect(@command.run('once')).to eql('test once')
|
80
|
+
expect(@command.run('twice')).to eql('test twice')
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should not accumulate entries in @proxy_options when run twice' do
|
84
|
+
expect(@command.run('--verbose')).to eql('test ')
|
85
|
+
expect(@command.proxy_options).to eq([[:verbose, true]])
|
86
|
+
expect(@command.run('foo')).to eql('test foo')
|
87
|
+
expect(@command.proxy_options).to eq([])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'should populate options with' do
|
92
|
+
it 'boolean values' do
|
93
|
+
@command.option '--[no-]toggle'
|
94
|
+
@command.when_called { |_, options| expect(options.toggle).to be true }
|
95
|
+
@command.run '--toggle'
|
96
|
+
@command.when_called { |_, options| expect(options.toggle).to be false }
|
97
|
+
@command.run '--no-toggle'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'mandatory arguments' do
|
101
|
+
@command.option '--file FILE'
|
102
|
+
@command.when_called { |_, options| expect(options.file).to eq('foo') }
|
103
|
+
@command.run '--file', 'foo'
|
104
|
+
expect { @command.run '--file' }.to raise_error(OptionParser::MissingArgument)
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'optional arguments' do
|
108
|
+
before do
|
109
|
+
@command.option '--use-config [file] '
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should return the argument when provided' do
|
113
|
+
@command.when_called { |_, options| expect(options.use_config).to eq('foo') }
|
114
|
+
@command.run '--use-config', 'foo'
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should return true when present without an argument' do
|
118
|
+
@command.when_called { |_, options| expect(options.use_config).to be true }
|
119
|
+
@command.run '--use-config'
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should return nil when not present' do
|
123
|
+
@command.when_called { |_, options| expect(options.use_config).to be_nil }
|
124
|
+
@command.run
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'typed arguments' do
|
129
|
+
before do
|
130
|
+
@command.option '--interval N', Integer
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should parse valid values' do
|
134
|
+
@command.when_called { |_, options| expect(options.interval).to eq(5) }
|
135
|
+
@command.run '--interval', '5'
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should reject invalid values' do
|
139
|
+
expect { @command.run '--interval', 'invalid' }.to raise_error(OptionParser::InvalidArgument)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'lists' do
|
144
|
+
@command.option '--fav COLORS', Array
|
145
|
+
@command.when_called { |_, options| expect(options.fav).to eq(%w(red green blue)) }
|
146
|
+
@command.run '--fav', 'red,green,blue'
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'lists with multi-word items' do
|
150
|
+
@command.option '--fav MOVIES', Array
|
151
|
+
@command.when_called { |_, options| expect(options.fav).to eq(['super\ bad', 'nightmare']) }
|
152
|
+
@command.run '--fav', 'super\ bad,nightmare'
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'defaults' do
|
156
|
+
@command.option '--files LIST', Array
|
157
|
+
@command.option '--interval N', Integer
|
158
|
+
@command.when_called do |_, options|
|
159
|
+
options.default \
|
160
|
+
files: %w(foo bar),
|
161
|
+
interval: 5
|
162
|
+
expect(options.files).to eq(%w(foo bar))
|
163
|
+
expect(options.interval).to eq(15)
|
164
|
+
end
|
165
|
+
@command.run '--interval', '15'
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'murano-cli-commander/configure'
|
3
|
+
|
4
|
+
describe Commander do
|
5
|
+
describe '.configure' do
|
6
|
+
it 'calls the given block' do
|
7
|
+
expect { Commander.configure { throw :block_called } }.to throw_symbol(:block_called)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'called block' do
|
11
|
+
before(:each) do
|
12
|
+
allow(Commander::Runner.instance).to receive(:run!)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'provides Commander configuration methods' do
|
16
|
+
Commander.configure do
|
17
|
+
program :name, 'test'
|
18
|
+
end
|
19
|
+
|
20
|
+
expect(Commander::Runner.instance.program(:name)).to eq('test')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'passes all arguments to the block' do
|
24
|
+
Commander.configure('foo') do |first_arg|
|
25
|
+
program :name, first_arg
|
26
|
+
end
|
27
|
+
|
28
|
+
expect(Commander::Runner.instance.program(:name)).to eq('foo')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'calls Runner#run! after calling the configuration block' do
|
33
|
+
expect(Commander::Runner.instance).to receive(:run!)
|
34
|
+
Commander.configure {}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Array do
|
4
|
+
describe '#parse' do
|
5
|
+
it 'should seperate a list of words into an array' do
|
6
|
+
expect(Array.parse('just a test')).to eq(%w(just a test))
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should preserve escaped whitespace' do
|
10
|
+
expect(Array.parse('just a\ test')).to eq(['just', 'a test'])
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should match %w behavior with multiple backslashes' do
|
14
|
+
str = 'just a\\ test'
|
15
|
+
expect(Array.parse(str)).to eq(eval("%w(#{str})"))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Object do
|
4
|
+
describe '#get_binding' do
|
5
|
+
it 'should return the objects binding' do
|
6
|
+
expect(-> {}.get_binding).to be_instance_of(Binding)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#method_missing' do
|
11
|
+
it 'should preserve its original behavior for missing methods' do
|
12
|
+
expect { send(:i_am_a_missing_method) }.to raise_error(NoMethodError)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should preserve its original behavior for missing variables' do
|
16
|
+
expect { i_am_a_missing_variable }.to raise_error(NameError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Commander::HelpFormatter::TerminalCompact do
|
4
|
+
include Commander::Methods
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
mock_terminal
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'global help' do
|
11
|
+
before :each do
|
12
|
+
new_command_runner 'help' do
|
13
|
+
program :help_formatter, :compact
|
14
|
+
command :'install gem' do |c|
|
15
|
+
c.syntax = 'foo install gem [options]'
|
16
|
+
c.summary = 'Install some gem'
|
17
|
+
end
|
18
|
+
end.run!
|
19
|
+
@global_help = @output.string
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'should display' do
|
23
|
+
it 'the command name' do
|
24
|
+
expect(@global_help).to include('install gem')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'the summary' do
|
28
|
+
expect(@global_help).to include('Install some gem')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'command help' do
|
34
|
+
before :each do
|
35
|
+
new_command_runner 'help', 'install', 'gem' do
|
36
|
+
program :help_formatter, :compact
|
37
|
+
command :'install gem' do |c|
|
38
|
+
c.syntax = 'foo install gem [options]'
|
39
|
+
c.summary = 'Install some gem'
|
40
|
+
c.description = 'Install some gem, blah blah blah'
|
41
|
+
c.example 'one', 'two'
|
42
|
+
c.example 'three', 'four'
|
43
|
+
end
|
44
|
+
end.run!
|
45
|
+
@command_help = @output.string
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'should display' do
|
49
|
+
it 'the command name' do
|
50
|
+
expect(@command_help).to include('install gem')
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'the description' do
|
54
|
+
expect(@command_help).to include('Install some gem, blah blah blah')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'all examples' do
|
58
|
+
expect(@command_help).to include('# one')
|
59
|
+
expect(@command_help).to include('two')
|
60
|
+
expect(@command_help).to include('# three')
|
61
|
+
expect(@command_help).to include('four')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'the syntax' do
|
65
|
+
expect(@command_help).to include('foo install gem [options]')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Commander::HelpFormatter::Terminal do
|
4
|
+
include Commander::Methods
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
mock_terminal
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'global help' do
|
11
|
+
before :each do
|
12
|
+
new_command_runner 'help' do
|
13
|
+
command :'install gem' do |c|
|
14
|
+
c.syntax = 'foo install gem [options]'
|
15
|
+
c.summary = 'Install some gem'
|
16
|
+
end
|
17
|
+
end.run!
|
18
|
+
@global_help = @output.string
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'should display' do
|
22
|
+
it 'the command name' do
|
23
|
+
expect(@global_help).to include('install gem')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'the summary' do
|
27
|
+
expect(@global_help).to include('Install some gem')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'command help' do
|
33
|
+
before :each do
|
34
|
+
new_command_runner 'help', 'install', 'gem' do
|
35
|
+
command :'install gem' do |c|
|
36
|
+
c.syntax = 'foo install gem [options]'
|
37
|
+
c.summary = 'Install some gem'
|
38
|
+
c.description = 'Install some gem, blah blah blah'
|
39
|
+
c.example 'one', 'two'
|
40
|
+
c.example 'three', 'four'
|
41
|
+
end
|
42
|
+
end.run!
|
43
|
+
@command_help = @output.string
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'should display' do
|
47
|
+
it 'the command name' do
|
48
|
+
expect(@command_help).to include('install gem')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'the description' do
|
52
|
+
expect(@command_help).to include('Install some gem, blah blah blah')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'all examples' do
|
56
|
+
expect(@command_help).to include('# one')
|
57
|
+
expect(@command_help).to include('two')
|
58
|
+
expect(@command_help).to include('# three')
|
59
|
+
expect(@command_help).to include('four')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'the syntax' do
|
63
|
+
expect(@command_help).to include('foo install gem [options]')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'murano-cli-commander/methods'
|
3
|
+
|
4
|
+
describe Commander::Methods do
|
5
|
+
it 'includes Commander::UI' do
|
6
|
+
expect(subject.ancestors).to include(Commander::UI)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'AskForClass' do
|
10
|
+
it 'includes Commander::UI::AskForClass' do
|
11
|
+
expect(subject.ancestors).to include(Commander::UI::AskForClass)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'defining methods' do
|
15
|
+
let(:terminal) { double }
|
16
|
+
|
17
|
+
before do
|
18
|
+
allow(terminal).to receive(:ask)
|
19
|
+
$_old_terminal = $terminal
|
20
|
+
$terminal = terminal
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
$terminal = $_old_terminal
|
25
|
+
end
|
26
|
+
|
27
|
+
subject do
|
28
|
+
Class.new do
|
29
|
+
include Commander::UI::AskForClass
|
30
|
+
end.new
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'defines common "ask_for_*" methods' do
|
34
|
+
expect(subject.respond_to?(:ask_for_float)).to be_truthy
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'responds to "ask_for_*" methods for classes that implement #parse' do
|
38
|
+
expect(subject.respond_to?(:ask_for_datetime)).to be_truthy
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'fails "ask_for_*" method invocations without a prompt' do
|
42
|
+
expect do
|
43
|
+
subject.ask_for_datetime
|
44
|
+
end.to raise_error(ArgumentError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'implements "ask_for_*"' do
|
48
|
+
expect(terminal).to receive(:ask)
|
49
|
+
subject.ask_for_datetime('hi')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'includes Commander::Delegates' do
|
55
|
+
expect(subject.ancestors).to include(Commander::Delegates)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'does not change the Object ancestors' do
|
59
|
+
expect(Object.ancestors).not_to include(Commander::UI)
|
60
|
+
end
|
61
|
+
end
|