Skip to content
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

Path with space completion fix for REPL #8838

Merged
merged 1 commit into from
Nov 23, 2014

Conversation

dhoegh
Copy link
Contributor

@dhoegh dhoegh commented Oct 28, 2014

This fixes completion for paths with spaces in both shell mode and julia mode ex:

shell>cd C:\\Program\ Files\ <tab>
shell>cd C:\\Program\ Files\ (x86)\\
julia>cd("C:\\Program\ Files\ <tab>
julia>cd ("C:\\Program\ Files\ (x86)\\

The main changes is in the completions that is used when completing in julia mode. The changes to get it working in shell mode is only 5 lines. If any of you have time to look at it @tkelman, @lucasb-eyer it would be greatly appreciated.

@StefanKarpinski could you approve the changes I made in the shell_parse? The main reason for the change is when a string is parsed to the shell_parse function like: "C:\\Progams\\ " this would throw an error before due to the ending space is removed and then the string has a dangling \. To prevent it from removing the space I use the keyword argument like: Base.shell_parse(string[r], true, strip_r=!endswith(string[r], "\\ ") and then it do not trim the space away when the string ends on "\\ ".

@dhoegh dhoegh changed the title Space completion Path with space completion fix for REPL Oct 28, 2014
function shell_parse(raw::String, interp::Bool)
s = strip(raw)
function shell_parse(raw::String, interp::Bool; strip_r::Bool=true)
s = strip_r ? strip(raw) : lstrip(raw)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wouldn't you just call the strip function on the argument before calling this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just need the function not to strip the last space away when "\\ " occurs. I just need to disable the strip it do on the raw variable. I could do the following and then just strip the input string before it is sent to the function.

function shell_parse(raw::String, interp::Bool; should_strip::Bool=true)
    s = should_strip ? strip(raw) : raw

And then the keyword argument is just a bool that controls whether the string should be stripped.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, that's a pointless option: if you want to strip the argument before doing anything else, then strip it before passing it to the function. You can write the call site like this:

Base.shell_parse(endswith(scs, "\\ ") ? strip(scs) : scs, true)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is that today it look like:

function shell_parse(raw::String, interp::Bool)
   s = strip(raw)

This means that the string is default stripped in both ends, but I would like to keep the last space in when the string endswith(scs, "\\ ") scs="C:\\Progam\\ " and today I cannot force it not to strip the last space away in the string.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any transformation of the string to be parsed to be done before passing it to the parsing function can be done without complicating the signature of the parsing function. Please do it that way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm slightly suspicious that shell parse is involved in parsing this in the first place, but that's a different story.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactly, I will change it to you suggestion @StefanKarpinski.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the stripping respect quoting with \? It seems like it should. Maybe that's the only problem here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that's how the shell parses things: if strips leading and trailing whitespace and then splits on spaces (modulo quoting).

not quite, the shell has to be able to gracefully handle files that end in spaces. I can make a file "a ", and a file "a", and bash can tell the difference:

~/Documents/no-backup/julia$ cat a
I'm a
~/Documents/no-backup/julia$ cat a\ 
I'm a_space

dropping the trailing spaces can even lead to bugs: http://www.exploit-monday.com/2013/02/WindowsFileConfusion.html

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, the correct fix here does seem to be to make sure that quoted spaces are respected by shell_parse.

@dhoegh
Copy link
Contributor Author

dhoegh commented Nov 13, 2014

I have now fixed the shell_parse function to respect the space when a string endwith "\\ ". Is this what you expected? @StefanKarpinski, @JeffBezanson. Should it be merged in a separate pull request and then the rest of the details about completion could be discussed here.

In the updated version the pull request can now also auto complete "$(ab<tab>"

@StefanKarpinski
Copy link
Member

Still not quite what I had in mind. I'll take a crack at it later.

@dhoegh dhoegh force-pushed the space_completion branch 9 times, most recently from f333eec to 1289276 Compare November 23, 2014 13:49
@dhoegh
Copy link
Contributor Author

dhoegh commented Nov 23, 2014

I have rebased and simplified the code and made some test cases. @StefanKarpinski did you get time for making the shell_parse to behave as wanted? What I suggest now is that it can be merged without the change in the shell_parse function, it will just not have any suggestions when there is a space in the end of the path in shell mode, but it will work in line 2.

shell>cd C:\\Program\ Files\ <tab>
shell>cd C:\\Program\ Files\ (x8<tab>
shell>cd C:\\Program\ Files\ (x86)\\

For completion in strings it works perfectly. If it gets merged without a version of the shell_parse function that respects the "\\ " then I will file an issue to track the problem.
@tkelman, @lucasb-eyer it would be greatly appriciated if you had time to test it.

@StefanKarpinski
Copy link
Member

Sorry, I haven't gotten around to this yet. However, the correct way to fix this issue is to get rid of the whitespace stripping I originally put in and instead build whitespace stripping into the shell_parse internal logic so that it respects backslash escaping. That is correct on all platforms, not just Windows. Looking at your current version of this patch, this may already be what you're doing. Is that correct?

@dhoegh
Copy link
Contributor Author

dhoegh commented Nov 23, 2014

Yes it strips whitespaces from the front and from the end it strips the whitespaces but it respects the backslash escaped spaces.

@StefanKarpinski
Copy link
Member

Ah, ok, carry on then. I approve of this approach. Sorry for snoozing on this so long – I swear last I looked it didn't work this way!

@StefanKarpinski
Copy link
Member

@tkelman, can you sanity check this and merge if it seems reasonable?

@tkelman
Copy link
Contributor

tkelman commented Nov 23, 2014

I'll add it to my list of things to test after 0.3.3.

@dhoegh
Copy link
Contributor Author

dhoegh commented Nov 23, 2014

Awesome good work at 0.3.3 👍

@tkelman
Copy link
Contributor

tkelman commented Nov 23, 2014

@dhoegh this works pretty nicely, I like it. Thanks for your continued improvements here!

tkelman added a commit that referenced this pull request Nov 23, 2014
Path with space completion fix for REPL
@tkelman tkelman merged commit 229f4aa into JuliaLang:master Nov 23, 2014
@dhoegh
Copy link
Contributor Author

dhoegh commented Nov 23, 2014

@tkelman you are very fast:+1:, should it be backported to 0.3.4?

@tkelman
Copy link
Contributor

tkelman commented Nov 23, 2014

@dhoegh possibly but not right away, let's wait for people to run with it on master for a few days at least.

@tkelman
Copy link
Contributor

tkelman commented Nov 25, 2014

Whoops, I merged this too soon, no backporting until the bug mentioned here #9137 (comment) is fixed

tkelman added a commit that referenced this pull request Nov 25, 2014
Fix error regarding unescape_string introduced by #8838
@tkelman tkelman added backport pending building Build system, or building Julia or its dependencies and removed building Build system, or building Julia or its dependencies labels Nov 25, 2014
@tkelman
Copy link
Contributor

tkelman commented Nov 25, 2014

This should be squashed along with #9143 and #9137 when backporting

edit: backport is at #9164

JeffBezanson added a commit that referenced this pull request Nov 30, 2014
@@ -187,12 +187,13 @@ function completions(string, pos)
partial = string[1:pos]
inc_tag = Base.incomplete_tag(parse(partial , raise=false))
if inc_tag in [:cmd, :string]
startpos = nextind(partial, rsearch(partial, non_filename_chars, pos))
m = match(r"[\t\n\r\"'`@\$><=;|&\{]| (?!\\)",reverse(partial))
startpos = length(partial)-(m == nothing ? 1 : m.offset) + 2
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivarne, @tkelman I think I have made the same mistanke here it should properly be:
startpos = nextind(partial, nextind(partial, length(partial) - (m == nothing ? 1 : m.offset)))
It does not crash the REPL but it can't complete on "ß C:\\.
Sorry about the mess I made now I understand the difficulties in indexing in strings.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't crash when it should, because of #7811.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since m.offset is guaranteed to be the offset of an ASCII character (that's what you were searching for), and ASCII characters are always represented by a single code unit in UTF-xx, isn't length(partial) - (m == nothing ? 1 : m.offset) + 2 endof(s) - start + 1 nextind(s,endof(s)) - start okay here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants