auto_remove_slash feature from zsh #3253

Closed
needmoreram opened this Issue Jul 19, 2016 · 11 comments

Comments

Projects
None yet
7 participants
@needmoreram

Often when tab-completing directories, a trailing slash is added at the end of said completion. If the next character is a word delimiter, the said trailing slash should be removed (ideally configurable) - this behaviour would be exactly the same as in zsh when auto_remove_slash option is enabled.

Ultimately a purely cosmetic enhancement, but imho will make the output less ugly and more readable.

For example,

➜ 0 ~ find .config/fish/ -type f
.config/fish//fish_history
.config/fish//fish_read_history
.config/fish//fishd.3c0754519632
.config/fish//fishd.406c8f111f61
.config/fish//fishd.985aeb8eac6e
.config/fish//fishd.985aeb8ebc6e
.config/fish//fishd.985aeb8efb6e
.config/fish//functions/fish_prompt.fish

(notice the unsightly double slash in the output)

@zanchey zanchey added the enhancement label Jul 19, 2016

@zanchey

This comment has been minimized.

Show comment
Hide comment
@zanchey

zanchey Jul 19, 2016

Member

How does this work in zsh? If the option is on and you push space, it erases the slash character and then adds a space? The problem with this option is that sometimes that changes the behaviour of the command - cp and rsync are the obvious examples.

Member

zanchey commented Jul 19, 2016

How does this work in zsh? If the option is on and you push space, it erases the slash character and then adds a space? The problem with this option is that sometimes that changes the behaviour of the command - cp and rsync are the obvious examples.

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Jul 19, 2016

Member

This seems way too magic for my taste. If you really want it, you might be able to bind space to a function that does it, basically doing

 commandline -rt -- (commandline -ct | string replace -r '/$' '')
 commandline -i " "
Member

faho commented Jul 19, 2016

This seems way too magic for my taste. If you really want it, you might be able to bind space to a function that does it, basically doing

 commandline -rt -- (commandline -ct | string replace -r '/$' '')
 commandline -i " "
@floam

This comment has been minimized.

Show comment
Hide comment
@floam

floam Jul 19, 2016

Member

If the option is on and you push space, it erases the slash character and then adds a space?

No. It doesn't really seem unreasonable or super spooky:

When the last character resulting from a completion is a slash and the next character
typed is a word delimiter, a slash, or a character that ends a command (such as a
semicolon or an ampersand), remove the slash.

So it's cleaning up after an often unpleasant completion artifact, for the most part, I think.

Member

floam commented Jul 19, 2016

If the option is on and you push space, it erases the slash character and then adds a space?

No. It doesn't really seem unreasonable or super spooky:

When the last character resulting from a completion is a slash and the next character
typed is a word delimiter, a slash, or a character that ends a command (such as a
semicolon or an ampersand), remove the slash.

So it's cleaning up after an often unpleasant completion artifact, for the most part, I think.

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Jul 19, 2016

Member

So it's cleaning up after an often unpleasant completion artifact, for the most part, I think.

That's really the thing - "often" unpleasant. Sometimes pleasant. For varying values of "often" and "sometimes".

Sometimes you want the slash, other times you don't. We don't know which is which, and not removing the slash is the more obvious thing to do - you get what you type, and if you type a space, you get a space. Not "remove the last character, then add a space".

If you want the slash, and space removes it, then you need to press space, go back, readd the slash and then move right again (or typing a space should hopefully work).

If you don't want the slash, you can press backspace to remove it and then press space (or whatever else you want to do next), just like with everything else. Slashes aren't special in this situation, completion isn't special here, you just press the keys to edit the text. That's what I'm talking about when I say "magic". This is a sometimes-optimization for a quite specific thing, and quite non-obvious (unless you've already used it with zsh).

In addition, not everything that ends in a slash is a path, so this would need to be added to the file completion code (and everything that completes files).

In case you haven't guessed, this is a 👎.

Member

faho commented Jul 19, 2016

So it's cleaning up after an often unpleasant completion artifact, for the most part, I think.

That's really the thing - "often" unpleasant. Sometimes pleasant. For varying values of "often" and "sometimes".

Sometimes you want the slash, other times you don't. We don't know which is which, and not removing the slash is the more obvious thing to do - you get what you type, and if you type a space, you get a space. Not "remove the last character, then add a space".

If you want the slash, and space removes it, then you need to press space, go back, readd the slash and then move right again (or typing a space should hopefully work).

If you don't want the slash, you can press backspace to remove it and then press space (or whatever else you want to do next), just like with everything else. Slashes aren't special in this situation, completion isn't special here, you just press the keys to edit the text. That's what I'm talking about when I say "magic". This is a sometimes-optimization for a quite specific thing, and quite non-obvious (unless you've already used it with zsh).

