Thursday, October 6, 2011

Avoid the escape key

SkyHi @ Thursday, October 06, 2011

created 2002 · complexity basic · author David A. Rogers · version 6.0

This tip discusses how to exit from insert mode without needing to press Esc. The Vi editor was originally written on an ADM-3A terminal, which had the Escape key in place of the Tab key (compared to most modern keyboards). Many touch typists appreciate the fact that they can leave their hands on the keyboard home row while using Vim, so there are several ideas for avoiding the Esc key at its current location (pressing Esc generally requires stretching to the top of the keyboard).
No utility programs or operating system tweaks are required for this tip. For other suggestions involving mapping keys with the operating system or utilities, see Map caps lock to escape in XWindows (for Unix-based systems), or Map caps lock to escape in Windows (for Windows). Some of the suggestions involve more than avoiding escape; topics also discussed include using the CapsLock key for Ctrl, and avoiding irritations from accidental use of CapsLock.



    Avoiding the Esc keyEdit

    Pressing Ctrl-[ (control plus left square bracket) is equivalent to pressing Esc. On a US keyboard, pressing Ctrl-[ is an easy way to exit from insert mode.
    Alternatively, simply press Ctrl-c to quit insert mode (however, Ctrl-c does not expand abbreviations).:help i_CTRL-C


    It can be convenient to use a mapping so that pressing a key, or sequence of keys, generates Escape. The:imap command is used to create the mapping so that it only applies while in insert mode.
    For example, the following allows you to press jj to exit from insert mode:
    :imap jj <esc>
    To generate Escape, jj has to be typed quickly. :help 'timeout'
    A problem with mapping a sequence like jj is that Vim will pause whenever you type j in insert mode (it is waiting for the next key to determine whether to apply the mapping). The pause is merely a visual distraction which you may not notice, and it does not slow down typing.
    For simplicity, we will show :imap but careful Vimmers are in the habit of using :inoremap which does not attempt to interpret the result of the mapping (with the :imap command, the result is scanned to see whether it contains another mapping).

    Alternative mappingsEdit

    Here are some alternative suggestions:
    " Press i to enter insert mode, and ii to exit.
    :imap ii <esc>
    " Use backtick.
    :imap ` <esc>
    " Two semicolons are easy to type.
    :imap ;; <esc>
    " Press Shift-Space (may not work on your system).
    :imap  <esc>
    " Try the following so Shift-Space also enters insert mode.
    :nmap  i
    " Or just Space to enter insert mode.
    :nmap  i
    " In Mac OS X, mapping  does not work, but the following
    " is better (press the "apple" key and the space key).
    " Note that this will conflict with the spotlight shortcut
    :imap  <esc>
    " On gvim and Linux console Vim, you can use Alt-Space.
    :imap  <esc>

    Using the Tab keyEdit

    With the following in your vimrc, you can press Tab to return to normal mode:
    nnoremap  <esc>
    vnoremap  <esc>gV
    onoremap  <esc>
    inoremap  <esc>`^
    In normal mode, you can press prefix keys before a command (for example, 12 for a count). The nnoremapcauses Tab to cancel any prefix keys.
    The vnoremap causes Tab to cancel any selection (gV is required to prevent automatic reselection).
    The onoremap causes Tab to cancel any operator-pending command (for example, y).
    The first inoremap causes Tab to exit insert mode, and the `^ restores the cursor position so exiting insert does not move the cursor left.
    The second inoremap, assuming the default leader key, allows you to press \ then Tab to insert a tab character. You may prefer an alternative mapping to make it easier to insert a tab. For example, on some systems, you may be able to use Alt-Tab to insert a tab character with:
    Some plugins may remap the Tab key. To remap them back from .vimrc, use autocmd:
    au VimEnter * map  <esc>
    au VimEnter * imap  <esc>
    au VimEnter * vmap  <esc>
    Due to the way that Vim read keys, Ctrl-i is the same as Tab. Therefore, you cannot map Tab to generate Escape,and map Ctrl-i to do something different.
    When adjusting indents, you can avoid tabs altogether:
    • In normal mode: Type << to shift the line left one 'shiftwidth', or >> to shift right (and press . to repeat).
    • In insert mode: Press Ctrl-d to shift left, or Ctrl-t to shift right.

    Using the Enter keyEdit

    It's very easy to exit insert mode using the Enter key:
    :inoremap  <esc>
    An example of using the above would be to type ce to change to the end of a word, then type new text, then press Enter to return to normal mode.
    When you want to enter a newline, you may find that Shift-Enter or Ctrl-Enter works (it should always work in gvim, but might not in a terminal, depending upon your system). If your Shift-Enter or Ctrl-Enter works, and you can get used to it, the above might be all you need.
    An alternative would be to map Shift-Enter to generate Escape:
    :inoremap  <esc>
    Then Enter will always work as expected, and Shift-Enter will always exit insert mode. If Shift-Enter does not work on your system, you might find that Ctrl-Enter () does.
    Another, more elaborate, alternative is:
    function! ToggleEnterMapping()
      if empty(mapcheck('', 'i'))
        inoremap  <esc>`^
        return "\<esc>"
        return "\"
    call ToggleEnterMapping()
    inoremap   ToggleEnterMapping()
    " Optional (so  cancels prefix, selection, operator).
    nnoremap  <esc>
    vnoremap  <esc>gV
    onoremap  <esc>
    • Initially, pressing Enter returns to normal mode.
    • In insert mode, pressing Shift-Enter enters "multiline" mode, meaning that pressing Enter will insert a newline.
    • In insert mode, after pressing Shift-Enter to enter "multiline" mode, pressing Shift-Enter again exits (returns to normal mode).
    The mapcheck() function returns the current insert-mode mapping for  (Enter). The empty() function returns nonzero (true) if there is no such mapping.
    The inoremap  command maps Shift-Enter to generate the expression returned by callingToggleEnterMapping() (the code for either Escape or Enter). Calling the function toggles the insert-mode mapping for Enter: if it is mapped, it is unmapped; otherwise it is mapped to <esc>`^ (generate Escape then go to the ^ mark).

    Toggling insert modeEdit

    Press Ctrl-Space to start and to stop insert mode (the same suggestion using Shift-Space is above):
    nnoremap  i
    imap  <esc>
    Or you may prefer to map Ctrl-Space to a rather than i so that repeatedly pressing Ctrl-Space does not move the cursor back (remember that pressing I allows you to insert a character at the beginning of the line):
    nnoremap  a
    imap  <esc>
    An alternative follows. It uses /i to toggle insertion at the cursor, and /a to toggle insertion at the end of the line. If you use /i (or /a) to insert, you must /i (or /a) to exit (not Esc).
    nnoremap  /i :let &insertmode=1-&insertmode
    inoremap  /i <esc>:let &insertmode=1-&insertmode
    nnoremap  /a :let &insertmode=1-&insertmodeif &insertmode:startinsert!endif
    inoremap  /a <esc>:let &insertmode=1-&insertmodeif &insertmode:startinsert!endif
    Probably can use :set insertmode! to toggle.
    The / is easy to type, but did you mean to use ? Also, why toggle 'insertmode'? Why not the following (and similar for append):
    nnoremap i i
    inoremap i <esc>

    Improving the Esc keyEdit

    You may not find attempts to replace the Esc key satisfactory. However, if you don't like the cursor moving left when you exit from insert mode, you may want to try this variation from the Tab key section above:
    inoremap <esc> <esc>`^
    The above trick means that the cursor will not move if you press i to enter insert mode, then press Esc to exit. However, pressing a (append) then Esc will move the cursor, so this "improvement" may not satisfy you.

    Command-Line ModeEdit

    If you want to map another key to Esc in command-line mode, if you attempt a mapping like
    cmap  <esc>
    the resulting mapping will submit the command-line as if pressing Return rather. To create a mapping to act like Esc in command-line mode, you must map to  instead.

    Mapping problemsEdit

    Vim runs on many different hardware and software platforms. Therefore some key sequences may not be available. For example, you may be able to map Shift-Space in a GUI Vim, but not in a terminal Vim (and even if you could, if you were running via PuTTY, for example, Vim might not receive the key code).
    To test your system, enter insert mode then press Ctrl-K followed by the key of interest (for example, press Ctrl-K then Shift-Space). :help i_CTRL-K

    Related tipsEdit

    The following advises using  instead of <esc> in insert mode mappings.
    The following are not related to the Esc key. They try to avoid CapsLock applying in normal mode (so you can insert text in uppercase when needed, but not type in uppercase after exiting insert mode).


    Use META +
    Depending on your terminal and vim settings it is possible that ^[ is sent firstly while you are pressing META(Alt)+. So during Insert mode you can press META+j to finish editing, return to Normal mode and move to the next line.


    vi/vim delete current to end of line

    SkyHi @ Thursday, October 06, 2011
     vi delete commands FAQ: Can you share some example "vi delete" commands?

    The vi editor can be just a little difficult to get started with, so I thought I'd share some more vi commands here today, specifically some commands about how to delete in vi.

    vi delete commands - reference

    A lot of times all people need is a quick reference, so I'll start with a reference of vi/vim delete commands:
    x   - delete current character
    dw  - delete current word
    dd  - delete current line
    5dd - delete five lines
    d$  - delete to end of line
    d0  - delete to beginning of line
    delete to beginning of file
    delete current to end of file
    If those don't make sense on their own, here's a brief description of each vi delete command.

    vi delete character command

    When you're in command mode in the vi editor (just hit the [Esc] key and you'll be there), and you want to delete the character at the current cursor position, just use the vi delete character command -- the lowercase letter 'x' -- like this:
    As mentioned, that deletes the character at your current cursor position. If you want to delete ten characters you can press the letter 'x' ten times, or you can use this command instead:

    vi delete word commands

    When you're in command mode in the vi editor and you want to delete the current word, use the vi delete word command:
    Just like the delete character command, if you want to delete the next five words, just precede the dw command with the number 5, like this:

    vi delete line commands

    When you're in command mode in the vi editor and you want to delete the current line, use the vi delete line command:
    Just like the delete character and delete word commands, if you want to delete the next five lines, just precede the dd command with the number 5, like this:

    delete to end of line or beginning of line

    To delete all the characters from your current cursor position to the beginning of the current line, use the d0 command, like this:
    Similarly, to delete from your current cursor position to the end of the current line, use the d$ command, like this:
    Whenever you're working with vi, the letter '0' typically refers to the beginning of the current line or the beginning of the file, and the '$' character typically refers to the end of the current line or end of file, so I find these commands fairly easy to remember.

    delete to beginning or end of file

    To delete all the lines from the beginning of the file to your current cursor position, use this command:
    That command can be read as "From line 1 to the current position, delete", or if you prefer, "Delete from line 1 to the current line position."
    Similarly, to delete everything from the current line to the end of the file, use this vi delete command:
    Again, that can be read as "From the current position to the end of file, delete."

    My vi/vim delete video tutorial

    If you'd like to see many of these vi/vim delete commands put to work, I've created thisvi/vim delete commands video tutorial on YouTube