Effectively moving around on the command line might be the single biggest time saver. Most of the time you're typing but you'll also be doing a fair deal of line editing and movement.
If you're using arrows to move back and forth you can save a lot of time learning some basic line movement keyboard shortcuts.
Your line movement will depend on your loaded keymaps and the widgets you have bound to different keys. More information about custom widgets can be found in the zle section.
You can manually set your keymap mode with
# emacs mode
bindkey -e
# vi mode
bindkey -v
For the examples below I'll be using vi mode for movement.
If your
$EDITOR
or$VISUAL
environment variables start withvi
when the shell starts your keymap mode is automatically set to vi
Keybindings have special characters to represent them. More info can be found in bindkey.
For reference:
^
= Ctrl^[
= Alt\e
or\E
= Escape
If you want to figure out how a key sequence should be represented you can try xxd
or echo " $keypress"
.
The key letter you press is not case sensitive.
So ^a
is the same as ^A
.
I may like vi mode for my keymap but I'm not a monster. Let's set the emacs begining and end of line keyboard shortcuts and reverse search.
bindkey
works by default on your main keymap. In vi mode that isviins
so these keybindings work when typing but not invimcmd
mode. To explicitly set a keymap mode usebindkey -M $mode
.
bindkey '^r' history-incremental-search-backward
bindkey '^a' beginning-of-line
bindkey '^e' end-of-line
# Also fix annoying vi backspace
bindkey '^?' backward-delete-char
Now I have four ways to get to the begining and end of a command line.
I can press Escape
,^
or Ctrl
+a
for the begining of the line, and Escape
,$
or Ctrl
+e
for the end of the line.
With vi mode you have to press escape to enter vicmd mode to enter standard vi commands. The
^
and$
are standard vi commands for beginning and end of a line.
We also probably want some other useful keyboard shortcuts so we don't have to go back and forth between (vicmd) and vi-insert (viins) modes. I personally like these.
bindkey '^[b' vi-backward-blank-word
bindkey '^[w' vi-forward-blank-word
To find widgets you can use, remember to use zle -la
to list all widgets and alt+x
or esc,:
to try the widget with execute-named-cmd
.
Remember, you can use any emacs or vi commands depending on what keymap you're using. You don't have to bind keys to use them.
If you want some additional functionallity check out the examples below.
In general you'll be binding widgets to keyboard shortcuts.
There are many *-kill-*
widgets available that will let you kill words, lines, or letters.
If you don't want to feel like a murderer you can also try the *-yank-*
and *-push-*
widgets too.
When jumping between words (for example [^f
and [^b
for forward and backwards in emacs mode). The shell uses a few different
things to define what a "word" is. By default you can echo $WORDCHARS
to see all the special characters the shell will include
as a single word. For example the default is:
$ echo $WORDCHARS
*?_-.[]~=/&;!#$%^(){}<>
This means that any alphanumeric character plus any of the above will be combined to be a single word. Notice how /
is
included in the above. This means foo/bar-bazz
will be one word to be acted upon.
If you are coming from bash and want your jump/delete word functions to stop at /
and -
you can add this in
your .zshrc:
autoload -U select-word-style
select-word-style bash
Without it [^D
will delete a full directory path. For example:
## Without
$ cd /project/example/delete
## Press [^D from front beginning of line
$ /project/example/delete
## Press [^D again
$
## With select-word-style bash
$ cd /project/example/delete
## Press [^D from front beginning of line
$ /project/example/delete
## Press [^D again
$ /example/delete
You can learn about the available word styles and their behavior here (search for select-word-syle
).
But here is a quick explanation:
$ select-word-style
Usage: select-word-style word-style
where word-style is one of the characters in parentheses:
(b)ash: Word characters are alphanumerics only
(n)ormal: Word characters are alphanumerics plus $WORDCHARS
(s)hell: Words are command arguments using shell syntax
(w)hitespace: Words are whitespace-delimited
(d)efault: Use default, no special handling (usually same as `n')
(q)uit: Quit without setting a new style
One important thing to note is that any select-word-style
that is not normal
will may not respect $WORDCHARS
.
When in normal
select-word-style all alphanumeric characters plus anything in $WORDCHARS
is used by zsh to determine
when to stop its action. If you want even more control feel free to set the var directly. This can then be used to make your
backwards jump different than your forwards jump.
For example if I want my backward delete to delete a whole directory path I can set this:
## with word-style set to `normal` but $WORDCHARS=''
default-backward-delete-word () {
local WORDCHARS="*?_[]~=/&;!#$%^(){}<>"
zle backward-delete-word
}
zle -N default-backward-delete-word
bindkey '^W' default-backward-delete-word
For example, let's say you have a long command line typed up but you forgot you needed to run a command first or look up some information.
Normally you would push ctrl+c
to cancel the command, run your command, and then use your mouse to select, copy, and paste the long command to the next prompt.
Or maybe you open a new terminal, run your command, and come back.
What if I told you there was a better way?
Check out the push-input
widget.
Let's bind it to ctrl+q
and see what it does.
You can also use yank-pop
widget to keep a ring of yanked commands you can cycle through.
# re-sets yank and kill shortcuts to bash/emacs mode
bindkey -M viins '^P' push-line-or-edit
bindkey -M viins '^Y' yank
# in order to use the below you must first yank without hitting enter
# subsequent alt-y combos will cycle through
# kill ring
bindkey -M viins '\ey' yank-pop
bindkey -M viins '^U' backward-kill-line
There's a handy plugin called autopair that can automatically match your brackets and quotes in your terminal. It works similarly to an IDE and loads an autopair-insert, autopair-close, and autopair-delete widget.
There's also an included surround
widget but I had difficulty using it. YMMV.
Previous: completions | home | Next: navigation