diff --git a/base/client.jl b/base/client.jl index 7f8c5b11370b2..64c460e545b0f 100644 --- a/base/client.jl +++ b/base/client.jl @@ -84,37 +84,64 @@ 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) - shell = shell_split(get(ENV,"JULIA_SHELL",get(ENV,"SHELL","/bin/sh"))) - shell_name = Base.basename(shell[1]) +function repl_cmd(line::AbstractString, out) + if Sys.iswindows() + shell = shell_split(get(ENV, "JULIA_SHELL", "cmd")) + shell_name = isempty(shell) ? "" : lowercase(splitext(basename(shell[1]))[1]) + else + shell = shell_split(get(ENV, "JULIA_SHELL", get(ENV,"SHELL","/bin/sh"))) + shell_name = basename(shell[1]) + end - if isempty(cmd.exec) + cmd = cmd_gen(eval(Main, shell_parse(line)[1])) + + if isempty(cmd) throw(ArgumentError("no cmd to execute")) - elseif cmd.exec[1] == "cd" - new_oldpwd = pwd() - if length(cmd.exec) > 2 - throw(ArgumentError("cd method only takes one argument")) - elseif length(cmd.exec) == 2 - dir = cmd.exec[2] - if dir == "-" - if !haskey(ENV, "OLDPWD") - error("cd: OLDPWD not set") - end - cd(ENV["OLDPWD"]) + elseif cmd[1] == "cd" && length(cmd) <= 2 + repl_cd(cmd, shell, out) + else + local command::Cmd + if Sys.iswindows() + interpolated_line = eval(Main, parse(string('"', escape_string(line), '"')))::String + if shell_name == "" + command = cmd + elseif shell_name == "cmd" + command = Cmd(`$shell /s /c $(string('"', interpolated_line, '"'))`, windows_verbatim=true) + elseif shell_name == "powershell" + command = `$shell -Command $interpolated_line` + elseif shell_name == "busybox" + command = `$shell sh -c $interpolated_line` else - cd(@static Sys.iswindows() ? dir : readchomp(`$shell -c "echo $(shell_escape(dir))"`)) + command = `$shell $interpolated_line` end else - cd() + ttyopt = STDIN isa TTY ? `-i` : `` + command = `$shell $ttyopt -c "$(shell_wrap_true(shell_name, cmd))"` end - ENV["OLDPWD"] = new_oldpwd - println(out, pwd()) - else - run(ignorestatus(@static Sys.iswindows() ? cmd : (isa(STDIN, TTY) ? `$shell -i -c "$(shell_wrap_true(shell_name, cmd))"` : `$shell -c "$(shell_wrap_true(shell_name, cmd))"`))) + run(ignorestatus(command)) end nothing end +function repl_cd(cmd::Cmd, shell, out) + new_oldpwd = pwd() + if length(cmd) == 2 + dir = cmd[2] + if dir == "-" + if !haskey(ENV, "OLDPWD") + error("cd: OLDPWD not set") + end + cd(ENV["OLDPWD"]) + else + cd(@static Sys.iswindows() ? dir : readchomp(`$shell -c "echo $(shell_escape(dir))"`)) + end + else + cd() + end + ENV["OLDPWD"] = new_oldpwd + println(out, pwd()) +end + function shell_wrap_true(shell_name, cmd) if shell_name == "fish" "begin; $(shell_escape(cmd)); and true; end" diff --git a/base/repl/REPL.jl b/base/repl/REPL.jl index ed793924fa0c8..71d7a4ff93757 100644 --- a/base/repl/REPL.jl +++ b/base/repl/REPL.jl @@ -779,13 +779,9 @@ function setup_interface( (repl.envcolors ? Base.input_color : repl.input_color) : "", repl = repl, complete = ShellCompletionProvider(), - # Transform "foo bar baz" into `foo bar baz` (shell quoting) - # and pass into Base.repl_cmd for processing (handles `ls` and `cd` - # special) + # Pass entered line into Base.repl_cmd for processing (handles `cd` special) on_done = respond(repl, julia_prompt) do line - Expr(:call, :(Base.repl_cmd), - :(Base.cmd_gen($(Base.shell_parse(line)[1]))), - outstream(repl)) + Expr(:call, :(Base.repl_cmd), line, outstream(repl)) end) diff --git a/doc/src/manual/environment-variables.md b/doc/src/manual/environment-variables.md index d2fe606136b76..12e9f8e2872cf 100644 --- a/doc/src/manual/environment-variables.md +++ b/doc/src/manual/environment-variables.md @@ -146,10 +146,9 @@ The absolute path of the shell with which Julia should execute external commands (via `Base.repl_cmd()`). Defaults to the environment variable `$SHELL`, and falls back to `/bin/sh` if `$SHELL` is unset. -!!! note - - On Windows, this environment variable is ignored, and external commands are - executed directly. +On Windows, `$JULIA_SHELL` can be set to `cmd`, `powershell`, `busybox` or `""`. +If set to `""` external commands are executed directly. Defaults to `cmd` if +`$JULIA_SHELL` is not set. ### `JULIA_EDITOR` diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index 40b68bf8221b3..e83098ffc2ea2 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -117,6 +117,7 @@ julia> ; # upon typing ;, the prompt changes (in place) to: shell> shell> echo hello hello ``` +See [JULIA_SHELL](@ref) in the Environment Variables section of the manual. ### Search modes