How to skip words in OS X terminal?

Let's say I wrote a long command in the Mac OSX terminal, i.e

say "Hello, how are you? I am good thank you. How is it going with you? Fine, thanks"

and now I want to change the word Hello to Hi.

To do that, right now I have to keep pressing (or hold down) the left keyboard key until the "cursor" gets to the end of the word Hello, and then delete it. The usual 'holding down option' technique doesn't work as it does in most other OS X applications.

Is there a way to skip a word at a time instead (or any other shorter way of getting the cursor there)?


Solution 1:

Command line editing is a function of your shell, not of Terminal. Probably your shell is bash and probably its command line editing style is set to “emacs”.

Here are a few of the Emacs-style key combinations that you might find handy:

  • C-a: beginning-of-line
  • C-e: end-of-line
  • M-f: forward-word
  • M-b: backward-word
  • C-d: delete-char
  • M-d: kill-word (delete the next ‘word’)
  • M-DEL: backward-kill-word

C-x means Control+x, so C-a is Control+a.

M-x means Meta+x, but there probably is no Meta key on your keyboard. So instead, you can use ESC x (i.e. Escape then x). Terminal has an setting to automatically send ESC before keys pressed with Option held down. Using this feature disables the extended character handling that Mac OS X usually provides when using the Option modifier. So, if you use few extended characters and want to have Option+x send ESC x, then you can enable this Terminal option.

There are lots of ways of moving to “Hello” in your example:

  • Search for “Hello”: C-r H e l l o C-j (or ESC)
    • In normal Emacs, you would just use RET (Return) to end the search at the current location and return to editing. But in bash, the default bindings cause RET (i.e. C-m) to always execute the current line, even if an incremental search is active. So the C-j/ESC part is a deviation from normal Emacs.
  • Jump to the beginning of the line and move forward: C-a M-f C-f (or )
  • Jump to the beginning of the line, then move by words: C-a M-f M-f M-b
  • Use M-b a lot (only really feasible if you map Option to Meta).

There are also several ways of accomplishing your desired replacement:

  • delete the word and replace it: M-d H i
  • delete characters and replace them: C-d C-d C-d C-d C-d H i
  • move past “H” and delete the following work, replace it: C-f M-d i
  • move past “H” and delete the remaining characters, replace them: C-f C-d C-d C-d C-d i

If you stopped at the end of the word (maybe via C-a M-f M-f), you could use M-DEL H i.

You might do something like bind -P | less to find other interesting bindings. Consult the readline section of the bash man page (or the readline parts of the bash info pages) for details.

Solution 2:

The default readline binding for forward-word is Meta-F (bash(1) man page, READLINE section, Commands for Moving subsection). I'm not sure what Meta translates to in OS X though. Option, perhaps.