diff --git a/lib/reline.rb b/lib/reline.rb index f88c368e5c..d88a8d7265 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -222,7 +222,6 @@ module Reline line_editor.auto_indent_proc = auto_indent_proc line_editor.dig_perfect_match_proc = dig_perfect_match_proc line_editor.pre_input_hook = pre_input_hook - line_editor.rerender unless config.test_mode config.read @@ -232,6 +231,8 @@ module Reline end end + line_editor.rerender + begin loop do read_io(config.keyseq_timeout) { |inputs| diff --git a/lib/reline/config.rb b/lib/reline/config.rb index 206be5be0e..9b8ddc0536 100644 --- a/lib/reline/config.rb +++ b/lib/reline/config.rb @@ -35,6 +35,10 @@ class Reline::Config show-all-if-ambiguous show-all-if-unmodified visible-stats + show-mode-in-prompt + vi-cmd-mode-icon + vi-ins-mode-icon + emacs-mode-string } VARIABLE_NAME_SYMBOLS = VARIABLE_NAMES.map { |v| :"#{v.tr(?-, ?_)}" } VARIABLE_NAME_SYMBOLS.each do |v| @@ -52,6 +56,9 @@ class Reline::Config @key_actors[:emacs] = Reline::KeyActor::Emacs.new @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new @key_actors[:vi_command] = Reline::KeyActor::ViCommand.new + @vi_cmd_mode_icon = '(cmd)' + @vi_ins_mode_icon = '(ins)' + @emacs_mode_string = '@' # https://tiswww.case.edu/php/chet/readline/readline.html#IDX25 @history_size = -1 # unlimited @keyseq_timeout = 500 @@ -253,6 +260,21 @@ class Reline::Config end when 'keyseq-timeout' @keyseq_timeout = value.to_i + when 'show-mode-in-prompt' + case value + when 'off' + @show_mode_in_prompt = false + when 'on' + @show_mode_in_prompt = true + else + @show_mode_in_prompt = false + end + when 'vi-cmd-mode-string' + @vi_cmd_mode_icon = value + when 'vi-ins-mode-string' + @vi_ins_mode_icon = value + when 'emacs-mode-string' + @emacs_mode_string = value when *VARIABLE_NAMES then variable_name = :"@#{name.tr(?-, ?_)}" instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on') diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 702bf0ee5b..81278810a0 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -76,11 +76,35 @@ class Reline::LineEditor if @prompt_proc prompt_list = @prompt_proc.(buffer) prompt_list.map!{ prompt } if @vi_arg or @searching_prompt + if @config.show_mode_in_prompt + if @config.editing_mode_is?(:vi_command) + mode_icon = @config.vi_cmd_mode_icon + elsif @config.editing_mode_is?(:vi_insert) + mode_icon = @config.vi_ins_mode_icon + elsif @config.editing_mode_is?(:emacs) + mode_icon = @config.emacs_mode_string + else + mode_icon = '?' + end + prompt_list.map!{ |pr| mode_icon + pr } + end prompt = prompt_list[@line_index] prompt_width = calculate_width(prompt, true) [prompt, prompt_width, prompt_list] else prompt_width = calculate_width(prompt, true) + if @config.show_mode_in_prompt + if @config.editing_mode_is?(:vi_command) + mode_icon = @config.vi_cmd_mode_icon + elsif @config.editing_mode_is?(:vi_insert) + mode_icon = @config.vi_ins_mode_icon + elsif @config.editing_mode_is?(:emacs) + mode_icon = @config.emacs_mode_string + else + mode_icon = '?' + end + prompt = mode_icon + prompt + end [prompt, prompt_width, nil] end end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index 080bc3624d..0d04e38308 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -81,6 +81,40 @@ begin prompt> EOC end + + def test_mode_icon_emacs + File.open(@inputrc_file, 'w') do |f| + f.write <<~LINES + set show-mode-in-prompt on + LINES + end + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl}) + sleep 0.5 + close + assert_screen(<<~EOC) + Multiline REPL. + @prompt> + EOC + end + + def test_mode_icon_vi + File.open(@inputrc_file, 'w') do |f| + f.write <<~LINES + set editing-mode vi + set show-mode-in-prompt on + LINES + end + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl}) + sleep 0.5 + write(":a\n\C-[k") + close + assert_screen(<<~EOC) + Multiline REPL. + (ins)prompt> :a + => :a + (cmd)prompt> :a + EOC + end end rescue LoadError, NameError # On Ruby repository, this test suit doesn't run because Ruby repo doesn't