Skip to content

Commit

Permalink
allow a function instead of a string as Prompt.prompt (JuliaLang#22809)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed Jul 27, 2017
1 parent d6e1e86 commit 85a2555
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 18 deletions.
27 changes: 16 additions & 11 deletions base/repl/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ struct ModalInterface <: TextInterface
end

mutable struct Prompt <: TextInterface
prompt::String
# A string or function to be printed as the prompt.
prompt::Union{String,Function}
# A string or function to be printed before the prompt. May not change the length of the prompt.
# This may be used for changing the color, issuing other terminal escape codes, etc.
prompt_prefix::Union{String,Function}
Expand All @@ -34,7 +35,7 @@ mutable struct Prompt <: TextInterface
sticky::Bool
end

show(io::IO, x::Prompt) = show(io, string("Prompt(\"", x.prompt, "\",...)"))
show(io::IO, x::Prompt) = show(io, string("Prompt(\"", prompt_string(x.prompt), "\",...)"))

mutable struct MIState
interface::ModalInterface
Expand Down Expand Up @@ -182,8 +183,10 @@ function _clear_input_area(terminal, state::InputAreaState)
clear_line(terminal)
end

prompt_string(s::PromptState) = s.p.prompt
prompt_string(s::PromptState) = prompt_string(s.p)
prompt_string(p::Prompt) = prompt_string(p.prompt)
prompt_string(s::AbstractString) = s
prompt_string(f::Function) = Base.invokelatest(f)

refresh_multi_line(s::ModeState) = refresh_multi_line(terminal(s), s)
refresh_multi_line(termbuf::TerminalBuffer, s::ModeState) = refresh_multi_line(termbuf, terminal(s), s)
Expand Down Expand Up @@ -271,7 +274,7 @@ end


# Edit functionality
is_non_word_char(c) = c in " \t\n\"\\'`@\$><=:;|&{}()[].,+-*/?%^~"
is_non_word_char(c) = c in """ \t\n\"\\'`@\$><=:;|&{}()[].,+-*/?%^~"""

function reset_key_repeats(f::Function, s::MIState)
key_repeats_sav = s.key_repeats
Expand Down Expand Up @@ -454,7 +457,7 @@ function edit_insert(s::PromptState, c)
end
str = string(c)
edit_insert(buf, str)
offset = s.ias.curs_row == 1 ? sizeof(s.p.prompt) : s.indent
offset = s.ias.curs_row == 1 ? sizeof(prompt_string(s.p.prompt)) : s.indent
if !('\n' in str) && eof(buf) &&
((line_size() + offset + sizeof(str) - 1) < width(terminal(s)))
# Avoid full update when appending characters to the end
Expand Down Expand Up @@ -625,15 +628,15 @@ default_enter_cb(_) = true

write_prompt(terminal, s::PromptState) = write_prompt(terminal, s.p)
function write_prompt(terminal, p::Prompt)
prefix = isa(p.prompt_prefix,Function) ? eval(Expr(:call, p.prompt_prefix)) : p.prompt_prefix
suffix = isa(p.prompt_suffix,Function) ? eval(Expr(:call, p.prompt_suffix)) : p.prompt_suffix
prefix = prompt_string(p.prompt_prefix)
suffix = prompt_string(p.prompt_suffix)
write(terminal, prefix)
write(terminal, Base.text_colors[:bold])
write(terminal, p.prompt)
write(terminal, prompt_string(p.prompt))
write(terminal, Base.text_colors[:normal])
write(terminal, suffix)
end
write_prompt(terminal, s::String) = write(terminal, s)
write_prompt(terminal, s::Union{AbstractString,Function}) = write(terminal, prompt_string(s))

### Keymap Support

Expand Down Expand Up @@ -1064,7 +1067,7 @@ PrefixHistoryPrompt(hp::T, parent_prompt) where T<:HistoryProvider = PrefixHisto
init_state(terminal, p::PrefixHistoryPrompt) = PrefixSearchState(terminal, p, "", IOBuffer())

write_prompt(terminal, s::PrefixSearchState) = write_prompt(terminal, s.histprompt.parent_prompt)
prompt_string(s::PrefixSearchState) = s.histprompt.parent_prompt.prompt
prompt_string(s::PrefixSearchState) = prompt_string(s.histprompt.parent_prompt.prompt)

terminal(s::PrefixSearchState) = s.terminal

Expand Down Expand Up @@ -1563,7 +1566,9 @@ end

run_interface(::Prompt) = nothing

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

function init_state(terminal, m::ModalInterface)
s = MIState(m, m.modes[1], false, Dict{Any,Any}())
Expand Down
15 changes: 8 additions & 7 deletions test/repl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,9 @@ function buffercontents(buf::IOBuffer)
c
end

function AddCustomMode(repl)
function AddCustomMode(repl, prompt)
# Custom REPL mode tests
foobar_mode = LineEdit.Prompt("TestΠ";
foobar_mode = LineEdit.Prompt(prompt;
prompt_prefix="\e[38;5;166m",
prompt_suffix=Base.text_colors[:white],
on_enter = s->true,
Expand Down Expand Up @@ -289,7 +289,7 @@ fakehistory = """
"""

# Test various history related issues
begin
for prompt = ["TestΠ", () -> randstring(rand(1:10))]
stdin_write, stdout_read, stdout_read, repl = fake_repl()
# In the future if we want we can add a test that the right object
# gets displayed by intercepting the display
Expand Down Expand Up @@ -458,7 +458,7 @@ begin

# Test that new modes can be dynamically added to the REPL and will
# integrate nicely
foobar_mode, custom_histp = AddCustomMode(repl)
foobar_mode, custom_histp = AddCustomMode(repl, prompt)

# ^R l, should now find `ls` in foobar mode
LineEdit.enter_search(s, histp, true)
Expand Down Expand Up @@ -733,14 +733,15 @@ const altkeys = [Dict{Any,Any}("\e[A" => (s,o...)->(LineEdit.edit_move_up(s) ||


if !Sys.iswindows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER
for keys = [altkeys, merge(altkeys...)]
for keys = [altkeys, merge(altkeys...)],
altprompt = ["julia-$(VERSION.major).$(VERSION.minor)> ",
() -> "julia-$(Base.GIT_VERSION_INFO.commit_short)"]
histfile = tempname()
try
stdin_write, stdout_read, stderr_read, repl = fake_repl()

repl.specialdisplay = Base.REPL.REPLDisplay(repl)
repl.history_file = true
altprompt = "julia-$(VERSION.major).$(VERSION.minor)> "
withenv("JULIA_HISTORY" => histfile) do
repl.interface = REPL.setup_interface(repl, extra_repl_keymap = altkeys)
end
Expand All @@ -767,7 +768,7 @@ if !Sys.iswindows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER

# Check that the correct prompt was displayed
output = readuntil(stdout_read, "1 * 1;")
@test !isempty(search(output, altprompt))
@test !isempty(search(output, LineEdit.prompt_string(altprompt)))
@test isempty(search(output, "julia> "))

# Check the history file
Expand Down

0 comments on commit 85a2555

Please sign in to comment.