[ruby/reline] Fix inputrc nested $if $else $endif bug

(https://github.com/ruby/reline/pull/689)

https://github.com/ruby/reline/commit/0d8aea26ec
This commit is contained in:
tomoya ishida 2024-04-26 01:12:46 +09:00 коммит произвёл git
Родитель 3a5d9553a7
Коммит 4ff249363d
2 изменённых файлов: 43 добавлений и 18 удалений

Просмотреть файл

@ -53,8 +53,6 @@ class Reline::Config
@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 = []
@ -190,9 +188,7 @@ class Reline::Config
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*#/)
@ -201,11 +197,11 @@ class Reline::Config
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
@ -219,14 +215,12 @@ class Reline::Config
@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'
@ -239,18 +233,17 @@ class Reline::Config
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

Просмотреть файл

@ -216,6 +216,38 @@ class Reline::Config::Test < Reline::TestCase
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")