/zsh-edit

🛠 Better command line editing tools for Zsh

Primary LanguageShellMIT LicenseMIT

Zsh Edit

Zsh Edit is a set of handy utilities for making life easier on the Zsh command line.

Requirements

Tested to work with Zsh 5.8 and newer.

Installating & updating

I recommend using Znap or installing the plugin manually. You can also install it using any 3rd-party framework or plugin manager you like, but I won't document that here.

Using Znap

Aust add this to your .zshrc file:

znap source marlonrichert/zsh-edit

To update, run znap pull.

Manually

  1. Clone the repo:
    % git clone --depth 1 https://github.com/marlonrichert/zsh-edit.git
  2. Source the plugin in your .zshrc file:
    source <your plugins dir>/zsh-edit/zsh-edit.plugin.zsh
  3. Restart your shell:
    exec zsh

To update:

% cd <your plugins dir>/zsh-edit
% git pull

bind Command

Bind shell commands directly to keyboard shortcuts. What's more, when using these, your current command line will be left intact.

bind  '^[:' 'cd ..'
bind  '^[-' 'pushd -1' \
      '^[=' 'pushd +0'

List duplicate keybindings in the main keymap or another one.

bind -d
bind -dM viins

List unused keybindings in the main keymap or another one.

bind -u
bind -uM emacs

Look up which combination of keys could generate an escape sequence listed by bind or bindkey.

% bind -n '^[[5~' '^[^[OA'
"^[[5~"    PageUp
"^[^[OA"   Alt-Up

Key Bindings

Zsh Edit adds the keyboard shortcuts below to your main and emacs keymaps.

  • By default, the emacs keymap is your main keymap.
  • However, if you use vi mode, then your main keymap will be the viins keymap.

All key bindings can be modified through Zsh's bindkey command, after sourcing Zsh Edit.

⚠️ Note:

  • Not all terminals support all key bindings.
  • In some terminals, instead of Alt, you'll have to press Esc or Ctrl[.
  • In many terminals, Home, End, PgUp and PgDn scroll the terminal buffer and don't send any keystrokes to the shell. To use these keys in the shell, you'll have to hold an additional modifier key, usually Shift. Refer to your terminal's documentation and/or settings for more info.
Command emacs keymap main keymap
Redo (reverse Undo) Alt/
Recover last line aborted with CtrlC or CtrlG CtrlAltG
Replace all Ctrl]
Reverse yank pop AltY
Repeat word up Alt.
Repeat word down Alt,
Repeat word left CtrlAlt-
Repeat word right AltShift-
Backward subword CtrlAltB Ctrl CtrlAlt
Forward subword CtrlAltF Ctrl CtrlAlt
Backward shell word AltB Alt Shift
Forward shell word AltF Alt Shift
Beginning of line CtrlA Home CtrlX
End of line CtrlE End CtrlX
Beginning of buffer Alt< PgUp CtrlX
End of buffer Alt> PgDn CtrlX
Backward delete character
Forward delete character
Backward kill subword CtrlH Ctrl AltCtrl
Forward kill subword CtrlAltD Ctrl AltCtrl
Backward kill shell word CtrlW Alt Shift
Forward kill shell word AltD Alt Shift
Backward kill line CtrlU CtrlShift CtrlX
Forward kill line CtrlK CtrlShift CtrlX

Replace All Occurences of a Character

Press Ctrl] followed by two characters and each substring consisting of one or more occurences of the first character will be replaced entirely with the second character. This is useful, for example, if you pasted a list of files separated by line breaks into the command line, but you need them to be separated with spaces instead.

If you've just pasted something or the region is active, only the pasted or selected text is affected. This way, you can find-and-replace selectively. Otherwise, this widget always operates on the whole command line.

Clipboard Viewer

Whenever you use yank (^Y in emacs), vi-put-after (p in vicmd) or vi-put-after (P in vicmd) to paste a kill into the command line, Zsh Edit will list the contents of your kill ring (including the cut buffer) below your command line. In addition, Zsh Edit eliminates all duplicate kills from your kill ring. Thus, each entry listed is guaranteed to be unique.

Furthermore, after pasting, when you use yank-pop (^[y in emacs), Zsh Edit will show you which kill is currently selected, making it easier to cycle to the right one. To view your clipboard at any time – without modifying your command line – just press yank-pop by itself.

Finally, Zsh Edit adds a new widget reverse-yank-pop, which lets you cycle in the opposite direction. It is bound to ^[Y in the emacs keymap.

Subword Movement

Zsh's widgets forward-word, backward-word, kill-word and backward-kill-word fail to stop on many of the positions that we humans see as word boundaries:

# Zsh with default WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>' moves/deletes way too much:
#              >       >             >             >          >
% ENV_VAR=value command --option-flag camelCaseWord ~/dir/*.ext
# <             <       <             <             <

# Zsh with  WORDCHARS='' is bit better, but skips punctuation clusters & doesn't find subWords:
#    >   >     >         >      >    >               >     >
% ENV_VAR=value command --option-flag camelCaseWord ~/dir/*.ext
# <   <   <     <         <      <    <               <     <

Zsh Edit adds new widgets with better parsing rules that can find all the word boundaries that matter to us as humans. Additionally, it adds smarter movement: If the cursor is inside a word, it will move to the beginning or end of that same word, not the next one. This way, you can quickly toggle between the beginning and the end of each word.

For example:

# Zsh Edit with WORDCHARS=''
#   >   >     >       >  >     >    >     >   >   >  >  >      >
% ENV_VAR=value command --option-flag camelCaseWord ~/dir/?*.ext
# <   <   <     <       < <      <    <    <   <    < <      <

To stop a character from being treated as a subword separator, simply add it to $WORDCHARS. For example, by treating ~, * and ? as word characters, you can get more precise subword movement in path strings:

# Zsh Edit with WORDCHARS='~*?'
#  > >   >  >   >
% cd ~/dir/?*.ext
# <  < <   <  <

If you don't want to change your $WORDCHARS globally, you can instead use the following:

zstyle ':edit:*' word-chars '~*?'

This will change $WORDCHARS only for the widgets provided by Zsh Edit.

Author

© 2020-2023 Marlon Richert

License

This project is licensed under the MIT License. See the LICENSE file for details.