Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to Pkg mode prompt immediately and load Pkg in the background #54594

Merged
merged 7 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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