In addition, not everything that ends in a slash is a path, so this would need to be added to the file completion code (and everything that completes files).

In case you haven't guessed, this is a 👎.

@krader1961

This comment has been minimized.

Show comment
Hide comment
@krader1961

krader1961 Jul 19, 2016

Contributor

You probably want a different example, @needmoreram, because the example you provided illustrates that the find command you're using needs an enhancement — not that fish needs to be changed. The macOS (BSD derivative) /usr/bin/find has that behavior but the GNU find from HomeBrew does not.

I agree with @faho and vote no 👎 .

Contributor

krader1961 commented Jul 19, 2016

You probably want a different example, @needmoreram, because the example you provided illustrates that the find command you're using needs an enhancement — not that fish needs to be changed. The macOS (BSD derivative) /usr/bin/find has that behavior but the GNU find from HomeBrew does not.

I agree with @faho and vote no 👎 .

@zanchey zanchey added this to the fish-tank milestone Jul 20, 2016

@needmoreram

This comment has been minimized.

Show comment
Hide comment
@needmoreram

needmoreram Jul 20, 2016

Hi guys, thanks for jumping on this right away, and for your thoughts so far! To answer some of the questions above:

@zanchey yes, but only if that slash was inserted as a result of a completion (@faho it does not always remove them as your binding commands to the space-key do). Additionally, zsh highlights (just) the trailing slash if its removal is imminent upon inputting a delimit character. To keep said slash, you simply key in an additional '/' before the delimiter.

In practice, the keystrokes some_dir_na<tab><slash><space> will insert 'some_dir_name/ ', while the keystrokes some_dir_na<tab><space> will insert 'some_dir_name '

The penalty you incur for this is one extra keystroke (slash) (@faho rather than the sequence you described involving going back and moving right). You still incur the same one stroke penalty today, when you want to remove the trailing slash (in the case of rsync/cp'ing the directory itself).

@krader1961 did not know that, thanks! :) Sure, another example where this would matter is when manipulating soft symlinks (symlink inode vs dir inode).

I suppose, in the end, it comes down to which action a majority of the community prefers/uses more regularly. Of course, not to shove such a feature down everyones throats, an option to turn it on (with default being off) would satisfy both sides :)

@faho Can you clarify in which cases a completion ending in a '/' won't be a path?

needmoreram commented Jul 20, 2016

Hi guys, thanks for jumping on this right away, and for your thoughts so far! To answer some of the questions above:

@zanchey yes, but only if that slash was inserted as a result of a completion (@faho it does not always remove them as your binding commands to the space-key do). Additionally, zsh highlights (just) the trailing slash if its removal is imminent upon inputting a delimit character. To keep said slash, you simply key in an additional '/' before the delimiter.

In practice, the keystrokes some_dir_na<tab><slash><space> will insert 'some_dir_name/ ', while the keystrokes some_dir_na<tab><space> will insert 'some_dir_name '

The penalty you incur for this is one extra keystroke (slash) (@faho rather than the sequence you described involving going back and moving right). You still incur the same one stroke penalty today, when you want to remove the trailing slash (in the case of rsync/cp'ing the directory itself).

@krader1961 did not know that, thanks! :) Sure, another example where this would matter is when manipulating soft symlinks (symlink inode vs dir inode).

I suppose, in the end, it comes down to which action a majority of the community prefers/uses more regularly. Of course, not to shove such a feature down everyones throats, an option to turn it on (with default being off) would satisfy both sides :)

@faho Can you clarify in which cases a completion ending in a '/' won't be a path?

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Jul 20, 2016

Member

yes, but only if that slash was inserted as a result of a completion (@faho it does not always remove them as your binding commands to the space-key do)

Yes, that's a wart of the simple hack I came up with. But my point regarding the "magic" stands - you press something that usually only inserts a character and a character disappears.

@faho Can you clarify in which cases a completion ending in a '/' won't be a path?

dbus has things that look like paths.

Another thought I had would be to not insert the trailing "/" in the completions in the first place. I need to think about that some more.

Of course, not to shove such a feature down everyones throats, an option to turn it on (with default being off) would satisfy both sides :)

Well, there is the paragraph on how "Configurability is the root of all evil" in our design document.

In general we try to not be like zsh. They add everything and hide it behind an option. We try to add sensible things and enable them by default.

Member

faho commented Jul 20, 2016

yes, but only if that slash was inserted as a result of a completion (@faho it does not always remove them as your binding commands to the space-key do)

