Skip to content

Commit 92f5aa5

Browse files
IanButterworthKristofferC
authored andcommitted
Switch to Pkg mode prompt immediately and load Pkg in the background (#54594)
Because Pkg is now a pkgimage it can load slowly on slower machines, which is a bit frustrating in the first repl switch. This makes the repl immediately switch to a dummy prompt that looks like Pkg mode to allow the user to keep typing while Pkg loads. During which the keymap is disabled. It works best if julia has >1 thread, otherwise typing stalls during Pkg load. If Pkg takes longer to load than the user to type the command and press return, then the UX isn't great as it won't do anything. https://github.com/JuliaLang/julia/assets/1694067/1bf17323-441a-4db2-8a3b-4d571eac622f (cherry picked from commit 13635e1)
1 parent c0f71e7 commit 92f5aa5

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

stdlib/REPL/src/REPL.jl

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,9 +1041,6 @@ setup_interface(
10411041
extra_repl_keymap::Any = repl.options.extra_keymap
10421042
) = setup_interface(repl, hascolor, extra_repl_keymap)
10431043

1044-
# we have to grab this after Pkg is loaded so cache it
1045-
pkg_mode::Union{Nothing,LineEdit.Prompt} = nothing
1046-
10471044
# This non keyword method can be precompiled which is important
10481045
function setup_interface(
10491046
repl::LineEditREPL,
@@ -1189,11 +1186,17 @@ function setup_interface(
11891186
end,
11901187
']' => function (s::MIState,o...)
11911188
if isempty(s) || position(LineEdit.buffer(s)) == 0
1192-
global pkg_mode
1193-
if pkg_mode === nothing
1189+
# print a dummy pkg prompt while Pkg loads
1190+
LineEdit.clear_line(LineEdit.terminal(s))
1191+
# use 6 .'s here because its the same width as the most likely `@v1.xx` env name
1192+
print(LineEdit.terminal(s), styled"{blue,bold:({gray:......}) pkg> }")
1193+
pkg_mode = nothing
1194+
transition_finished = false
1195+
iolock = Base.ReentrantLock() # to avoid race between tasks reading stdin & input buffer
1196+
# spawn Pkg load to avoid blocking typing during loading. Typing will block if only 1 thread
1197+
t_replswitch = Threads.@spawn begin
11941198
pkgid = Base.PkgId(Base.UUID("44cfe95a-1eb2-52ea-b672-e2afdf69b78f"), "Pkg")
11951199
REPLExt = Base.require_stdlib(pkgid, "REPLExt")
1196-
pkg_mode = nothing
11971200
if REPLExt isa Module && isdefined(REPLExt, :PkgCompletionProvider)
11981201
for mode in repl.interface.modes
11991202
if mode isa LineEdit.Prompt && mode.complete isa REPLExt.PkgCompletionProvider
@@ -1202,16 +1205,31 @@ function setup_interface(
12021205
end
12031206
end
12041207
end
1208+
if pkg_mode !== nothing
1209+
@lock iolock begin
1210+
buf = copy(LineEdit.buffer(s))
1211+
transition(s, pkg_mode) do
1212+
LineEdit.state(s, pkg_mode).input_buffer = buf
1213+
end
1214+
if !isempty(s)
1215+
@invokelatest(LineEdit.check_for_hint(s)) && @invokelatest(LineEdit.refresh_line(s))
1216+
end
1217+
transition_finished = true
1218+
end
1219+
end
12051220
end
1206-
if pkg_mode !== nothing
1207-
buf = copy(LineEdit.buffer(s))
1208-
transition(s, pkg_mode) do
1209-
LineEdit.state(s, pkg_mode).input_buffer = buf
1221+
Base.errormonitor(t_replswitch)
1222+
# while loading just accept all keys, no keymap functionality
1223+
while !istaskdone(t_replswitch)
1224+
# wait but only take if task is still running
1225+
peek(stdin, Char)
1226+
@lock iolock begin
1227+
transition_finished || edit_insert(s, read(stdin, Char))
12101228
end
1211-
return
12121229
end
1230+
else
1231+
edit_insert(s, ']')
12131232
end
1214-
edit_insert(s, ']')
12151233
end,
12161234

12171235
# Bracketed Paste Mode

stdlib/REPL/src/precompile.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,14 @@ 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}})
232+
223233
end # Precompile

0 commit comments

Comments
 (0)