2 Comments

Improving Command Line Productivity with GNU Readline

I spend a lot of my day working on the command line, from file navigation to version control to remote work on servers over SSH, and anywhere in between. I’ve found that even small improvements to my workflow significantly add up over time to provide big productivity boosts.

Recently, I realized that some features I’d become accustomed to were part of the GNU Readline library. Today, I’d like to share a few very simple Readline tools that I’ve picked up over time and continue to use.

Keyboard Shortcuts

As an Emacs-turned-Vim user, one thing that I’ve stubbornly held onto is using keyboard shortcuts. GNU Readline provides some great tools to move the cursor around, manage a kill ring, and more.

Setup

There are typically two modes: emacs and vi. To specify one or the other, run: set -o vi or set -o emacs (I will explain later how to persist this choice). Choose whatever is more comfortable for you.

While I typically use Vim as my editor of choice, I still use Emacs Readline mode. Many other applications have hooks for it (even this WordPress editor!), and I like to keep the muscle memory fresh in my mind.

Favorites

Here are some of the shortcuts I commonly use:

  • CTRL-a: move cursor to the beginning of line
  • CTRL-e: move cursor to the end of line
  • CTRL-d: delete a character
  • CTRL-f: move cursor forward (→)
  • CTRL-b: move cursor backward (←)
  • CTRL-p: previous line, previous command in history (↑)
  • CTRL-n: next line, next command in history (↓)
  • CTRL-k: kill the line after the cursor, add to clipboard
  • CTRL-u: kill the line before the cursor, add to clipboard
  • CTRL-y: paste from the clipboard
  • ALT-b: move cursor back one word
  • ALT-f: move cursor forward one word

While seeing all of these shortcuts (not even my whole list) may seem overwhelming at first glance, if you continue to use them, they will become like second nature.

These shortcuts are especially useful on my laptop, which doesn’t have home, end, or delete keys. Frequently, I will start writing a command, decide I’m not ready for it, CTRL-u to kill it and store it in the clipboard, run another command, and CTRL-y to put back the command I just deleted.

Long Commands

While technically, this next shortcut is part of the GNU Readline library, it’s so useful that I wanted to talk about it on its own. If you ever find yourself writing long commands (I just checked–my longest command was 811 characters), this is for you.

On the command line, press CTRL-x CTRL-e. That is, hold down control, and press x, then e. This brings up an editor to type whatever you like, and it will execute the command(s) when closed. If you have already typed something, do not fear. CTRL-x CTRL-e will populate the editor with what you’ve already typed in.

Alternatively, you can run the command fc, and it will open an editor with the most recently run command. You can also run fc with a number from history to load a specific command.

According to the Bash man page: “Bash attempts to invoke $FCEDIT, $EDITOR, and Emacs as the editor, in that order.” You can set those environment variables to whatever you like, including the path to GUI editor, if you prefer.

One benefit of writing commands in a text editor is that you can quickly save it to a file, if you want to create a script to reuse later.

Reverse Search

To search through history, press CTRL-r. This is very versatile, as you can search as far back as you store history. To start the search, press CTRL-r, start typing the search term, and press it again to move further back in history. When you have found the item you’re looking for, you can exit the search by moving the cursor or using the tab.

If you feel like you might want to use a certain command in the future, append a # at the end of the line to start a comment, and label it as you desire.

Persisting Options

If you want to save your Readline settings to persist them through more than one session, add them to ~/.inputrc. Mine is pretty simple:

$include /etc/inputrc
set completion-ignore-case On
set show-all-if-ambiguous On
set visible-stats On
set mark-directories On
set bell-style none
set editing-mode emacs
set completion-query-items 300

# perform alias expansion
"\C-xa": alias-expand-line
# Quote the current or previous word
"\C-xq": "\eb\"\ef\""
# edit the path
"\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f"

Near the end, you can see some custom keystrokes to perform an action. Here, you can use a default Readline function (such as alias-expand-line), or define your own.

To see what your current settings are, run the Bash builtin command bind -v, and bind -p to see the keybindings.

Readline is a fantastic library with endless possibilities for customization. I highly recommend checking out the “READLINE” section in the Bash man page, or reading the documentation here.