Skip to content

Commit

Permalink
fix indentation for varying-width function prompt
Browse files Browse the repository at this point in the history
Since #22809 a function can be used as the prompt, but the indentation
of non-prompt lines was still determined by the first value of the prompt
(usually "julia> "). Now, the indentation is determined by the currently
printed prompt, which can vary from one keypress to the next.
  • Loading branch information
rfourquet committed Aug 9, 2017
1 parent 44c53f4 commit b297116
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 7 deletions.
22 changes: 15 additions & 7 deletions base/repl/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ mutable struct PromptState <: ModeState
p::Prompt
input_buffer::IOBuffer
ias::InputAreaState
# indentation of lines which do not include the prompt
# if negative, the width of the prompt is used
indent::Int
end

Expand Down Expand Up @@ -201,11 +203,9 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf
buf_pos = position(buf)
line_pos = buf_pos
# Write out the prompt string
write_prompt(termbuf, prompt)
prompt = prompt_string(prompt)
lindent = write_prompt(termbuf, prompt)
# Count the '\n' at the end of the line if the terminal emulator does (specific to DOS cmd prompt)
miscountnl = @static Sys.iswindows() ? (isa(Terminals.pipe_reader(terminal), Base.TTY) && !Base.ispty(Terminals.pipe_reader(terminal))) : false
lindent = strwidth(prompt)

# Now go through the buffer line by line
seek(buf, 0)
Expand Down Expand Up @@ -244,7 +244,7 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf
end
end
cur_row += div(max(lindent + llength + miscountnl - 1, 0), cols)
lindent = indent
lindent = indent < 0 ? lindent : indent
end
seek(buf, buf_pos)

Expand Down Expand Up @@ -627,16 +627,24 @@ default_completion_cb(::IOBuffer) = []
default_enter_cb(_) = true

write_prompt(terminal, s::PromptState) = write_prompt(terminal, s.p)

function write_prompt(terminal, p::Prompt)
prefix = prompt_string(p.prompt_prefix)
suffix = prompt_string(p.prompt_suffix)
write(terminal, prefix)
write(terminal, Base.text_colors[:bold])
write(terminal, prompt_string(p.prompt))
width = write_prompt(terminal, p.prompt)
write(terminal, Base.text_colors[:normal])
write(terminal, suffix)
width
end

# returns the width of the written prompt
function write_prompt(terminal, s::Union{AbstractString,Function})
promptstr = prompt_string(s)
write(terminal, promptstr)
strwidth(promptstr)
end
write_prompt(terminal, s::Union{AbstractString,Function}) = write(terminal, prompt_string(s))

### Keymap Support

Expand Down Expand Up @@ -1568,7 +1576,7 @@ run_interface(::Prompt) = nothing

init_state(terminal, prompt::Prompt) =
PromptState(terminal, prompt, IOBuffer(), InputAreaState(1, 1),
#=indent(spaces)=# strwidth(prompt_string(prompt)))
#=indent(spaces)=# -1)

function init_state(terminal, m::ModalInterface)
s = MIState(m, m.modes[1], false, Dict{Any,Any}())
Expand Down
26 changes: 26 additions & 0 deletions test/lineedit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,29 @@ let
Base.LineEdit.InputAreaState(0,0), "julia> ", indent = 7)
@test s == Base.LineEdit.InputAreaState(3,1)
end

@testset "function prompt indentation" begin
term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer(), false)
# default prompt: PromptState.indent should not be to a final fixed value
s = LineEdit.init_state(term, ModalInterface([Prompt("julia> ")]))
ps::LineEdit.PromptState = s.mode_state[s.current_mode]
@test ps.indent == -1
# the prompt is modified afterwards to a function
ps.p.prompt = let i = 0
() -> ["Julia is Fun! > ", "> "][mod1(i+=1, 2)] # lengths are 16 and 2
end
buf = LineEdit.buffer(ps)
write(buf, "begin\n julia = :fun\nend")
outbuf = IOBuffer()
termbuf = Base.Terminals.TerminalBuffer(outbuf)
LineEdit.refresh_multi_line(termbuf, term, ps)
@test String(take!(outbuf)) ==
"\r\e[0K\e[1mJulia is Fun! > \e[0m\r\e[16Cbegin\n" *
"\r\e[16C julia = :fun\n" *
"\r\e[16Cend\r\e[19C"
LineEdit.refresh_multi_line(termbuf, term, ps)
@test String(take!(copy(outbuf))) ==
"\r\e[0K\e[1A\r\e[0K\e[1A\r\e[0K\e[1m> \e[0m\r\e[2Cbegin\n" *
"\r\e[2C julia = :fun\n" *
"\r\e[2Cend\r\e[5C"
end

0 comments on commit b297116

Please sign in to comment.