4 Stop Fighting the Keyboard
By now you have typed a wrong character in the middle of a long command and retyped the whole line. You have also run a command, wanted it again with one change, and typed it from scratch. Both habits cost time, and both are unnecessary. The shell has a line editor, a memory of what you ran, and a way to finish names for you.
The concepts in this chapter are:
- the line editor, the part of the shell that handles what you type before Enter;
- cursor movement and editing keys, and which program owns each shortcut;
- command history, recall, and history search;
- completion of commands, paths, and options;
- multiline input and continuation prompts;
- cancellation: stopping a command, abandoning a line, and unfreezing a terminal.
Each shell has its own line editor with its own defaults. Bash uses Readline, zsh has the Zsh Line Editor (ZLE), and PowerShell uses the PSReadLine module. Command Prompt relies on the editing keys of the Windows console. Their default bindings overlap, which is convenient, but the overlap is a coincidence of history rather than a standard. [1], [2], [3]
4.1 Who Handles the Key You Pressed?
A keystroke travels through several programs, and the first one that recognizes it acts on it. Knowing which program owns a shortcut tells you where to look when it does not work and where to change it.
| Owner | Examples | Where to change it |
|---|---|---|
| Terminal application | Ctrl+Shift+T new tab, Cmd+C copy on macOS, Ctrl+Shift+F search |
Terminal settings |
| Terminal driver or console | Ctrl+C interrupt, Ctrl+Z suspend, Ctrl+D end of input, Ctrl+S pause output |
stty on UNIX; console settings on Windows |
| Shell line editor | Ctrl+A, Ctrl+R, Tab, Up Arrow |
Readline, ZLE, or PSReadLine configuration |
| Running program | q in a pager, Ctrl+X in nano, :q in Vim |
The program’s own settings |
On UNIX-style systems the terminal driver, part of the operating system, turns Ctrl+C into an interrupt signal before the shell or program ever sees a character. stty -a prints those assignments; look for intr, susp, eof, stop, and start. [4] On Windows, the console host performs the same role for Ctrl+C. [5]
Trap: Ctrl+S on a UNIX terminal pauses output, and the terminal looks frozen. Nothing is broken; the terminal driver is waiting for Ctrl+Q to resume. Press Ctrl+Q before assuming a program has hung.
Everything below describes default bindings. Your configuration, or a tutorial’s, may differ; Chapter 10 shows how to change them.
4.2 Move the Cursor
The line editor keeps your command in a buffer until you press Enter. Enter runs the whole buffer no matter where the cursor is, which you saw in Chapter 1.
4.2.1 Bash/zsh
Readline and ZLE start in Emacs mode, named after the editor whose keys they borrow. [2], [6]
| Action | Keys |
|---|---|
| Start or end of line | Ctrl+A, Ctrl+E; also Home, End in most terminals |
| One character | Left, Right; also Ctrl+B, Ctrl+F |
| One word | Alt+B, Alt+F |
Wut: zsh switches to its vi keymap by itself when the EDITOR or VISUAL environment variable contains vi. If Ctrl+A inserts a character instead of moving the cursor, that is why. bindkey -e restores the Emacs keys for the session. [2]
Alt here means the Readline Meta key. Pressing Esc and then the letter does the same thing when Alt is taken by the terminal. macOS Terminal sends Alt+B as a special character unless you enable Use Option as Meta key in the profile’s keyboard settings. [7]
4.2.2 PowerShell
PSReadLine has two default edit modes, and the mode decides most of the keys in this chapter. On Windows the default is Windows mode; on macOS and Linux it is Emacs mode. [3]
| Action | Windows mode | Emacs mode |
|---|---|---|
| Start or end of line | Home, End |
Ctrl+A, Ctrl+E, also Home, End |
| One word | Ctrl+Left, Ctrl+Right |
Alt+B, Alt+F |
Get-PSReadLineOption reports the current mode in its EditMode property, and Get-PSReadLineKeyHandler lists every binding. Check the mode before following a tutorial’s key list. [8]
4.2.3 Command Prompt
The console provides Home, End, Left, Right, and Ctrl+Left and Ctrl+Right for word movement. There is no Ctrl+A binding for start of line. [9]
4.3 Edit the Line
Deleting a few characters with Backspace is fine. Deleting a whole argument or the rest of a line is faster with a kill command, which removes text and keeps it so you can yank it back.
4.3.1 Bash/zsh
| Action | Keys |
|---|---|
| Delete to start of line | Ctrl+U |
| Delete to end of line | Ctrl+K |
| Delete the word before the cursor | Ctrl+W |
| Delete the word after the cursor | Alt+D |
| Paste the last deleted text | Ctrl+Y |
| Clear the screen, keeping the line | Ctrl+L |
| Undo the last edit | Ctrl+_ or Ctrl+X Ctrl+U |
Try it with a line you do not want to run. Type echo one two three, press Ctrl+W twice, then Ctrl+Y twice, and read the result before you press Enter. [10]
4.3.2 PowerShell
| Action | Windows mode | Emacs mode |
|---|---|---|
| Delete to start of line | Ctrl+Home |
Ctrl+U |
| Delete to end of line | Ctrl+End |
Ctrl+K |
| Delete the word before the cursor | Ctrl+Backspace |
Ctrl+W |
| Paste the last deleted text | Ctrl+Y |
Ctrl+Y |
| Undo | Ctrl+Z |
Ctrl+_ |
| Abandon the line | Esc |
Ctrl+C |
In Windows mode Ctrl+A selects the whole line, as in a text editor, and Ctrl+C copies a selection when there is one. [3], [8]
4.3.3 Command Prompt
Esc clears the line. Ctrl+Home and Ctrl+End delete to the start and end of the line. There is no yank. [9]
4.4 History
The shell records the commands you run. Up and Down Arrow walk through them, and each recalled command can be edited before you press Enter.
More useful than walking is searching. Press Ctrl+R, type part of a command, and the shell shows the most recent match. Press Ctrl+R again for an older match, Enter to run it, or the left or right arrow to edit it first. This binding is the same in Readline, ZLE, and both PSReadLine modes. [2], [3], [11]
4.4.1 Bash/zsh
history prints the numbered list. Bash also expands history designators before running a command:
!!repeats the previous command;!$is the last argument of the previous command;!42runs command number 42.
Run echo hello and then echo !! to see the expansion appear on your screen before the second command runs. zsh has the same designators. [11], [12], [13]
Trap: History expansion happens inside double quotes. echo "Surprise!" is fine because ! is followed by a quote, but echo "Hello!world" tries to expand !world. Use single quotes for text containing !, or type set +H in Bash to turn expansion off for the session.
Where history is saved, and how much, depends on the shell’s configuration. Bash writes to ~/.bash_history when an interactive shell exits by default; zsh saves nothing until HISTFILE is set, which most distributions and macOS do in a startup file. Chapter 10 returns to these settings. [14], [15]
4.4.2 PowerShell
Get-History lists this session’s commands with numbers, and Invoke-History 5 or its alias r 5 reruns one. PSReadLine keeps its own history file across sessions, separately from Get-History, and it is the one that Up Arrow and Ctrl+R use. [3], [16]
In Windows mode, F8 searches backward for commands that start with what you have typed so far.
4.4.3 Command Prompt
Up and Down Arrow recall commands within the session. F7 shows a menu of the session’s history, and doskey /history prints it. The list is not saved when the window closes. [9]
4.5 Completion
Typing the first few characters of a name and pressing Tab asks the line editor to finish it. Completion reads the real filesystem and command list, so it is also a way to check spelling without running anything.
4.5.1 Bash/zsh
Press Tab once to complete a unique name. If several names match, Bash completes the common prefix and a second Tab lists the choices. zsh lists the choices immediately and, with its completion system enabled, lets you cycle through them with repeated Tab. [17], [18]
Try cd ~/Do followed by Tab and see what your home directory offers. On Linux, most distributions install bash-completion, which adds completion for command options and arguments. Without it, Bash completes command names and paths only.
4.5.2 PowerShell
In Windows mode, Tab cycles through the matches one at a time, and Shift+Tab cycles backward. In Emacs mode, Tab behaves like Bash and lists the choices. In Windows mode, Ctrl+Space opens a menu completion, where arrow keys pick a match; Chapter 10 shows how to bind MenuComplete in other modes. [3]
PowerShell completes parameter names too. Type Get-ChildItem - and press Tab to walk through the parameters of that cmdlet. It also completes $env: variable names and drive names.
4.5.3 Command Prompt
Tab cycles through matching file and directory names in the current directory. It does not complete command names or options. [19]
4.6 More Than One Line
A long command can be split across lines, and some constructs require it. The shell shows a continuation prompt while it waits for the rest.
4.6.1 Bash/zsh
A backslash at the very end of a line continues the command on the next line. Bash shows > as the continuation prompt by default:
$ echo one \ > two one two
An unclosed quote also continues the line, which is why a missing quotation mark leaves the shell waiting. Press Ctrl+C to abandon the whole thing. [20]
4.6.2 PowerShell
PowerShell continues automatically when a line cannot be complete, such as after an open brace, a pipe character, or a comma. A backtick at the end of a line continues it explicitly. The continuation prompt is >>: [21]
$ Write-Output one ` >> two one two
Note that Write-Output received two arguments and printed each on its own line, which is a difference from the Bash example, not a mistake. Shift+Enter inserts a new line inside the buffer without running it, in both edit modes.
4.6.3 Command Prompt
A caret at the end of a line continues the command, and the continuation prompt is More?:
$ echo one ^ More? two one two
The caret is Command Prompt’s escape character, which you saw in Chapter 2. [19]
4.7 Cancel, Stop, and Quit
Four different situations look similar and need different keys.
- You typed a line you do not want.
Ctrl+Cin Bash, zsh, and PowerShell abandons it and gives you a fresh prompt.Escdoes the same in Command Prompt and in PSReadLine’s Windows mode. - A command is running and you want it to stop.
Ctrl+Casks the program to stop. Most programs comply; Chapter 9 covers the ones that do not. - A program is waiting for input and you have finished.
Ctrl+Don UNIX andCtrl+Zthen Enter in Command Prompt send end of input. At an empty Bash or zsh prompt,Ctrl+Dexits the shell, which surprises people. - A program has taken over the screen. Pagers exit with
q, nano withCtrl+X, and Vim withEscthen:q. Chapters 5 and 6 cover them.
Ctrl+Z at a UNIX prompt does not undo anything. It suspends the running program, which Chapter 9 explains; if you press it by accident, fg brings the program back.
4.8 Key Points
- Each shell has its own line editor with its own defaults: Readline, ZLE, PSReadLine, or the Windows console.
- A shortcut belongs to the terminal, the terminal driver, the shell, or the running program, and that owner is where to look when it does not work.
Ctrl+A,Ctrl+E,Ctrl+U,Ctrl+K,Ctrl+W, andCtrl+Yedit the line in Emacs-mode editors; PSReadLine’s Windows mode uses editor-style keys instead.Ctrl+Rsearches history in every shell covered here except Command Prompt.Tabcompletes names, and the shells differ in whether they list or cycle.- Backslash, backtick, and caret continue a line in Bash/zsh, PowerShell, and Command Prompt.
Ctrl+Ccancels,Ctrl+Dends input,Ctrl+Zsuspends on UNIX, andCtrl+Qunfreezes a terminal paused byCtrl+S.
4.9 Level Up
n00bs finish the chapter here. You can edit a line without retyping it, find an old command, and complete names instead of spelling them. Hackers start bending the editor to their habits.
Print your editor’s full binding list and read it: bind -p in Bash, bindkey in zsh, and Get-PSReadLineKeyHandler in PowerShell. Find three bindings you did not know and try them.
Each editor has a vi mode that uses Vim’s keys instead of Emacs keys: set -o vi in Bash, bindkey -v in zsh, and Set-PSReadLineOption -EditMode Vi in PowerShell. Try it for a session after Chapter 5 introduces Vim, and decide which mode fits you.
Investigate fzf, a fuzzy finder that replaces Ctrl+R with an interactive search over history and can complete paths the same way. Explain what it adds beyond the built-in search, and what it costs in setup.
Look at PSReadLine’s predictive IntelliSense, which suggests commands from history as you type, and at zsh’s zsh-autosuggestions plugin, which does the same. What data do they use, and where is it stored?
4.10 Exercises
- What does this do? In Bash, type
echo alpha beta gamma, then pressCtrl+W,Ctrl+A,Ctrl+Y. Predict the line before you look. - What does this do? Run
echo helloand thenecho !!in Bash. Explain each line of output, including the one the shell prints before running the second command. - What is the problem? A PowerShell user on Windows presses
Ctrl+Aexpecting the cursor to jump to the start of the line, and the whole line is highlighted instead. Explain what happened and give two ways to get the cursor movement they wanted. - What is the problem? A terminal stops responding after a user tries to save with
Ctrl+S. Nothing appears, but the program is not hung. Explain what happened and how to fix it. - Why is it like this?
Ctrl+Cis copy in most desktop programs but cancel in a terminal. Explain which program decides, and why the terminal applications in Chapter 1 useCtrl+Shift+Cfor copy. - Why is it like this?
Get-Historyin PowerShell shows only this session’s commands, but Up Arrow recalls commands from last week. Explain which component owns each list. - How do you rerun the command before last with one argument changed, in Bash, without retyping it? Give two methods.
- How do you find out which key deletes the word before the cursor in your current PowerShell edit mode, without reading this chapter?