Skip to content

Commit e6dd695

Browse files
IanButterworthKristofferC
authored and
KristofferC
committed
REPL: improve prompt! async function handler (#54760)
(cherry picked from commit e7893a1)
1 parent cfe9c49 commit e6dd695

File tree

3 files changed

+42
-43
lines changed

3 files changed

+42
-43
lines changed

stdlib/REPL/src/LineEdit.jl

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ mutable struct MIState
7676
key_repeats::Int
7777
last_action::Symbol
7878
current_action::Symbol
79-
async_channel::Channel
79+
async_channel::Channel{Function}
8080
end
8181

82-
MIState(i, mod, c, a, m) = MIState(i, mod, c, a, m, String[], 0, Char[], 0, :none, :none, Channel())
82+
MIState(i, mod, c, a, m) = MIState(i, mod, c, a, m, String[], 0, Char[], 0, :none, :none, Channel{Function}())
8383

8484
const BufferLike = Union{MIState,ModeState,IOBuffer}
8585
const State = Union{MIState,ModeState}
@@ -2829,40 +2829,45 @@ function prompt!(term::TextTerminal, prompt::ModalInterface, s::MIState = init_s
28292829
try
28302830
activate(prompt, s, term, term)
28312831
old_state = mode(s)
2832+
l = Base.ReentrantLock()
2833+
t = @async while true
2834+
fcn = take!(s.async_channel)
2835+
status = @lock l fcn(s)
2836+
status (:ok, :ignore) || break
2837+
end
2838+
Base.errormonitor(t)
28322839
while true
28332840
kmap = keymap(s, prompt)
2834-
waitany((
2835-
@async(eof(term) || peek(term, Char)),
2836-
@async(wait(s.async_channel)),
2837-
), throw=true)
2838-
fcn = isempty(s.async_channel) ? match_input(kmap, s) : take!(s.async_channel)
2839-
kdata = keymap_data(s, prompt)
2840-
s.current_action = :unknown # if the to-be-run action doesn't update this field,
2841-
# :unknown will be recorded in the last_action field
2842-
local status
2843-
# errors in keymaps shouldn't cause the REPL to fail, so wrap in a
2844-
# try/catch block
2845-
try
2846-
status = fcn(s, kdata)
2847-
catch e
2848-
@error "Error in the keymap" exception=e,catch_backtrace()
2849-
# try to cleanup and get `s` back to its original state before returning
2850-
transition(s, :reset)
2851-
transition(s, old_state)
2852-
status = :done
2853-
end
2854-
status !== :ignore && (s.last_action = s.current_action)
2855-
if status === :abort
2856-
s.aborted = true
2857-
return buffer(s), false, false
2858-
elseif status === :done
2859-
return buffer(s), true, false
2860-
elseif status === :suspend
2861-
if Sys.isunix()
2862-
return buffer(s), true, true
2841+
fcn = match_input(kmap, s)
2842+
@lock l begin
2843+
kdata = keymap_data(s, prompt)
2844+
s.current_action = :unknown # if the to-be-run action doesn't update this field,
2845+
# :unknown will be recorded in the last_action field
2846+
local status
2847+
# errors in keymaps shouldn't cause the REPL to fail, so wrap in a
2848+
# try/catch block
2849+
try
2850+
status = fcn(s, kdata)
2851+
catch e
2852+
@error "Error in the keymap" exception=e,catch_backtrace()
2853+
# try to cleanup and get `s` back to its original state before returning
2854+
transition(s, :reset)
2855+
transition(s, old_state)
2856+
status = :done
2857+
end
2858+
status !== :ignore && (s.last_action = s.current_action)
2859+
if status === :abort
2860+
s.aborted = true
2861+
return buffer(s), false, false
2862+
elseif status === :done
2863+
return buffer(s), true, false
2864+
elseif status === :suspend
2865+
if Sys.isunix()
2866+
return buffer(s), true, true
2867+
end
2868+
else
2869+
@assert status (:ok, :ignore)
28632870
end
2864-
else
2865-
@assert status (:ok, :ignore)
28662871
end
28672872
end
28682873
finally

stdlib/REPL/src/REPL.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ function setup_interface(
12421242
REPLExt = load_pkg()
12431243
if REPLExt isa Module && isdefined(REPLExt, :PkgCompletionProvider)
12441244
put!(s.async_channel,
1245-
function (s::MIState, _)
1245+
function (s::MIState)
12461246
LineEdit.mode(s) === dummy_pkg_mode || return :ok
12471247
for mode in repl.interface.modes
12481248
if mode isa LineEdit.Prompt && mode.complete isa REPLExt.PkgCompletionProvider

stdlib/REPL/src/precompile.jl

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,8 @@ end
220220
generate_precompile_statements()
221221

222222
precompile(Tuple{typeof(getproperty), REPL.REPLBackend, Symbol})
223-
224-
# Helps Pkg repl mode switch
225-
precompile(Tuple{typeof(REPL.Terminals.clear_line), REPL.Terminals.TTYTerminal})
226-
precompile(Tuple{typeof(Base.print), REPL.Terminals.TTYTerminal, Base.AnnotatedString{String}})
227-
precompile(Tuple{typeof(Base.peek), Base.TTY, Type{Char}})
228-
precompile(Tuple{typeof(Base.similar), Array{String, 1}})
229-
precompile(Tuple{typeof(Base.Iterators.enumerate), Array{String, 1}})
230-
precompile(Tuple{typeof(Base.setindex!), Array{String, 1}, String, Int64})
231-
precompile(Tuple{typeof(Base.convert), Type{Base.Dict{String, Union{Array{String, 1}, String}}}, Base.Dict{String, Any}})
223+
precompile(Tuple{typeof(Base.take!), Base.Channel{Function}})
224+
precompile(Tuple{typeof(Base.put!), Base.Channel{Function}, Function})
225+
precompile(Tuple{typeof(Core.kwcall), NamedTuple{names, T} where T<:Tuple where names, typeof(REPL.LineEdit.complete_line), REPL.LineEdit.EmptyCompletionProvider, Any})
232226

233227
end # Precompile

0 commit comments

Comments
 (0)