gli 2.12.3 → 2.13.0
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 +4 -4
- data/lib/gli/app.rb +12 -0
- data/lib/gli/app_support.rb +9 -3
- data/lib/gli/command_finder.rb +42 -25
- data/lib/gli/gli_option_parser.rb +21 -10
- data/lib/gli/version.rb +1 -1
- data/test/tc_command_finder.rb +54 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b949aa32e5bf3ec2a8c7f98c690c75ec7e2a1577
|
4
|
+
data.tar.gz: da3bb5140f7bd7297857a2f80019d693b0bcb59f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7cdc67b6b99bc4f68075c5549a44a0cfd4e779697c071dce15c777bd6a743a78a540fc87cca4b91b5d59c363bc9c370645120a9013664cfd2d920ebfb05915c7
|
7
|
+
data.tar.gz: 5d5687cb17c78b7e66927e195e7ee2f27defb48292fc401066caf357c3aa0e6075c238afe1feffd7f115859b1e04c57ac57472237a61fedf1deed5eed519ede0
|
data/lib/gli/app.rb
CHANGED
@@ -302,6 +302,18 @@ module GLI
|
|
302
302
|
@argument_handling_strategy = handling_strategy
|
303
303
|
end
|
304
304
|
|
305
|
+
|
306
|
+
# Enables/Disables command autocomplete, where partially spelled commands are automatically expanded to their full form
|
307
|
+
#
|
308
|
+
# Example:
|
309
|
+
# When enabled, executing 'shake' would execute 'shake_hand' (if no 'shake' command is defined).
|
310
|
+
# When disabled, executing 'shake' would throw an UnknownCommand error
|
311
|
+
#
|
312
|
+
# +boolean+:: Boolean value to enable or disable autocomplete, respectively. True by default.
|
313
|
+
def autocomplete_commands(boolean)
|
314
|
+
@autocomplete = boolean
|
315
|
+
end
|
316
|
+
|
305
317
|
private
|
306
318
|
|
307
319
|
def load_commands(path)
|
data/lib/gli/app_support.rb
CHANGED
@@ -26,6 +26,7 @@ module GLI
|
|
26
26
|
@pre_block = false
|
27
27
|
@post_block = false
|
28
28
|
@default_command = :help
|
29
|
+
@autocomplete = false
|
29
30
|
@around_block = nil
|
30
31
|
@subcommand_option_handling_strategy = :legacy
|
31
32
|
@argument_handling_strategy = :loose
|
@@ -68,9 +69,10 @@ module GLI
|
|
68
69
|
flags,
|
69
70
|
switches,
|
70
71
|
accepts,
|
71
|
-
@default_command,
|
72
|
-
|
73
|
-
|
72
|
+
:default_command => @default_command,
|
73
|
+
:autocomplete => autocomplete,
|
74
|
+
:subcommand_option_handling_strategy => subcommand_option_handling_strategy,
|
75
|
+
:argument_handling_strategy => argument_handling_strategy)
|
74
76
|
|
75
77
|
parsing_result = gli_option_parser.parse_options(args)
|
76
78
|
parsing_result.convert_to_openstruct! if @use_openstruct
|
@@ -211,6 +213,10 @@ module GLI
|
|
211
213
|
@subcommand_option_handling_strategy || :legacy
|
212
214
|
end
|
213
215
|
|
216
|
+
def autocomplete
|
217
|
+
@autocomplete.nil? ? true : @autocomplete
|
218
|
+
end
|
219
|
+
|
214
220
|
private
|
215
221
|
|
216
222
|
def handle_exception(ex,command)
|
data/lib/gli/command_finder.rb
CHANGED
@@ -1,40 +1,57 @@
|
|
1
1
|
module GLI
|
2
2
|
class CommandFinder
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
attr_accessor :options
|
4
|
+
|
5
|
+
DEFAULT_OPTIONS = {
|
6
|
+
default_command: nil,
|
7
|
+
autocomplete: true
|
8
|
+
}
|
9
|
+
|
10
|
+
def initialize(commands, options = {})
|
11
|
+
self.options = DEFAULT_OPTIONS.merge(options)
|
12
|
+
self.commands_with_aliases = expand_with_aliases(commands)
|
13
13
|
end
|
14
14
|
|
15
|
-
# Finds the command with the given name, allowing for partial matches. Returns the command named by
|
16
|
-
# the default command if no command with +name+ matched
|
17
15
|
def find_command(name)
|
18
|
-
name
|
19
|
-
|
20
|
-
raise UnknownCommand.new("No command name given nor default available") if String(name).strip == ''
|
16
|
+
name = String(name || options[:default_command]).strip
|
17
|
+
raise UnknownCommand.new("No command name given nor default available") if name == ''
|
21
18
|
|
22
|
-
command_found =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
command_found = commands_with_aliases.fetch(name) do |command_to_match|
|
20
|
+
if options[:autocomplete]
|
21
|
+
found_match = find_command_by_partial_name(commands_with_aliases, command_to_match)
|
22
|
+
if found_match.kind_of? GLI::Command
|
23
|
+
if ENV["GLI_DEBUG"] == 'true'
|
24
|
+
$stderr.puts "Using '#{name}' as it's is short for #{found_match.name}."
|
25
|
+
$stderr.puts "Set autocomplete false for any command you don't want matched like this"
|
26
|
+
end
|
27
|
+
elsif found_match.kind_of?(Array) && !found_match.empty?
|
28
|
+
raise AmbiguousCommand.new("Ambiguous command '#{name}'. It matches #{found_match.sort.join(',')}")
|
29
|
+
end
|
30
|
+
found_match
|
31
|
+
end
|
29
32
|
end
|
33
|
+
|
34
|
+
raise UnknownCommand.new("Unknown command '#{name}'") if Array(command_found).empty?
|
30
35
|
command_found
|
31
36
|
end
|
32
37
|
|
33
38
|
private
|
39
|
+
attr_accessor :commands_with_aliases
|
40
|
+
|
41
|
+
def expand_with_aliases(commands)
|
42
|
+
expanded = {}
|
43
|
+
commands.each do |command_name, command|
|
44
|
+
expanded[command_name.to_s] = command
|
45
|
+
Array(command.aliases).each do |command_alias|
|
46
|
+
expanded[command_alias.to_s] = command
|
47
|
+
end
|
48
|
+
end
|
49
|
+
expanded
|
50
|
+
end
|
34
51
|
|
35
|
-
def find_command_by_partial_name(
|
36
|
-
partial_matches =
|
37
|
-
return
|
52
|
+
def find_command_by_partial_name(commands_with_aliases, command_to_match)
|
53
|
+
partial_matches = commands_with_aliases.keys.select { |command_name| command_name =~ /^#{command_to_match}/ }
|
54
|
+
return commands_with_aliases[partial_matches[0]] if partial_matches.size == 1
|
38
55
|
partial_matches
|
39
56
|
end
|
40
57
|
end
|
@@ -1,24 +1,35 @@
|
|
1
1
|
module GLI
|
2
2
|
# Parses the command-line options using an actual +OptionParser+
|
3
3
|
class GLIOptionParser
|
4
|
-
|
5
|
-
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
DEFAULT_OPTIONS = {
|
7
|
+
:default_command => nil,
|
8
|
+
:autocomplete => true,
|
9
|
+
:subcommand_option_handling_strategy => :legacy,
|
10
|
+
:argument_handling_strategy => :loose
|
11
|
+
}
|
12
|
+
|
13
|
+
def initialize(commands,flags,switches,accepts, options={})
|
14
|
+
self.options = DEFAULT_OPTIONS.merge(options)
|
15
|
+
|
16
|
+
command_finder = CommandFinder.new(commands,
|
17
|
+
:default_command => (options[:default_command] || :help),
|
18
|
+
:autocomplete => options[:autocomplete])
|
6
19
|
@global_option_parser = GlobalOptionParser.new(OptionParserFactory.new(flags,switches,accepts),command_finder,flags)
|
7
20
|
@accepts = accepts
|
8
|
-
|
9
|
-
@argument_handling_strategy = argument_handling_strategy
|
10
|
-
if @argument_handling_strategy == :strict && @subcommand_option_handling_strategy != :normal
|
21
|
+
if options[:argument_handling_strategy] == :strict && options[:subcommand_option_handling_strategy] != :normal
|
11
22
|
raise ArgumentError, "To use strict argument handling, you must enable normal subcommand_option_handling, e.g. subcommand_option_handling :normal"
|
12
23
|
end
|
13
24
|
end
|
14
25
|
|
15
26
|
# Given the command-line argument array, returns an OptionParsingResult
|
16
27
|
def parse_options(args) # :nodoc:
|
17
|
-
option_parser_class = self.class.const_get("#{
|
28
|
+
option_parser_class = self.class.const_get("#{options[:subcommand_option_handling_strategy].to_s.capitalize}CommandOptionParser")
|
18
29
|
OptionParsingResult.new.tap { |parsing_result|
|
19
30
|
parsing_result.arguments = args
|
20
31
|
parsing_result = @global_option_parser.parse!(parsing_result)
|
21
|
-
option_parser_class.new(@accepts).parse!(parsing_result,
|
32
|
+
option_parser_class.new(@accepts).parse!(parsing_result, options[:argument_handling_strategy])
|
22
33
|
}
|
23
34
|
end
|
24
35
|
|
@@ -101,7 +112,7 @@ module GLI
|
|
101
112
|
end
|
102
113
|
|
103
114
|
def error_handler
|
104
|
-
lambda { |message,extra_error_context|
|
115
|
+
lambda { |message,extra_error_context|
|
105
116
|
raise UnknownCommandArgument.new(message,extra_error_context)
|
106
117
|
}
|
107
118
|
end
|
@@ -120,7 +131,7 @@ module GLI
|
|
120
131
|
arguments = option_block_parser.parse!(arguments)
|
121
132
|
|
122
133
|
parsed_command_options[command] = option_parser_factory.options_hash_with_defaults_set!
|
123
|
-
command_finder = CommandFinder.new(command.commands,command.get_default_command)
|
134
|
+
command_finder = CommandFinder.new(command.commands, :default_command => command.get_default_command)
|
124
135
|
next_command_name = arguments.shift
|
125
136
|
|
126
137
|
verify_required_options!(command.flags, command, parsed_command_options[command])
|
@@ -193,7 +204,7 @@ module GLI
|
|
193
204
|
end
|
194
205
|
|
195
206
|
default_command = command.get_default_command
|
196
|
-
finder = CommandFinder.new(command.commands,default_command.to_s)
|
207
|
+
finder = CommandFinder.new(command.commands, :default_command => default_command.to_s)
|
197
208
|
|
198
209
|
begin
|
199
210
|
results = [finder.find_command(command_name),arguments[1..-1]]
|
data/lib/gli/version.rb
CHANGED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TC_testCommandFinder < Clean::Test::TestCase
|
4
|
+
include TestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@app = CLIApp.new
|
8
|
+
[:status, :deployable, :some_command, :some_similar_command].each do |command|
|
9
|
+
@app.commands[command] = GLI::Command.new(:names => command)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_unknown_command_name
|
17
|
+
assert_raise(GLI::UnknownCommand) do
|
18
|
+
GLI::CommandFinder.new(@app.commands, :default_command => :status).find_command(:unfindable_command)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_no_command_name_without_default
|
23
|
+
assert_raise(GLI::UnknownCommand) do
|
24
|
+
GLI::CommandFinder.new(@app.commands).find_command(nil)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_no_command_name_with_default
|
29
|
+
actual = GLI::CommandFinder.new(@app.commands, :default_command => :status).find_command(nil)
|
30
|
+
expected = @app.commands[:status]
|
31
|
+
|
32
|
+
assert_equal(actual, expected)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_ambigous_command
|
36
|
+
assert_raise(GLI::AmbiguousCommand) do
|
37
|
+
GLI::CommandFinder.new(@app.commands, :default_command => :status).find_command(:some)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_partial_name_with_autocorrect_enabled
|
42
|
+
actual = GLI::CommandFinder.new(@app.commands, :default_command => :status).find_command(:deploy)
|
43
|
+
expected = @app.commands[:deployable]
|
44
|
+
|
45
|
+
assert_equal(actual, expected)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_partial_name_with_autocorrect_disabled
|
49
|
+
assert_raise(GLI::UnknownCommand) do
|
50
|
+
GLI::CommandFinder.new(@app.commands, :default_command => :status, :autocomplete => false)
|
51
|
+
.find_command(:deploy)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Copeland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -241,6 +241,7 @@ files:
|
|
241
241
|
- test/init_simplecov.rb
|
242
242
|
- test/option_test_helper.rb
|
243
243
|
- test/tc_command.rb
|
244
|
+
- test/tc_command_finder.rb
|
244
245
|
- test/tc_compound_command.rb
|
245
246
|
- test/tc_doc.rb
|
246
247
|
- test/tc_flag.rb
|
@@ -319,6 +320,7 @@ test_files:
|
|
319
320
|
- test/init_simplecov.rb
|
320
321
|
- test/option_test_helper.rb
|
321
322
|
- test/tc_command.rb
|
323
|
+
- test/tc_command_finder.rb
|
322
324
|
- test/tc_compound_command.rb
|
323
325
|
- test/tc_doc.rb
|
324
326
|
- test/tc_flag.rb
|