Skip to content

Commit

Permalink
Fix inputrc nested $if $else $endif bug (#689)
Browse files Browse the repository at this point in the history
  • Loading branch information
tompng committed Apr 25, 2024
1 parent 0c8d3c8 commit 0d8aea2
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 18 deletions.
29 changes: 11 additions & 18 deletions lib/reline/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ def initialize
@additional_key_bindings[:vi_insert] = {}
@additional_key_bindings[:vi_command] = {}
@oneshot_key_bindings = {}
@skip_section = nil
@if_stack = nil
@editing_mode_label = :emacs
@keymap_label = :emacs
@keymap_prefix = []
Expand Down Expand Up @@ -190,9 +188,7 @@ def read_lines(lines, file = nil)
end
end
end
conditions = [@skip_section, @if_stack]
@skip_section = nil
@if_stack = []
if_stack = []

lines.each_with_index do |line, no|
next if line.match(/\A\s*#/)
Expand All @@ -201,11 +197,11 @@ def read_lines(lines, file = nil)

line = line.chomp.lstrip
if line.start_with?('$')
handle_directive(line[1..-1], file, no)
handle_directive(line[1..-1], file, no, if_stack)
next
end

next if @skip_section
next if if_stack.any? { |_no, skip| skip }

case line
when /^set +([^ ]+) +([^ ]+)/i
Expand All @@ -219,14 +215,12 @@ def read_lines(lines, file = nil)
@additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
end
end
unless @if_stack.empty?
raise InvalidInputrc, "#{file}:#{@if_stack.last[1]}: unclosed if"
unless if_stack.empty?
raise InvalidInputrc, "#{file}:#{if_stack.last[0]}: unclosed if"
end
ensure
@skip_section, @if_stack = conditions
end

def handle_directive(directive, file, no)
def handle_directive(directive, file, no, if_stack)
directive, args = directive.split(' ')
case directive
when 'if'
Expand All @@ -239,18 +233,17 @@ def handle_directive(directive, file, no)
condition = true if args == 'Ruby'
condition = true if args == 'Reline'
end
@if_stack << [file, no, @skip_section]
@skip_section = !condition
if_stack << [no, !condition]
when 'else'
if @if_stack.empty?
if if_stack.empty?
raise InvalidInputrc, "#{file}:#{no}: unmatched else"
end
@skip_section = !@skip_section
if_stack.last[1] = !if_stack.last[1]
when 'endif'
if @if_stack.empty?
if if_stack.empty?
raise InvalidInputrc, "#{file}:#{no}: unmatched endif"
end
@skip_section = @if_stack.pop
if_stack.pop
when 'include'
read(File.expand_path(args))
end
Expand Down
32 changes: 32 additions & 0 deletions test/reline/test_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,38 @@ def test_if_with_indent
end
end

def test_nested_if_else
@config.read_lines(<<~LINES.lines)
$if Ruby
"\x1": "O"
$if NotRuby
"\x2": "X"
$else
"\x3": "O"
$if Ruby
"\x4": "O"
$else
"\x5": "X"
$endif
"\x6": "O"
$endif
"\x7": "O"
$else
"\x8": "X"
$if NotRuby
"\x9": "X"
$else
"\xA": "X"
$endif
"\xB": "X"
$endif
"\xC": "O"
LINES
keys = [0x1, 0x3, 0x4, 0x6, 0x7, 0xC]
key_bindings = keys.to_h { |k| [[k.ord], ['O'.ord]] }
assert_equal(key_bindings, @config.instance_variable_get(:@additional_key_bindings)[:emacs])
end

def test_unclosed_if
e = assert_raise(Reline::Config::InvalidInputrc) do
@config.read_lines(<<~LINES.lines, "INPUTRC")
Expand Down

0 comments on commit 0d8aea2

Please sign in to comment.