2

When using Ctrl+w or Alt+Backspace or Alt+d keyboard shortcuts to delete words backward/forward, I know I can define the WORDCHARS characters:

WORDCHARS='~!#$%^&*(){}[]<>?.+;-'

for example, using Ctrl+w from the end of this string, will successively delete each word

echo aaa bbb ccc ddd eee

but if I have quoted strings, how can I treat the whole quoted block as one entity?

echo 'aaa bbb ccc' 'ddd eee fff'

so, Ctrl+w should delete whole 'ddd eee fff' in one go. Same behavior should be for strings quoted with double quotes "

3 Answers 3

3

The shell word style does exactly this.

autoload -U select-word-style
select-word-style shell
2

I think you'd need to have space in WORDCHARS and as there doesn't seem to be a way to define rules around their use, I'm not sure there's a way to make that work. Maybe there's a way to define a custom Emacs macro that the command line can reference. If there is a way to do either of these it's beyond my familiarity and I'd happily defer to someone in the know.

Not the answer you were looking for

This isn't a direct answer to the question as posed but it is something you could do along the lines you describe, using built features (caveats to follow):

Change the line editor method to vi

set -o vi

Then you could try to remember to type this little beauty:

Esc2dF"x or Esc2dF'x according to the quotes in use.

It doesn't really roll off the fingers, but you can at least press . to repeat if you want.

Caveats

It's just searching backwards twice for an instance of the given quote and deleting everything that's in the way (with no appreciation of syntax, context etc). Given this was your command line, and your cursor was lying at the end:

echo "foo bar" baz

You would end up with

echo<space>

Or if you started with

echo "foo bar" baz "boz

You would end up with the equally not-quite-what-I-wanted

echo "foo bar

You'd need to be in vi mode before you started typing, so you'd have to set it in your profile or some such.

Having vi as your editor at the command line is something of a paradigm shift and will probably be a fight against muscle memory -- and that really doesn't seem like much fun.

So...

I'd probably stick with smashing CtrlW a few times myself.

If you accidentally overdo it, there's always undo Ctrl_.

1

The word style described by Gilles is indeed the right way to do this. But if you follow his suggestion, you will get this behavior for all word-based keys. So M+f will stop moving forward by [A-Za-z0-9] words and will instead jump forward a full shell paramter.

Since you requested a way to delete a full shell parameter at a time, but didn't say anything about other movement, here's how you do that:

autoload -U select-word-style
select-word-style normal

zle -N backward-kill-shell-word backward-kill-word-match
zstyle :zle:backward-kill-shell-word word-style shell

bindkey '^w'  backward-kill-shell-word

This will bind Ctrl+W to a newly-created zsh widget, backward-kill-shell-word. Obviously, you would need to adjust the first argument of bindkey if you want to use a different shortcut for this. See the zsh docs for more.

NB: Different terminal emulators send different hex codes/escape sequences for the same keypresses. In my case, I actually wanted to use Ctrl+Backspace (Ctrl+Delete on Mac.) This is non-trivial, and Ctrl+Backspace is particularly fraught. In my case (iTerm2 on macOS) I actually needed to create and send a synthetic escape sequence for Ctrl+Delete to get the behavior I was after. Then I used that sequence (^[[27;6;8~) in bindkey in my .zshrc.

I'd like to point out that all three of the SO answers I used to work this out have come from Gilles, who is a giant among men. Thank you!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .