diff options
author | Dmitry Gutov <dgutov@yandex.ru> | 2017-07-06 04:28:02 +0300 |
---|---|---|
committer | Dmitry Gutov <dgutov@yandex.ru> | 2017-07-06 04:28:02 +0300 |
commit | 4ba21483f9efa888e99e275ab6c1e975f04f5d66 (patch) | |
tree | 12216e513b300831985d902d981ad69041ab9aed | |
parent | acce49b8c0653d9fb87408a04b2b19a0d76ac860 (diff) | |
download | pry-4ba21483f9efa888e99e275ab6c1e975f04f5d66.tar.gz |
Fix method completion on string literals
* Remove quote characters from the "word break characters" list. This
was done in IRB some 5 years ago, in ruby/ruby@f1ce1f1.
* Change completer_word_break_characters instead of
basic_word_break_characters. The latter is only used during
Readline's initialization, to maybe set the value of the former.
* Except for JRuby, where completer_word_break_characters= is broken.
* Perform this assignment as soon as we can. By the time the completer
is created, Readline has already used this value at least once.
* Implement String-specific completion.
Fixes #1528.
-rw-r--r-- | lib/pry/config.rb | 15 | ||||
-rw-r--r-- | lib/pry/config/behavior.rb | 4 | ||||
-rw-r--r-- | lib/pry/input_completer.rb | 15 | ||||
-rw-r--r-- | spec/completion_spec.rb | 7 | ||||
-rw-r--r-- | spec/config_spec.rb | 14 |
5 files changed, 46 insertions, 9 deletions
diff --git a/lib/pry/config.rb b/lib/pry/config.rb index 4f702863..ba2076c9 100644 --- a/lib/pry/config.rb +++ b/lib/pry/config.rb @@ -8,4 +8,19 @@ class Pry::Config < Pry::BasicObject def self.shortcuts Convenience::SHORTCUTS end + + READLINE_WORD_ESCAPE_STR = " \t\n`><=;|&{(" + + def input=(input) + @lookup['input'] = input + + if input.respond_to?(:completer_word_break_characters=) + begin + input.completer_word_break_characters = READLINE_WORD_ESCAPE_STR + rescue ArgumentError + # Hi JRuby + input.basic_word_break_characters = READLINE_WORD_ESCAPE_STR + end + end + end end diff --git a/lib/pry/config/behavior.rb b/lib/pry/config/behavior.rb index f487637d..ee67ac3f 100644 --- a/lib/pry/config/behavior.rb +++ b/lib/pry/config/behavior.rb @@ -219,9 +219,11 @@ private def __push(key,value) unless singleton_class.method_defined? key define_singleton_method(key) { self[key] } + end + unless singleton_class.method_defined? "#{key}=" define_singleton_method("#{key}=") { |val| @lookup[key] = val } end - @lookup[key] = value + send("#{key}=", value) end def __remove(key) diff --git a/lib/pry/input_completer.rb b/lib/pry/input_completer.rb index 859cb667..b33668c1 100644 --- a/lib/pry/input_completer.rb +++ b/lib/pry/input_completer.rb @@ -12,7 +12,8 @@ class Pry::InputCompleter CONSTANT_OR_METHOD_REGEXP = /^([A-Z].*)::([^:.]*)$/ HEX_REGEXP = /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/ GLOBALVARIABLE_REGEXP = /^(\$[^.]*)$/ - VARIABLE_REGEXP = /^([^."].*)\.([^.]*)$/ + VARIABLE_REGEXP = /^(.*[^.'"])\.([^.]*)$/ + STRING_REGEXP = /^(.*["'])\.([^.]*)$/ ReservedWords = [ "BEGIN", "END", @@ -39,12 +40,9 @@ class Pry::InputCompleter "[]", "[]=", "^", "!", "!=", "!~" ] - WORD_ESCAPE_STR = " \t\n\"\\'`><=;|&{(" - def initialize(input, pry = nil) @pry = pry @input = input - @input.basic_word_break_characters = WORD_ESCAPE_STR if @input.respond_to?(:basic_word_break_characters=) @input.completion_append_character = nil if @input.respond_to?(:completion_append_character=) end @@ -179,12 +177,13 @@ class Pry::InputCompleter } end select_message(path, receiver, message, candidates.sort) - when /^\.([^.]*)$/ - # Unknown(maybe String) - receiver = "" - message = Regexp.quote($1) + when STRING_REGEXP + receiver = $1 + message = Regexp.quote($2) candidates = String.instance_methods(true).collect(&:to_s) select_message(path, receiver, message, candidates) + # TODO: Handle the target-less calls (e.g. with a space before the dot). + # when /^\.([^.]*)$/ else candidates = eval( "methods | private_methods | local_variables | " \ diff --git a/spec/completion_spec.rb b/spec/completion_spec.rb index 81996c07..40c73e5e 100644 --- a/spec/completion_spec.rb +++ b/spec/completion_spec.rb @@ -85,6 +85,13 @@ describe Pry::InputCompleter do # Absolute Constant completer_test(o).call('::IndexError') + + # String + completer_test(Object.new).call('"".size') + completer_test(Object.new).call('abcd".size') + + # Chain of calls starting with a string + completer_test(Object.new).call('abcd".size.times') end it 'should complete for target symbols' do diff --git a/spec/config_spec.rb b/spec/config_spec.rb index d6961c80..9d5c3956 100644 --- a/spec/config_spec.rb +++ b/spec/config_spec.rb @@ -239,4 +239,18 @@ describe Pry::Config do expect(local['output']).to eq(nil) end end + + describe "#input=" do + it 'assigns a value on the key' do + local = Pry::Config.from_hash({}) + local.input = :foo + expect(local.input).to eq(:foo) + end + + it 'modifies input itself' do + input = OpenStruct.new(completer_word_break_characters: 'asdf') + local = Pry::Config.from_hash(input: input) + expect(input.completer_word_break_characters).to eq(Pry::Config::READLINE_WORD_ESCAPE_STR) + end + end end |