Skip to content
Open
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
6 changes: 6 additions & 0 deletions lib/reline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class Core
output_modifier_proc
prompt_proc
auto_indent_proc
rprompt
pre_input_hook
dig_perfect_match_proc
).each(&method(:attr_reader))
Expand Down Expand Up @@ -158,6 +159,10 @@ def dig_perfect_match_proc=(p)
@dig_perfect_match_proc = p
end

def rprompt=(val)
@rprompt = val&.encode(encoding)
end

DialogProc = Struct.new(:dialog_proc, :context)
def add_dialog_proc(name_sym, p, context = nil)
raise ArgumentError unless name_sym.instance_of?(Symbol)
Expand Down Expand Up @@ -323,6 +328,7 @@ def readline(prompt = '', add_hist = false)
line_editor.prompt_proc = prompt_proc
line_editor.auto_indent_proc = auto_indent_proc
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
line_editor.rprompt = rprompt

pre_input_hook&.call

Expand Down
15 changes: 15 additions & 0 deletions lib/reline/line_editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Reline::LineEditor
attr_accessor :prompt_proc
attr_accessor :auto_indent_proc
attr_accessor :dig_perfect_match_proc
attr_accessor :rprompt

VI_MOTIONS = %i{
ed_prev_char
Expand Down Expand Up @@ -476,6 +477,20 @@ def render
prompt_width = Reline::Unicode.calculate_width(prompt, true)
[[0, prompt_width, prompt], [prompt_width, Reline::Unicode.calculate_width(line, true), line]]
end

# Add rprompt to the first visible line if set and there's room
if @rprompt && [email protected]? && new_lines[0]
rprompt_width = Reline::Unicode.calculate_width(@rprompt, true)
right_col = screen_width - rprompt_width
first_line = new_lines[0]
# Calculate the end of the current content (prompt + input)
content_end = first_line.sum { |_, width, _| width }
# Only show rprompt if there's at least 1 char gap between content and rprompt
if right_col > content_end
first_line << [right_col, rprompt_width, @rprompt]
end
end

if @menu_info
@menu_info.lines(screen_width).each do |item|
new_lines << [[0, Reline::Unicode.calculate_width(item), item]]
Expand Down
16 changes: 16 additions & 0 deletions test/reline/test_reline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def setup
Reline.auto_indent_proc = nil
Reline.pre_input_hook = nil
Reline.dig_perfect_match_proc = nil
Reline.rprompt = nil
end

def teardown
Expand Down Expand Up @@ -232,6 +233,21 @@ def test_pre_input_hook
assert_equal(l, Reline.pre_input_hook)
end

def test_rprompt
assert_equal(nil, Reline.rprompt)

Reline.rprompt = "[Time]"
assert_equal("[Time]", Reline.rprompt)
assert_equal(get_reline_encoding, Reline.rprompt.encoding)

Reline.rprompt = "[Time]".encode(Encoding::ASCII)
assert_equal("[Time]", Reline.rprompt)
assert_equal(get_reline_encoding, Reline.rprompt.encoding)

Reline.rprompt = nil
assert_equal(nil, Reline.rprompt)
end

def test_dig_perfect_match_proc
assert_equal(nil, Reline.dig_perfect_match_proc)

Expand Down
3 changes: 3 additions & 0 deletions test/reline/yamatanooroti/multiline_repl
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ opt.on('--autocomplete-width-long') {
}.select{ |c| c.start_with?(target) }
}
}
opt.on('--rprompt VAL') { |v|
Reline.rprompt = v
}
opt.parse!(ARGV)

begin
Expand Down
29 changes: 29 additions & 0 deletions test/reline/yamatanooroti/test_rendering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,35 @@ def test_prompt
close
end

def test_rprompt
start_terminal(5, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --rprompt [RPROMPT]}, startup_message: 'Multiline REPL.')
assert_screen(<<~EOC)
Multiline REPL.
prompt> [RPROMPT]
EOC
close
end

def test_rprompt_with_input
start_terminal(5, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --rprompt [RPROMPT]}, startup_message: 'Multiline REPL.')
write("hello")
assert_screen(<<~EOC)
Multiline REPL.
prompt> hello [RPROMPT]
EOC
close
end

def test_rprompt_hides_when_input_reaches_rprompt
start_terminal(5, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --rprompt [RPROMPT]}, startup_message: 'Multiline REPL.')
write("a" * 30)
assert_screen(<<~EOC)
Multiline REPL.
prompt> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
EOC
close
end

def test_mode_string_emacs
write_inputrc <<~LINES
set show-mode-in-prompt on
Expand Down