From 5e21715018c0aa63c79c66711f4b7fdf56148ec0 Mon Sep 17 00:00:00 2001 From: Lionel Zoubritzky Date: Fri, 8 Jul 2022 00:00:13 +0200 Subject: [PATCH] Fix layout of REPL completions with newlines Co-authored-by: Jameson Nash --- stdlib/REPL/src/LineEdit.jl | 25 +++++++++++++++---------- stdlib/REPL/test/lineedit.jl | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index d7d929570df6e..42046ed2b2e1b 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -322,23 +322,28 @@ end # Show available completions function show_completions(s::PromptState, completions::Vector{String}) - colmax = maximum(map(length, completions)) - num_cols = max(div(width(terminal(s)), colmax+2), 1) - entries_per_col, r = divrem(length(completions), num_cols) - entries_per_col += r != 0 # skip any lines of input after the cursor cmove_down(terminal(s), input_string_newlines_aftercursor(s)) println(terminal(s)) - for row = 1:entries_per_col - for col = 0:num_cols - idx = row + col*entries_per_col - if idx <= length(completions) - cmove_col(terminal(s), (colmax+2)*col+1) + if any(Base.Fix1(occursin, '\n'), completions) + foreach(Base.Fix1(println, terminal(s)), completions) + else + colmax = 2 + maximum(length, completions; init=1) # n.b. length >= textwidth + num_cols = max(div(width(terminal(s)), colmax), 1) + n = length(completions) + entries_per_col = cld(n, num_cols) + idx = 0 + for _ in 1:entries_per_col + for col = 0:(num_cols-1) + idx += 1 + idx > n && break + cmove_col(terminal(s), colmax*col+1) print(terminal(s), completions[idx]) end + println(terminal(s)) end - println(terminal(s)) end + # make space for the prompt for i = 1:input_string_newlines(s) println(terminal(s)) diff --git a/stdlib/REPL/test/lineedit.jl b/stdlib/REPL/test/lineedit.jl index 4b9ba05b2b1e6..90badda189348 100644 --- a/stdlib/REPL/test/lineedit.jl +++ b/stdlib/REPL/test/lineedit.jl @@ -906,3 +906,17 @@ end @test get_last_word("a[b[]]") == "b" @test get_last_word("a[]") == "a[]" end + +@testset "issue #45836" begin + term = FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer()) + promptstate = REPL.LineEdit.init_state(term, REPL.LineEdit.mode(new_state())) + strings = ["abcdef", "123456", "ijklmn"] + REPL.LineEdit.show_completions(promptstate, strings) + completion = String(take!(term.out_stream)) + @test completion == "\033[0B\n\rabcdef\r\033[8C123456\r\033[16Cijklmn\n" + strings2 = ["abcdef", "123456\nijklmn"] + promptstate = REPL.LineEdit.init_state(term, REPL.LineEdit.mode(new_state())) + REPL.LineEdit.show_completions(promptstate, strings2) + completion2 = String(take!(term.out_stream)) + @test completion2 == "\033[0B\nabcdef\n123456\nijklmn\n" +end