Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 2 additions & 22 deletions lib/irb/completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,6 @@ class BaseCompletor # :nodoc:

# Set of reserved words used by Ruby, you should not use these for
# constants or variables
ReservedWords = %w[
__ENCODING__ __LINE__ __FILE__
BEGIN END
alias and
begin break
case class
def defined? do
else elsif end ensure
false for
if in
module
next nil not
or
redo rescue retry return
self super
then true
undef unless until
when while
yield
]

HELP_COMMAND_PREPOSING = /\Ahelp\s+/

Expand Down Expand Up @@ -459,12 +439,12 @@ def retrieve_completion_data(input, bind:, doc_namespace:)
eval("#{perfect_match_var}.class.name", bind) rescue nil
else
candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
candidates |= ReservedWords
candidates |= RubyLex::RESERVED_WORDS.map(&:to_s)
Comment thread
st0012 marked this conversation as resolved.
candidates.find{ |i| i == input }
end
else
candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
candidates |= ReservedWords
candidates |= RubyLex::RESERVED_WORDS.map(&:to_s)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the above.

candidates.grep(/^#{Regexp.quote(input)}/).sort
end
end
Expand Down
25 changes: 25 additions & 0 deletions lib/irb/ruby-lex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,27 @@ class RubyLex
on_words_beg on_qwords_beg
]

RESERVED_WORDS = %i[
__ENCODING__ __LINE__ __FILE__
BEGIN END
alias and
begin break
case class
def defined? do
else elsif end ensure
false for
if in
module
next nil not
or
redo rescue retry return
self super
then true
undef unless until
when while
yield
]

class TerminateLineInput < StandardError
def initialize
super("Terminate Line Input")
Expand All @@ -77,6 +98,10 @@ def compile_with_errors_suppressed(code, line_no: 1)
end

def generate_local_variables_assign_code(local_variables)
# Some reserved words could be a local variable
# Example: def f(if: 1); binding.irb; end
# These reserved words should be removed from assignment code
local_variables -= RESERVED_WORDS
"#{local_variables.join('=')}=nil;" unless local_variables.empty?
end

Expand Down
4 changes: 2 additions & 2 deletions test/irb/test_color.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ def test_colorize_code_with_local_variables
result_with_lvars = "a /(b +#{BLUE}#{BOLD}1#{CLEAR})/i"

assert_equal_with_term(result_without_lvars, code)
assert_equal_with_term(result_with_lvar, code, local_variables: ['a'])
assert_equal_with_term(result_with_lvars, code, local_variables: ['a', 'b'])
assert_equal_with_term(result_with_lvar, code, local_variables: [:a])
assert_equal_with_term(result_with_lvars, code, local_variables: [:a, :b])
end

def test_colorize_code_complete_true
Expand Down
14 changes: 14 additions & 0 deletions test/irb/test_irb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ def test_underscore_stores_last_result
assert_include output, "=> 12"
end

def test_local_variable_handeld_correctly
write_ruby <<~'RUBY'
tap do |if:0, and:0, foo:100|
binding.irb
end
RUBY

output = run_ruby_file do
type 'foo /4#/ do'
type 'exit!'
end
assert_include output, '=> 25'
end

def test_commands_dont_override_stored_last_result
write_ruby <<~'RUBY'
binding.irb
Expand Down
12 changes: 10 additions & 2 deletions test/irb/test_ruby_lex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,16 @@ def test_local_variables_dependent_code
lines = ["a /1#/ do", "2"]
assert_indent_level(lines, 1)
assert_code_block_open(lines, true)
assert_indent_level(lines, 0, local_variables: ['a'])
assert_code_block_open(lines, false, local_variables: ['a'])
assert_indent_level(lines, 0, local_variables: [:a])
assert_code_block_open(lines, false, local_variables: [:a])
end

def test_keyword_local_variables
# Assuming `def f(if: 1, and: 2, ); binding.irb; end`
local_variables = [:if, :and]
lines = ['1 + 2']
assert_indent_level(lines, 0, local_variables: local_variables)
assert_code_block_open(lines, false, local_variables: local_variables)
end

def test_literal_ends_with_space
Expand Down