gli 2.12.3 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 84a063f077612bd68999d7ab4771655577b9f66e
4
- data.tar.gz: 1c12e2ce024650ac44bff39eaba6a4df7f28f77c
3
+ metadata.gz: b949aa32e5bf3ec2a8c7f98c690c75ec7e2a1577
4
+ data.tar.gz: da3bb5140f7bd7297857a2f80019d693b0bcb59f
5
5
  SHA512:
6
- metadata.gz: d417534ed4728c1a95b03069dd965f9cc9b74bac4edcbdfc6087712ba13e6a55084c71d6c58e21af237dfc8685dc8208a3b9371a6320ba3d31c54804007251f3
7
- data.tar.gz: 01fb54aa5de01661ef48dfb2d359fa396db13bbc9bb16fb20d75f1f71cda9197047f925d63754b831b4661c94ff8c3849ba1c3cf0e578074ab843eab8ae3ffa6
6
+ metadata.gz: 7cdc67b6b99bc4f68075c5549a44a0cfd4e779697c071dce15c777bd6a743a78a540fc87cca4b91b5d59c363bc9c370645120a9013664cfd2d920ebfb05915c7
7
+ data.tar.gz: 5d5687cb17c78b7e66927e195e7ee2f27defb48292fc401066caf357c3aa0e6075c238afe1feffd7f115859b1e04c57ac57472237a61fedf1deed5eed519ede0
@@ -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)
@@ -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
- self.subcommand_option_handling_strategy,
73
- self.argument_handling_strategy)
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)
@@ -1,40 +1,57 @@
1
1
  module GLI
2
2
  class CommandFinder
3
- # Initialize a finder on the given list of commands, using default_command as the default if none found
4
- def initialize(commands,default_command)
5
- @default_command = default_command
6
- @names_to_commands = {}
7
- commands.each do |command_name,command|
8
- @names_to_commands[command_name.to_s] = command
9
- Array(command.aliases).each do |command_alias|
10
- @names_to_commands[command_alias.to_s] = command
11
- end
12
- end
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 ||= @default_command
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 = @names_to_commands.fetch(name.to_s) do |command_to_match|
23
- find_command_by_partial_name(@names_to_commands, command_to_match)
24
- end
25
- if Array(command_found).empty?
26
- raise UnknownCommand.new("Unknown command '#{name}'")
27
- elsif command_found.kind_of? Array
28
- raise AmbiguousCommand.new("Ambiguous command '#{name}'. It matches #{command_found.sort.join(',')}")
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(names_to_commands, command_to_match)
36
- partial_matches = names_to_commands.keys.select { |command_name| command_name =~ /^#{command_to_match}/ }
37
- return names_to_commands[partial_matches[0]] if partial_matches.size == 1
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
- def initialize(commands,flags,switches,accepts,default_command = nil,subcommand_option_handling_strategy=:legacy,argument_handling_strategy=:loose)
5
- command_finder = CommandFinder.new(commands,default_command || "help")
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
- @subcommand_option_handling_strategy = subcommand_option_handling_strategy
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("#{@subcommand_option_handling_strategy.to_s.capitalize}CommandOptionParser")
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, @argument_handling_strategy)
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]]
@@ -1,5 +1,5 @@
1
1
  module GLI
2
2
  unless const_defined? :VERSION
3
- VERSION = '2.12.3'
3
+ VERSION = '2.13.0'
4
4
  end
5
5
  end
@@ -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.12.3
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-02-21 00:00:00.000000000 Z
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