Skip to content

Commit

Permalink
REPL: offer to try to install package if not found
Browse files Browse the repository at this point in the history
  • Loading branch information
IanButterworth committed Apr 24, 2021
1 parent e5da821 commit ba8e166
Showing 1 changed file with 36 additions and 1 deletion.
37 changes: 36 additions & 1 deletion stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -776,9 +776,44 @@ find_hist_file() = get(ENV, "JULIA_HISTORY",

backend(r::AbstractREPL) = r.backendref

# Allows an external package to add hooks into the code loading
# return true if all packages could be installed, false if not
# to e.g. install packages on demand
const install_packages_hooks = Any[]

function eval_with_backend(ast, backend::REPLBackendRef)
mods_to_be_loaded = modules_to_be_loaded(ast)
mods_not_found = list_unfindable_modules(mods_to_be_loaded)
!isempty(mods_not_found) && pass_to_install_package_hooks(mods_not_found)
put!(backend.repl_channel, (ast, 1))
return take!(backend.response_channel) # (val, iserr)
resp = take!(backend.response_channel) # (val, iserr)
return resp
end

function modules_to_be_loaded(ast, mods = Symbol[])
if ast.head in [:using, :import]
for arg in ast.args
if first(arg.args) isa Symbol # i.e. `Foo`
push!(mods, first(arg.args))
else # i.e. `Foo: Bar`
push!(mods, first(first(arg.args).args))
end
end
end
for arg in ast.args
arg isa Expr && modules_to_be_loaded(arg, mods)
end
return mods
end

function list_unfindable_modules(mods)
filter(mod -> isnothing(Base.identify_package(String(mod))), mods)
end

function pass_to_install_package_hooks(mods)
for f in install_packages_hooks
f(mods) && return
end
end

function respond(f, repl, main; pass_empty::Bool = false, suppress_on_semicolon::Bool = true)
Expand Down

0 comments on commit ba8e166

Please sign in to comment.