Skip to content

Commit

Permalink
add REPL hook to prompt to install missing packages, if available in …
Browse files Browse the repository at this point in the history
…registry
  • Loading branch information
IanButterworth committed May 2, 2021
1 parent e5f9e61 commit a6dee3c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Pkg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ function __init__()
end
end
end
push!(empty!(REPL.install_packages_hooks), REPLMode.try_prompt_pkg_add)
OFFLINE_MODE[] = get(ENV, "JULIA_PKG_OFFLINE", nothing) == "true"
return nothing
end
Expand Down Expand Up @@ -671,6 +672,7 @@ const precompile_script = """
Pkg.add("TestPkg")
Pkg.develop(Pkg.PackageSpec(path="TestPkg.jl"))
Pkg.add(Pkg.PackageSpec(path="TestPkg.jl/"))
Pkg.REPLMode.try_prompt_pkg_add(Symbol[:notapackage])
] add Te\t\t$CTRL_C
] st
$CTRL_C
Expand Down
41 changes: 41 additions & 0 deletions src/REPLMode/REPLMode.jl
Original file line number Diff line number Diff line change
Expand Up @@ -650,4 +650,45 @@ end

const help = gen_help()

function try_prompt_pkg_add(pkgs::Vector{Symbol})
ctx = Context()
available_uuids = [Types.registered_uuids(ctx.registries, String(pkg)) for pkg in pkgs] # vector of vectors
available_pkgs = pkgs[isempty.(available_uuids) .== false]
isempty(available_pkgs) && return false
resp = try
plural1 = length(pkgs) == 1 ? "" : "s"
plural2 = length(available_pkgs) == 1 ? "a package" : "packages"
plural3 = length(available_pkgs) == 1 ? "is" : "are"
plural4 = length(available_pkgs) == 1 ? "" : "s"
missing_pkg_list = length(pkgs) == 1 ? String(pkgs[1]) : "[$(join(pkgs, ", "))]"
available_pkg_list = length(available_pkgs) == 1 ? String(available_pkgs[1]) : "[$(join(available_pkgs, ", "))]"
printstyled(ctx.io, ""; color=:green)
println(ctx.io, "Package$(plural1) $(missing_pkg_list) not found,",
" but $(plural2) named $(available_pkg_list) $(plural3) available from a registry.")
printstyled(ctx.io, ""; color=:green)
println(ctx.io, "Install package$(plural4)?")
printstyled(ctx.io, ""; color=:green)
print(ctx.io, " ")
printstyled(ctx.io, REPLMode.promptf(); color=:blue)
println(ctx.io, "add ", join(available_pkgs, ' '))
printstyled(ctx.io, ""; color=:green)
Base.prompt(stdin, ctx.io, "(y/n)", default = "n")
catch err
if err isa InterruptException
println(ctx.io)
return false
end
rethrow()
end
if lowercase(resp) in ["y", "yes"]
Pkg.add(string.(available_pkgs))
if length(available_pkgs) < length(pkgs)
return false # declare that some pkgs couldn't be installed
else
return true
end
end
return false
end

end #module
5 changes: 5 additions & 0 deletions test/repl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -667,4 +667,9 @@ end
@inferred Pkg.REPLMode.CompoundSpecs(Pair{String,Vector{Pkg.REPLMode.CommandDeclaration}}[])
end

@testset "REPL missing package install hook" begin
@test Pkg.REPLMode.try_prompt_pkg_add(Symbol[:notapackage]) == false
# cannot test installation of findable packages given requires user input to stdin on the prompt
end

end # module

0 comments on commit a6dee3c

Please sign in to comment.