Skip to content
Closed
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
48 changes: 38 additions & 10 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,38 @@ answer_color() = text_colors[repl_color("JULIA_ANSWER_COLOR", default_color_answ
stackframe_lineinfo_color() = repl_color("JULIA_STACKFRAME_LINEINFO_COLOR", :bold)
stackframe_function_color() = repl_color("JULIA_STACKFRAME_FUNCTION_COLOR", :bold)

function repl_cmd(cmd, out)
"""
ShellSpecification{is_windows, shell}

A type used for dispatch to select the appropriate shell command preparation logic.
It is parameterized by `is_windows::Bool` indicating the operating system,
and `shell::Symbol` representing the basename of the shell executable.
"""
struct ShellSpecification{is_windows,shell} end

"""
prepare_shell_command(spec::ShellSpecification, cmd::Cmd, raw_string::String) -> Cmd

Returns a `Cmd` object configured for execution according to `spec`,
using the provided `cmd` (parsed command) and `raw_string` (original input).
Specialized methods for `ShellSpecification` define shell- and OS-specific behavior.
"""
function prepare_shell_command(::ShellSpecification{true,shell}, cmd, _) where {shell}
return cmd
end
function prepare_shell_command(::ShellSpecification{false,shell}, cmd, _) where {shell}
shell_escape_cmd = "$(shell_escape_posixly(cmd)) && true"
return `$shell -c $shell_escape_cmd`
end
function prepare_shell_command(::ShellSpecification{false,:fish}, cmd, _)
shell_escape_cmd = "begin; $(shell_escape_posixly(cmd)); and true; end"
return `fish -c $shell_escape_cmd`
end
function prepare_shell_command(::ShellSpecification{false,:nu}, _, raw_string)
return `nu -c $raw_string`
end

function repl_cmd(cmd, raw_string, out)
shell = shell_split(get(ENV, "JULIA_SHELL", get(ENV, "SHELL", "/bin/sh")))
shell_name = Base.basename(shell[1])

Expand Down Expand Up @@ -64,16 +95,10 @@ function repl_cmd(cmd, out)
cd(dir)
println(out, pwd())
else
@static if !Sys.iswindows()
if shell_name == "fish"
shell_escape_cmd = "begin; $(shell_escape_posixly(cmd)); and true; end"
else
shell_escape_cmd = "($(shell_escape_posixly(cmd))) && true"
end
cmd = `$shell -c $shell_escape_cmd`
end
shell_spec = ShellSpecification{Sys.iswindows(),Symbol(shell_name)}()
prepared_cmd = prepare_shell_command(shell_spec, cmd, raw_string)
try
run(ignorestatus(cmd))
run(ignorestatus(prepared_cmd))
catch
# Windows doesn't shell out right now (complex issue), so Julia tries to run the program itself
# Julia throws an exception if it can't find the program, but the stack trace isn't useful
Expand All @@ -85,6 +110,9 @@ function repl_cmd(cmd, out)
nothing
end

# For backward compatibility
repl_cmd(cmd, out) = repl_cmd(cmd, string(cmd), out)

# deprecated function--preserved for DocTests.jl
function ip_matches_func(ip, func::Symbol)
for fr in StackTraces.lookup(ip)
Expand Down
1 change: 1 addition & 0 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,7 @@ function setup_interface(
on_done = respond(repl, julia_prompt) do line
Expr(:call, :(Base.repl_cmd),
:(Base.cmd_gen($(Base.shell_parse(line::String)[1]))),
line::String,
outstream(repl))
end,
sticky = true)
Expand Down
6 changes: 3 additions & 3 deletions test/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1925,15 +1925,15 @@ end
cd(dir) do
withenv("OLDPWD" => nothing) do
io = IOBuffer()
Base.repl_cmd(@cmd("cd"), io)
Base.repl_cmd(@cmd("cd -"), io)
Base.repl_cmd(@cmd("cd"), "cd", io)
Base.repl_cmd(@cmd("cd -"), "cd -", io)
@test realpath(pwd()) == realpath(dir)
if !Sys.iswindows()
# Delete the working directory and check we can cd out of it
# Cannot delete the working directory on Windows
rm(dir)
@test_throws Base._UVError("pwd()", Base.UV_ENOENT) pwd()
Base.repl_cmd(@cmd("cd \\~"), io)
Base.repl_cmd(@cmd("cd \\~"), "cd \\~", io)
end
end
end
Expand Down