Skip to content

Commit

Permalink
Switch to Pkg mode prompt immediately and load Pkg in the background (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
IanButterworth committed Jun 4, 2024
1 parent 4e211eb commit 13635e1
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 12 deletions.
42 changes: 30 additions & 12 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1080,9 +1080,6 @@ setup_interface(
extra_repl_keymap::Any = repl.options.extra_keymap
) = setup_interface(repl, hascolor, extra_repl_keymap)

# we have to grab this after Pkg is loaded so cache it
pkg_mode::Union{Nothing,LineEdit.Prompt} = nothing

# This non keyword method can be precompiled which is important
function setup_interface(
repl::LineEditREPL,
Expand Down Expand Up @@ -1228,11 +1225,17 @@ function setup_interface(
end,
']' => function (s::MIState,o...)
if isempty(s) || position(LineEdit.buffer(s)) == 0
global pkg_mode
if pkg_mode === nothing
# print a dummy pkg prompt while Pkg loads
LineEdit.clear_line(LineEdit.terminal(s))
# use 6 .'s here because its the same width as the most likely `@v1.xx` env name
print(LineEdit.terminal(s), styled"{blue,bold:({gray:......}) pkg> }")
pkg_mode = nothing
transition_finished = false
iolock = Base.ReentrantLock() # to avoid race between tasks reading stdin & input buffer
# spawn Pkg load to avoid blocking typing during loading. Typing will block if only 1 thread
t_replswitch = Threads.@spawn begin
pkgid = Base.PkgId(Base.UUID("44cfe95a-1eb2-52ea-b672-e2afdf69b78f"), "Pkg")
REPLExt = Base.require_stdlib(pkgid, "REPLExt")
pkg_mode = nothing
if REPLExt isa Module && isdefined(REPLExt, :PkgCompletionProvider)
for mode in repl.interface.modes
if mode isa LineEdit.Prompt && mode.complete isa REPLExt.PkgCompletionProvider
Expand All @@ -1241,16 +1244,31 @@ function setup_interface(
end
end
end
if pkg_mode !== nothing
@lock iolock begin
buf = copy(LineEdit.buffer(s))
transition(s, pkg_mode) do
LineEdit.state(s, pkg_mode).input_buffer = buf
end
if !isempty(s)
@invokelatest(LineEdit.check_for_hint(s)) && @invokelatest(LineEdit.refresh_line(s))
end
transition_finished = true
end
end
end
if pkg_mode !== nothing
buf = copy(LineEdit.buffer(s))
transition(s, pkg_mode) do
LineEdit.state(s, pkg_mode).input_buffer = buf
Base.errormonitor(t_replswitch)
# while loading just accept all keys, no keymap functionality
while !istaskdone(t_replswitch)
# wait but only take if task is still running
peek(stdin, Char)
@lock iolock begin
transition_finished || edit_insert(s, read(stdin, Char))
end
return
end
else
edit_insert(s, ']')
end
edit_insert(s, ']')
end,

# Bracketed Paste Mode
Expand Down
10 changes: 10 additions & 0 deletions stdlib/REPL/src/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,14 @@ end
generate_precompile_statements()

precompile(Tuple{typeof(getproperty), REPL.REPLBackend, Symbol})

# Helps Pkg repl mode switch
precompile(Tuple{typeof(REPL.Terminals.clear_line), REPL.Terminals.TTYTerminal})
precompile(Tuple{typeof(Base.print), REPL.Terminals.TTYTerminal, Base.AnnotatedString{String}})
precompile(Tuple{typeof(Base.peek), Base.TTY, Type{Char}})
precompile(Tuple{typeof(Base.similar), Array{String, 1}})
precompile(Tuple{typeof(Base.Iterators.enumerate), Array{String, 1}})
precompile(Tuple{typeof(Base.setindex!), Array{String, 1}, String, Int64})
precompile(Tuple{typeof(Base.convert), Type{Base.Dict{String, Union{Array{String, 1}, String}}}, Base.Dict{String, Any}})

end # Precompile

0 comments on commit 13635e1

Please sign in to comment.