-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
edit command breaks for EDITOR path containing spaces #13032
Conversation
I'm confused, shouldn't your
? Why does it include an explicit backslash character? |
@stevengj After further inspection I believe you are correct and I shouldn't be including the backslash. For some context here is what I had for my Sublime terminal setup: SUBL2="/Applications/Sublime\ Text\ 2.app/Contents/SharedSupport/bin/subl"
SUBL3="/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl"
SUBL=$SUBL3
alias subl2="$SUBL2"
alias subl3="$SUBL3"
alias subl="$SUBL"
export EDITOR="$SUBL" The reason I included the backslash was to make the aliases work. Without the backslash I was getting SUBL2="/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"
SUBL3="/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"
SUBL=$SUBL3
# Note: Single quotes used to handle spaces
alias subl2="'$SUBL2'"
alias subl3="'$SUBL3'"
alias subl="'$SUBL'"
export EDITOR="$SUBL" Note that my updated setup still has problems with Julia's |
Now after running several experiments the EDITOR variable using My rational behind this decision is that the EDITOR variable can contain more than just a path to an executable and can contain flags. When an EDITOR contains both spaces in the executable path and flags it becomes difficult to determine the editor's name. eg. julia> shell_split("/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl -w")
3-element Array{AbstractString,1}:
"/Applications/Sublime"
"Text.app/Contents/SharedSupport/bin/subl"
"-w" vs. julia> shell_split("/Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl -w")
2-element Array{AbstractString,1}:
"/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"
"-w"
julia> shell_split("'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl' -w")
2-element Array{AbstractString,1}:
"/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"
"-w" Alternatively, if we really wanted to we could support an EDITOR without escaped spaces by assuming that no flags will exist. Note that the command One last note: I'll be adding the following to my terminal setup to keep crontab and Julia happy: export JULIA_EDITOR="'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl'" |
@stevengj Here is the short answer to your original question: The backslash was included to escape the path such that the eg. julia> ENV["EDITOR"] = "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"
"/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"
julia> edit(edit, (String,))
ERROR: could not spawn `/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl /usr/local/Cellar/julia/HEAD/bin/../share/julia/base/interactiveutil.jl:56`: no such file or directory (ENOENT)
in _jl_spawn at process.jl:255
in anonymous at process.jl:408
in setup_stdio at process.jl:396
in spawn at process.jl:407
in edit at interactiveutil.jl:37
in edit at interactiveutil.jl:58 |
In particular, it looks like the culprit is the call to shell_split in the The bug was introduced by #6865 by @jayschwa in order to handle sublime arguments, but the "cure" introduced a bug whenever the sublime path contains a space. |
In general, any call to I guess we could call |
(But in any case, the proposed solution, of recognizing backslashed spaces in a pathname, is definitely wrong.) |
@stevengj I'll note that the current implementation of |
I agree that escaping/quoting should happen as late as possible. In this case however I don't think you can escape later due to the example you illustrated with |
@omus, the problem is that there are two conflicting desires here:
Your patch fixes the former at the price of breaking the latter (#6865). Maybe this is a good idea, or maybe there is a heuristic to mostly support both (e.g. split after substrings beginning with |
I'm quite surprised that it worked with an escaped backslash. If you have a file |
The reason the escaped backslash calls were working was due to julia> subl = "/Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl"
"/Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl"
julia> `$subl`
`'/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl'`
julia> run(`$subl`)
ERROR: could not spawn `'/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl'`: no such file or directory (ENOENT)
in _jl_spawn at process.jl:255
in anonymous at process.jl:408
in setup_stdio at /usr/local/Cellar/julia/HEAD/lib/julia/sys.dylib
in __spawn#58__ at /usr/local/Cellar/julia/HEAD/lib/julia/sys.dylib
in run at /usr/local/Cellar/julia/HEAD/lib/julia/sys.dylib
julia> import Base: shell_split; `$(shell_split(subl))`
`'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl'`
julia> run(`$(shell_split(subl))`)
# Success |
My goal here is to have Julia's
I may wrong here but I feel like we need to be supporting what is allowed by the shell and not forcing users to update their environment to suit Julia. |
When working within Julia with julia> cmd = "foo bar"; file = "baz"; c = `$cmd $file`
`'foo bar' baz` However when working with paths coming from outside of Julia, like ENV for example, I believe that you should be using |
I can't find any sources that actually document a recommendation to backslash-escape spaces in the contents of variables like Even in the shell, all the sources that I can find advise using environment variables quoted like |
Unfortunately the $ touch '/tmp/a b'
$ bash -c "ls /tmp/a b"
ls: /tmp/a: No such file or directory
ls: b: No such file or directory
$ bash -c "ls /tmp/a\ b"
/tmp/a b
$ bash -c "ls '/tmp/a b'"
/tmp/a b Julia behaves in the exact same way as bash: julia> run(`ls /tmp/a b`)
ls: /tmp/a: No such file or directory
ls: b: No such file or directory
ERROR: failed process: Process(`ls /tmp/a b`, ProcessExited(1)) [1]
in run at /usr/local/Cellar/julia/HEAD/lib/julia/sys.dylib
julia> run(`ls /tmp/a\ b`)
/tmp/a b
julia> run(`ls '/tmp/a b'`)
/tmp/a b
julia> run(`ls "/tmp/a b"`)
/tmp/a b
julia> string(`ls /tmp/a\ b`) == string(`ls '/tmp/a b'`) == string(`ls "/tmp/a b"`)
true The fundamental reason we need to support for quoting in this particular case is to allow Julia to support an EDITOR variable that contains both spaces in a path and arguments. Otherwise I'm starting to get confused to what the fundamental problem is exactly. The proposed solution doesn't change the prior behaviour in regards to:
But adds support for the following for all editors:
I can't think of another solution to this problem that allows for both flags and spaces in paths. |
I see; I had thought your patch didn't support arguments, but I see that I was mistaken. (I'm used to quoting, but not in environment variables like Looks reasonable to me now; the key point is that it is not really a change of our quoting/parsing behavior, but rather it just makes it more uniform for all editors. You'll need to squash the commits, of course. Is there any way to add a test for this? Maybe at least some tests for |
I'll do some experimenting with how to test this. I definitely don't want to actually launch the editor during a test but I could probably abstract out the generation of the Am I correct in that you want me to combine all of the commits before this is merged? |
Yes, squashing means combining all the commits. You can do that with an interactive rebase ( |
I think it's probably enough to add a couple of tests for |
f1a74ad
to
db4caa8
Compare
I am aware of squashing but I was surprised that I was asked to do it for a PR. Note that I focused on adding tests for quoting. Let me know if you want additional tests. |
I think I can abstract out the part of |
@stevengj I added test cases for One behavioural change I did was to remove the following check:
Which isn't a very useful as it will only error if the program is exists in the system (ispath) and the permissions are not set to readable. I can add this back in if you wish. Let me know if you are happy with all of these changes. If you are I will squash the last two changes together and this PR should be ready to be merged. |
editor() | ||
|
||
Determines the editor to use when running functions like `edit`. You can change the editor | ||
by setting JULIA_EDITOR, VISUAL, or EDITOR as an environmental variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document that it returns an array to splat into backticks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do
Looks good, though I'm not completely sure these tests should go into two separate files. |
I reworked the
Do you want me to put the tests in the same file or remove the redundant tests? |
Maybe put the |
Ok I moved the tests into the appropriate files. |
LGTM. Squash the commits, then probably good to merge? |
48b064d
to
4a5448d
Compare
Lets merge this! Thanks for your patience on this PR @stevengj |
for use within backticks. You can change the editor by setting JULIA_EDITOR, VISUAL, or | ||
EDITOR as an environmental variable. | ||
""" | ||
function editor() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be sync'd to the rst doc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
editor
isn't an exported function so I would guess this should not be included in the external documentation. Opinions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be fine to leave this as is for now....
4a5448d
to
53fcec2
Compare
I randomly stumbled upon |
When working with Sublime as my default editor on OS X I had set my editor to: EDITOR=/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl Since the `ispath` function did not recognize this as a path (because contained a backslash) this resulted in my editor not being recognized as "subl" and line number support being unavailable. The section of `edit` that deals with determining the user's editor has been abstracted into a new function `editor`. Test cases have been added for `editor` along with some basic tests for `shell_split`. Note that `startswith` is used to identify alternative editor names: - Sublime Text can refer to "subl" or "sublime". - Emacs can refer to "emacs" or "emacsclient".
edit command breaks for EDITOR path containing spaces
My preference would be to backport this after 0.4.0, since it might require some hands-on interactive testing to get the kinks out. |
Yes, 0.4.1 seems fine. I hate to see anything non-critical go into 0.4.0 this late. |
Completely fine with me. |
When working with Sublime as my default editor on OS X I had set my editor to: EDITOR=/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl Since the `ispath` function did not recognize this as a path (because contained a backslash) this resulted in my editor not being recognized as "subl" and line number support being unavailable. The section of `edit` that deals with determining the user's editor has been abstracted into a new function `editor`. Test cases have been added for `editor` along with some basic tests for `shell_split`. Note that `startswith` is used to identify alternative editor names: - Sublime Text can refer to "subl" or "sublime". - Emacs can refer to "emacs" or "emacsclient". (cherry picked from commit 53fcec2) ref #13032
I noticed when using the
edit
function in Julia that I was getting this message:After doing some digging I noticed that my default editor Sublime is supported by the
edit
function but something else was going on. My editor is set using the environmental variable EDITOR and looks like this:In Julia the path includes the backslash but is not recognized as a path:
Since the
ispath
function doesn't recognize this string as a path theedit
function will not recognize the editor as "subl" and state that line number support is not available. Note that if I set the EDITOR to not include the backslashispath
will pass but will cause the spawn call to fail:I have updated the code to use
shell_split
earlier which strips the backslash and makes it easier to find the editor name. Another improvement is allowing the if the user includes flags in their EDITOR (such as ".../subl -w") we can still determine the editor name.I believe that this pull request fixes the issue in #11305 and is an improvement over the pull request #11329.