Yes, that's a wart of the simple hack I came up with. But my point regarding the "magic" stands - you press something that usually only inserts a character and a character disappears.

@faho Can you clarify in which cases a completion ending in a '/' won't be a path?

dbus has things that look like paths.

Another thought I had would be to not insert the trailing "/" in the completions in the first place. I need to think about that some more.

Of course, not to shove such a feature down everyones throats, an option to turn it on (with default being off) would satisfy both sides :)

Well, there is the paragraph on how "Configurability is the root of all evil" in our design document.

In general we try to not be like zsh. They add everything and hide it behind an option. We try to add sensible things and enable them by default.

@needmoreram

This comment has been minimized.

Show comment
Hide comment
@needmoreram

needmoreram Jul 21, 2016

Well, there is the paragraph on how "Configurability is the root of all evil" in our design document.

In general we try to not be like zsh. They add everything and hide it behind an option. We try to add sensible things and enable them by default.

@faho Thanks for the link, and after reading it over, I realized that this was one of the main reasons I started to use fish in the first place! And so I agree, making this an option will be big compromise without justifiable improvement in workflow/productivity.

Another thought I had would be to not insert the trailing "/" in the completions in the first place. I need to think about that some more.

True, this crossed my mind when typing out the sequence in my previous comment.

Thanks again everyone and especially @faho for your patience in taking the time to explain things :)

Well, there is the paragraph on how "Configurability is the root of all evil" in our design document.

In general we try to not be like zsh. They add everything and hide it behind an option. We try to add sensible things and enable them by default.

@faho Thanks for the link, and after reading it over, I realized that this was one of the main reasons I started to use fish in the first place! And so I agree, making this an option will be big compromise without justifiable improvement in workflow/productivity.

Another thought I had would be to not insert the trailing "/" in the completions in the first place. I need to think about that some more.

True, this crossed my mind when typing out the sequence in my previous comment.

Thanks again everyone and especially @faho for your patience in taking the time to explain things :)

@faho

This comment has been minimized.

Show comment
Hide comment
@faho

faho Aug 4, 2016

Member

I'm assuming we're not gonna do this, so I'm closing.

Member

faho commented Aug 4, 2016

I'm assuming we're not gonna do this, so I'm closing.

@faho faho closed this Aug 4, 2016

@faho faho added the will-not-fix label Aug 4, 2016

@faho faho removed this from the fish-tank milestone Aug 4, 2016

@ivan

This comment has been minimized.

Show comment
Hide comment
@ivan

ivan Aug 25, 2016

Coming from zsh, I started using fish yesterday and I've already made a mess with rsync because it has a special interpretation when a directory argument has a trailing slash. (The behavior without the slash is what I want ~95% of the time.) rsync doesn't seem to have a way to disable the behavior, either, though someone requested it in 2012.

Putting #3253 (comment) in a function and binding it with bind \x20 remove_slash isn't a great workaround because it affects all trailing slashes on the command line, even ones that didn't come from tab-completion.

I am now using a function to strip trailing slashes just for rsync, similar to the one in the archlinux wiki.

ivan commented Aug 25, 2016

Coming from zsh, I started using fish yesterday and I've already made a mess with rsync because it has a special interpretation when a directory argument has a trailing slash. (The behavior without the slash is what I want ~95% of the time.) rsync doesn't seem to have a way to disable the behavior, either, though someone requested it in 2012.

Putting #3253 (comment) in a function and binding it with bind \x20 remove_slash isn't a great workaround because it affects all trailing slashes on the command line, even ones that didn't come from tab-completion.

I am now using a function to strip trailing slashes just for rsync, similar to the one in the archlinux wiki.

@nhooyr

This comment has been minimized.

Show comment
Hide comment
@nhooyr

nhooyr Jun 23, 2017

Contributor

cp also has the same behaviour as rsync and this has bit me quite a few times with fish.

cp -r soemdir/ /tmp

is equivalent to

cp -r soemdir/* /tmp

Which is entirely unexpected imo but I don't think we can get cp to change its behaviour. Maybe we could wrap cp in a function to prevent this but I think that might be too magical.

I'm not sure what the best solution to this is, but we can be more liberal with a solution because of fish 3.

Contributor

nhooyr commented Jun 23, 2017

cp also has the same behaviour as rsync and this has bit me quite a few times with fish.

cp -r soemdir/ /tmp

is equivalent to

cp -r soemdir/* /tmp

Which is entirely unexpected imo but I don't think we can get cp to change its behaviour. Maybe we could wrap cp in a function to prevent this but I think that might be too magical.

I'm not sure what the best solution to this is, but we can be more liberal with a solution because of fish 3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment