summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Gutov <dgutov@yandex.ru>2017-07-06 04:28:02 +0300
committerDmitry Gutov <dgutov@yandex.ru>2017-07-06 04:28:02 +0300
commit4ba21483f9efa888e99e275ab6c1e975f04f5d66 (patch)
tree12216e513b300831985d902d981ad69041ab9aed
parentacce49b8c0653d9fb87408a04b2b19a0d76ac860 (diff)
downloadpry-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.rb15
-rw-r--r--lib/pry/config/behavior.rb4
-rw-r--r--lib/pry/input_completer.rb15
-rw-r--r--spec/completion_spec.rb7
-rw-r--r--spec/config_spec.rb14
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