Skip to content

Commit d5d5ffa

Browse files
populate the dummy Pkg prompt properly
use Base.TOML.parse
1 parent d0f165f commit d5d5ffa

File tree

2 files changed

+124
-14
lines changed

2 files changed

+124
-14
lines changed

stdlib/REPL/src/Pkg_beforeload.jl

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
## Pkg stuff needed before Pkg has loaded
2+
3+
const Pkg_pkgid = Base.PkgId(Base.UUID("44cfe95a-1eb2-52ea-b672-e2afdf69b78f"), "Pkg")
4+
const Pkg_REPLExt_pkgid = Base.PkgId(Base.UUID("ceef7b17-42e7-5b1c-81d4-4cc4a2494ccf"), "REPLExt")
5+
6+
function load_pkg()
7+
@lock Base.require_lock begin
8+
REPLExt = Base.require_stdlib(Pkg_pkgid, "REPLExt")
9+
# require_stdlib does not guarantee that the `__init__` of the package is done when loading is done async
10+
# but we need to wait for the repl mode to be set up
11+
lock = get(Base.package_locks, Pkg_REPLExt_pkgid.uuid, nothing)
12+
lock !== nothing && wait(lock[2])
13+
return REPLExt
14+
end
15+
end
16+
17+
## Below here copied/tweaked from Pkg Types.jl so that the dummy Pkg prompt
18+
# can populate the env correctly before Pkg loads
19+
20+
function safe_realpath(path)
21+
isempty(path) && return path
22+
if ispath(path)
23+
try
24+
return realpath(path)
25+
catch
26+
return path
27+
end
28+
end
29+
a, b = splitdir(path)
30+
return joinpath(safe_realpath(a), b)
31+
end
32+
33+
function find_project_file(env::Union{Nothing,String}=nothing)
34+
project_file = nothing
35+
if env isa Nothing
36+
project_file = Base.active_project()
37+
project_file === nothing && return nothing # in the Pkg version these are pkgerrors
38+
elseif startswith(env, '@')
39+
project_file = Base.load_path_expand(env)
40+
project_file === nothing && return nothing
41+
elseif env isa String
42+
if isdir(env)
43+
isempty(readdir(env)) || return nothing
44+
project_file = joinpath(env, Base.project_names[end])
45+
else
46+
project_file = endswith(env, ".toml") ? abspath(env) :
47+
abspath(env, Base.project_names[end])
48+
end
49+
end
50+
@assert project_file isa String &&
51+
(isfile(project_file) || !ispath(project_file) ||
52+
isdir(project_file) && isempty(readdir(project_file)))
53+
return safe_realpath(project_file)
54+
end
55+
56+
function find_root_base_project(start_project::String)
57+
project_file = start_project
58+
while true
59+
base_project_file = Base.base_project(project_file)
60+
base_project_file === nothing && return project_file
61+
project_file = base_project_file
62+
end
63+
end
64+
65+
function relative_project_path(project_file::String, path::String)
66+
# compute path relative the project
67+
# realpath needed to expand symlinks before taking the relative path
68+
return relpath(safe_realpath(abspath(path)), safe_realpath(dirname(project_file)))
69+
end
70+
71+
function projname(project_file::String)
72+
p = Base.TOML.Parser()
73+
Base.TOML.reinit!(p, read(project_file, String); filepath=project_file)
74+
proj = Base.TOML.parse(p)
75+
name = get(proj, "name", nothing)
76+
if name === nothing
77+
name = basename(dirname(project_file))
78+
end
79+
for depot in Base.DEPOT_PATH
80+
envdir = joinpath(depot, "environments")
81+
if startswith(abspath(project_file), abspath(envdir))
82+
return "@" * name
83+
end
84+
end
85+
return name
86+
end
87+
88+
prev_project_file = nothing
89+
prev_project_timestamp = nothing
90+
prev_prefix = ""
91+
92+
function Pkg_promptf()
93+
global prev_project_timestamp, prev_prefix, prev_project_file
94+
project_file = find_project_file()
95+
prefix = ""
96+
if project_file !== nothing
97+
if prev_project_file == project_file && prev_project_timestamp == mtime(project_file)
98+
prefix = prev_prefix
99+
else
100+
project_name = projname(project_file)
101+
if project_name !== nothing
102+
root = find_root_base_project(project_file)
103+
rootname = projname(root)
104+
if root !== project_file
105+
path_prefix = "/" * dirname(relative_project_path(root, project_file))
106+
else
107+
path_prefix = ""
108+
end
109+
if textwidth(rootname) > 30
110+
rootname = first(rootname, 27) * "..."
111+
end
112+
prefix = "($(rootname)$(path_prefix)) "
113+
prev_prefix = prefix
114+
prev_project_timestamp = mtime(project_file)
115+
prev_project_file = project_file
116+
end
117+
end
118+
end
119+
# Note no handling of Pkg.offline, as the Pkg version does here
120+
return "$(prefix)pkg> "
121+
end

stdlib/REPL/src/REPL.jl

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ using .REPLCompletions
151151
include("TerminalMenus/TerminalMenus.jl")
152152
include("docview.jl")
153153

154+
include("Pkg_beforeload.jl")
155+
154156
@nospecialize # use only declared type signatures
155157

156158
answer_color(::AbstractREPL) = ""
@@ -1082,19 +1084,6 @@ setup_interface(
10821084
extra_repl_keymap::Any = repl.options.extra_keymap
10831085
) = setup_interface(repl, hascolor, extra_repl_keymap)
10841086

1085-
const Pkg_pkgid = Base.PkgId(Base.UUID("44cfe95a-1eb2-52ea-b672-e2afdf69b78f"), "Pkg")
1086-
const Pkg_REPLExt_pkgid = Base.PkgId(Base.UUID("ceef7b17-42e7-5b1c-81d4-4cc4a2494ccf"), "REPLExt")
1087-
1088-
function load_pkg()
1089-
@lock Base.require_lock begin
1090-
REPLExt = Base.require_stdlib(Pkg_pkgid, "REPLExt")
1091-
# require_stdlib does not guarantee that the `__init__` of the package is done when loading is done async
1092-
# but we need to wait for the repl mode to be set up
1093-
lock = get(Base.package_locks, Pkg_REPLExt_pkgid.uuid, nothing)
1094-
lock !== nothing && wait(lock[2])
1095-
return REPLExt
1096-
end
1097-
end
10981087

10991088
# This non keyword method can be precompiled which is important
11001089
function setup_interface(
@@ -1173,7 +1162,7 @@ function setup_interface(
11731162

11741163
# Set up dummy Pkg mode that will be replaced once Pkg is loaded
11751164
# use 6 dots to occupy the same space as the most likely "@v1.xx" env name
1176-
dummy_pkg_mode = Prompt("(......) $PKG_PROMPT",
1165+
dummy_pkg_mode = Prompt(Pkg_promptf,
11771166
prompt_prefix = hascolor ? repl.pkg_color : "",
11781167
prompt_suffix = hascolor ?
11791168
(repl.envcolors ? Base.input_color : repl.input_color) : "",

0 commit comments

Comments
 (0)