Skip to content
This repository has been archived by the owner on Aug 10, 2021. It is now read-only.
/ vim-galore-es Public archive

🎓 ¡Todo Sobre Vim! WIP

License

Notifications You must be signed in to change notification settings

UltiRequiem/vim-galore-es

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

No planeo continuar con esto, por falta de tiempo

El que quiera puede hacer un fork y continuar con el proyecto.


Intro

¿Qué es Vim?

Vim es un editor de texto con una larga linea de antecesores que viene desde qed. Bram Moolenaar hizo el lanzamiento de la primera versión en 1991.

El proyecto esta hospeado en vim.org.

Obteniendo Vim: Usa tu manejador de paquetes favorito o visita la pagina de descarga.

Discuciones o preguntas de usuario son bien respondidas en vim_use o usando IRC (Freenode) en el canal #vim.

El desarrollo sucede en GitHub, y las discusiones en vim_dev.

Lee Why, oh WHY, do those #?@! nutheads use vi? para saber los basicos de vim.

La filosofia de Vim

Vim se adiere a la filosofia de editor modal. Esto significa que los atajos hacen cosas diferentes segun en el modo que estes. Tu te mueves entre archivos en normal mode, insertas texto en insert mode, seleccionas lineas en visual mode y ejecutas comandos en command-line mode. Esto tal vez suena complicado al inicio, pero tiene un gran ventaja: No tendras que romper tu flujo de escritura solo para seleccionar texto o editar alguna parte.

Un conecepto que funciona bien con la edición modal son operadores y mociones. Operadores comenzar cierta acción, e.g. cambiar, remover, o seleccionar texto. Después que especificas la región de texto con que vas a interctuar viene la moción. Para cambiar todo lo que este entre parentesis usa ci( (lee change inner parentheses). Para remover un parrafo entero , usa dap (read delete around paragraph).

Si ve usuarios avanzados de Vim trabajando, notará que hablan el lenguaje de Vim así como los pianistas manejan sus instrumentos. Complejas operaciones se realizan con sólo pulsar unas pocas teclas. Ni siquiera lo piensan ya que su memoria muscular ya sabe que hacer. Esto reduce la carga mental y ayuda a centrarse en la tarea principal.

Primeros pasos

Vim viene con un tutorial interactivo que enseña las cosas basicas que necesitas saber. Puede iniciarlo desde su terminal:

$ vimtutor

No se desanime por lo aburrido que parece y resuelva los ejercicios. Los editores o IDE que usaste antes eran probablemente todos no modales, por lo que cambiar de modo parecerá incómodo al principio, pero cuanto más use Vim, más se guardara en su memoria muscular.

Vim esta muy fuertemente ligado a Stevie, cual es un clon de vi, y admite dos modos de funcionamiento: "compatible" y "nocompatible". Usar Vim en modo compatible significa usar los valores predeterminados de vi, muy diferentes a los por defecto de Vim. Hasta que no crees un vimrc o inicie Vim con vim -N, el modo compatible es asumido! ¡No use Vim en modo compatible!

Siguientes pasos:

  1. Crea tu propio vimrc.
  2. Ten algunas cheatsheets listas para las primeras semanas.
  3. Lea la sección de conceptos basicos para saber qué es posible.
  4. ¡Aprenda bajo demanda! Nunca terminas de aprender Vim. Si encuentra algun problemas, búsquelo en Internet. Tu problema seguro que ya fue resuelto. Vim viene con una gran documentación y saber cómo navegar es imprescindible: Obteniendo ayuda offline.
  5. Echale un ojo a los recursos adicionales.

Un ultimo aviso: Porfavor aprende como usar Vim de forma correcta antes de empezar a usar toda clases de plugins.

Basico vimrc

Puedes guardar tu configuración en ~/.vimrc o en aras de una mejor separación en ~/.vim/vimrc. Este último facilita la colocación de toda la configuración en un solo directorio, en el cual puede usar un manejador de versiones y subirlo a algun sito como GitHub.

Encontrarás muchos "vimrcs mínimos" en toda la red, y tal vez mi versión no sea tan mínimo como debería ser, pero proporciona un buen conjunto de ajustes cuerdos que considero útiles para empezar.

Finalmente, tendrá que leer todas las configuraciones mencionadas de todos modos y decidir para ti. :-)

Asi que aqui esta: minimal-vimrc

En caso de que te interese, aquí tienes mi vimrc.

SUGERENCIA: la mayoría de los autores de plugins mantienen varios plugins y también publican sus vimrc en GitHub (a menudo en un repositorio llamado "vim-config" o "dotfiles"), entonces siempre que encuentre un complemento que le guste, busque el perfil de GitHub de su mantenedor y busque en los repositorios.

¿Qué tipo de Vim estoy ejecutando?

Ejecutar :version le dará toda la información que necesita saber sobre cómo se compiló el binario de Vim que usted ejecuta actualmente.

La primera línea le dice cuándo se compiló el binario y la versión. Ej. 7.4. Una de las siguientes líneas dice Included patches: 1-1051. Por lo tanto, en este ejemplo su versión exacta de Vim es 7.4.1051.

Otra línea dice algo como Tiny version without GUI o Huge version with GUI. La información obvia de eso es si su Vim incluye GUI o no, ej. para iniciar gvim desde el shell o ejecutar : gui desde Vim dentro de un emulador de terminal. La otra información importante es el "Tiny" y "Huge". Vim distingue entre conjuntos de características llamadas tiny, small, normal, big, and huge, todos habilitando diferentes subconjuntos de características.

La mayor parte del output de :version es consumida por la propia lista de características. +clipboard significa que la función del portapapeles se compiló, mientras que -clipboard significa que no se compiló.

Es necesario compilar algunas características de Vim para que funcionen. ej. para que :prof funcione, necesita un Vim con un gran conjunto de funciones, porque ese conjunto permite la Característica +profile.

Si ese no es el caso e instaló Vim desde un administrador de paquetes, asegúrese de instalar un paquete llamado vim-x, vim-x11, vim-gtk, vim-gnome o similar, ya que estos paquetes generalmente vienen con un gran conjunto de funciones.

También puede probar la versión o las características mediante programación:

"Haga algo si ejecuta al menos Vim 7.4.42 con + perfil habilitado.
if (v:version > 704 || v:version == 704 && has('patch42')) && has('profile')
  " haga algo
endif

Ayuda:

:h :version
:h feature-list
:h +feature-list
:h has-patch

Cheatsheets

O abre rápidamente una hoja de trucos desde Vim: vim-cheat40.

Basicos

Buffers, ventanas, tabs

Vim es un editor de texto. Cada vez que el texto se muestra,el texto es parte de un buffer. Cada archivo sera abierto en su propio buffer. Los Plugins muestran sus cosas en sus propios buffers etc.

Los buffers tienen muchos atributos, ej.si el texto que contiene es modificable, o si está asociado con un archivo y, por lo tanto, debe sincronizarse con disco al guardar.

Windows son ventanas graficos sobre los buffers.Si tu quieres ver mucho archivos al mismo tiempo o incluso en el mismo en diferentes locaciones del archivo, debes usar Ventanas.

Y porfavor, no los llames splits. Tu puedes dividir una ventana en dos, pero eso no lo hace un split.

Las ventanas se pueden dividir vertical u horizontalmente y las alturas y anchos de las ventanas existentes también se pueden modificar. Por lo tanto, puede usar cualquier ventana diseño que prefieras.

Una tab page (o simplemente tab) es una colección de ventanas. Por lo tanto, si quieres use múltiples diseños de ventana, use pestañas.

En pocas palabras, si inicia Vim sin argumentos, tendrá una pestaña que contiene una ventana que muestra un búfer.

Por cierto, la lista de búfer es global y puede acceder a cualquier búfer desde cualquier pestaña.

Active, loaded, listed, named buffers

Vim ejecuta esto comovim file1. El contenido del archivo se cargará en un búfer. Tienes un búfer cargado ahora. El contenido del búfer solo se sincroniza al disco (escrito de nuevo en el archivo) si guardas dentro de Vim.

Dado que el búfer también se muestra en una ventana, también es un búfer activo. Ahora si carga otro archivo a través de :e file2, file1 se convertirá en un búfer oculto y file2 el bufér activo.

Ambos búferes también se enumeran, por lo que se enumerarán en la salida de :ls. Los búferes de complementos o los búferes de ayuda a menudo se marcan como no listados, ya que no son archivos normales que se sulen editar con un editor de texto.

Los Búferes sin nombre, que también suelen utilizar los complementos, son búferes que no tienen un nombre de archivo asociado. ej. :enew creará un búfer temporal sin nombre. Agregar algo de texto y escribirlo en el disco a través de :w/tmp/foo, y se convertirá en un nombre buffer.

Argument list

La lista global de buffers es una cosa de Vim. Antes, en vi, solo eran argumentos, que tambien estan dispoibles en Vim.

Cada nombre de archivo dado a Vim en la línea de comandos del shell, se recuerda en el lista de argumentos. Puede haber varias listas de argumentos: por defecto todos los argumentos se colocan en la lista de argumentos global, pero puede usar :arglocal para crear un nueva lista de argumentos que es local a la ventana.

Enumere los argumentos actuales con :args. Cambiar entre archivos del argumento lista con :next,:previous, :first,:last y similares. Alterna con :argadd,:argdelete o :args en una lista de archivos.

Si prefiere usar el búfer o la lista de argumentos para trabajar con archivos es una cuestión de gusto. Mi impresión es que la mayoría de la gente usa la lista de búfer exclusivamente.

Sin embargo, hay un gran caso de uso para la lista de argumentos: procesamiento por lotes a través de :argdo! Un ejemplo simple de refactorización:

:args **/*.[ch]
:argdo %s/foo/bar/ge | update

Esto reemplaza todas las apariciones de "foo" por "bar" en todos los archivos fuente y de encabezado de C desde el directorio actual y todos los que se encuentren dentro.

Ayuda: :h argument-list

Mappings

Puede definir sus propias asignaciones con la familia de comandos :map. Cada El comando de esa familia define un mapeo para un cierto conjunto de modos. Técnicamente Vim viene con 12 modos, 6 de ellos se pueden mapear. Además, algunos los comandos actúan en múltiples modos a la vez.

Recursivo No Recursivo Unmap Modos
:map :noremap :unmap normal, visual, operator-pending
:nmap :nnoremap :nunmap normal
:xmap :xnoremap :xunmap visual
:cmap :cnoremap :cunmap command-line
:omap :onoremap :ounmap operator-pending
:imap :inoremap :iunmap insert

Ej. Esto define el mapeo solo para el modo normal:

:nmap <space> :echo "foo"<cr>

Desmapearlo nuevamente usando :nunmap <space>.

Para ver algunos modos más, consulte : h map-modes.

Hasta aquí todo bien. Solo hay un problema que puede resultar bastante confuso para los principiantes::nmap es recursivo! Es decir, el lado derecho tiene en cuenta otras asignaciones.

Así que definiste un mapeo que simplemente hace echo de "Foo":

:nmap b :echo "Foo"<cr>

Pero, ¿qué sucede si desea asignar el comportamiento predeterminado de b (retrocediendo una palabra) a otra clave?

:nmap a b

Si presiona a, esperamos que el cursor retroceda una palabra, pero en su lugar "Foo" está impreso en la línea de comandos. Debido a que el lado derecho, b, era mapeado a otra acción, a saber :echo "Foo"<cr>.

La forma correcta de resolver este problema es utilizar un mapeo no recursivo en lugar de:

:nnoremap a b

Regla de oro: utilice siempre mapeos no recursivos a menos que realmente desee el recursivo.

Busque sus asignaciones sin dar un lado derecho. ej. :nmap muestra todo asignaciones normales y :nmap <leader> muestra todas las asignaciones normales que comienzan con el mapleader.

Si desea deshabilitar un mapeo estándar, asígnele <nop> al caracter, ej. :noremap <left> <nop>.

Ayuda: :h key-notation :h mapping :h 05.3

Mapleader

The mapleader is simply a placeholder than can be used with custom mappings and is set to \ por defecto.

nnoremap <leader>h :helpgrep<space>

This mapping is triggered by \h. If you want to use <space>h instead:

let mapleader = ' '
nnoremap <leader>h :helpgrep<space>

Moreover, there is <localleader> that is the local counterpart to <leader> and is supposed to be used for mappings that are local to the buffer, eg. filetype-specific plugins. It also defaults to \.

Note: Set the mapleaders before mappings! All leader mappings that are in effect already, won't change just because the mapleader was changed. :nmap <leader> will show all normal mode leader mappings with the mapleader resolved already, so use it to double-check your mappings.

See :h mapleader and :h maplocalleader for more.

Registers

Registers are slots that save text. Copying text into a register is called yanking and extracting text from a register is called pasting.

Vim provee los siguientes registros:

Tipo Caracter Filled by? Readonly? Contains text from?
Unnamed " vim [ ] Last yank or deletion. (d, c, s, x, y)
Numbered 0 to 9 vim [ ] Register 0: Last yank. Register 1: Last deletion. Register 2: Second last deletion. And so on. Think of registers 1-9 as a read-only queue with 9 elements.
Small delete - vim [ ] Last deletion that was less than one line.
Named a to z, A to Z user [ ] If you yank to register a, you replace its text. If you yank to register A, you append to the text in register a.
Read-only :, ., % vim [x] :: Last command, .: Last inserted text, %: Current filename.
Alternate buffer # vim [ ] Most of the time the previously visited buffer of the current window. See :h alternate-file
Expression = user [ ] Evaluation of the VimL expression that was yanked. E.g. do this in insert mode: <c-r>=5+5<cr> and "10" will be inserted in the buffer.
Selection +, * vim [ ] * and + are the clipboard registers.
Drop ~ vim [x] From last drag'n'drop.
Black hole _ vim [ ] If you don't want any other registers implicitly affected. E.g. "_dd deletes the current line without affecting registers ", 1, +, *.
Last search pattern / vim [ ] Last pattern used with /, ?, :global, etc.

Each register that is not readonly can be set by the user:

:let @/ = 'register'

Afterwards n would jump to the next occurrence of "register".

There are numerous exceptions when registers get implicitly filled, so be sure to read :h registers.

Yank with y and paste with p/P, but mind that Vim distinguishes between characterwise and linewise visual selections. See :h linewise.

Example: linewise

yy (or just Y) yanks the current line, move the cursor somewhere else, use p to paste below the current line P for pasting above it.

Example: charwise

Yank the first word with 0yw, move somewhere else, paste after the cursor on the current line with p and before the cursor with P.

Example: explicit naming of register

"aY yanks the current line into register a. Move to another line. "AY appends the current line to register a.

I suggest playing around with all these registers a bit and constantly checking :reg, so you can see what's actually happening.

Fun fact: In Emacs "yanking" stands for pasting (or reinserting previously killed text) not copying.

Ranges

Ranges are pretty easy to understand, but many Vimmers don't know about their full potential.

  • Many commands take ranges.
  • An address denotes a certain line.
  • A range is either a single address or a pair of addresses separated by either , or ;.
  • Ranges tell commands which lines to act on.
  • Most commands act only on the current line por defecto. Notable exceptions are :write and :global which act on all lines.

The usage of ranges is pretty intuitive, so here are some examples (using :d as short form of :delete):

Command Lines acted on
:d Current line.
:.d Current line.
:1d First line.
:$d Last line.
:1,$d All lines.
:%d All lines (syntactic sugar for 1,$).
:.,5d Current line to line 5.
:,5d Also current line to line 5.
:,+3d Current line and the next 3 lines.
:1,+3d First line to current line + 3.
:,-3d Current line and the last 3 lines. (Vim will prompt you, since this is a reversed range.)
:3,'xdelete Lines 3 to the line marked by mark x.
:/^foo/,$delete From the next line that starts with "foo" to the end.
:/^foo/+1,$delete From the line after the line that starts with "foo" to the end.

Note that instead of ,, ; can be used as a separator. The difference is that in the case of from,to, the to is relative to the current line, but when using from;to, the to is relative to the address of from! Assuming you're on line 5, :1,+1d would delete lines 1 to 6, whereas :1;+1d would only delete lines 1 and 2.

The / address can be preceded with another address. This allows you to stack patterns, e.g.:

:/foo//bar//quux/d

This would delete the first line containing "quux" after the first line containing "bar" after the first line containing "foo" after the current line.

Sometimes Vim automatically prepends the command-line with a range. E.g. start a visual line selection with V, select some lines and type :. The command-line will be populated with the range '<,'>, which means the following command will use the previously selected lines as a range. (This is also why you sometimes see mappings like :vnoremap foo :<c-u>command. Here <c-u> is used to remove the range, because Vim will throw an error when giving a range to a command that doesn't support it.)

Another example is using !! in normal mode. This will populate the command-line with :.!. If followed by an external program, that program's output would replace the current line. So you could replace the current paragraph with the output of ls by using :?^$?+1,/^$/-1!ls. Fancy!

Help:

:h cmdline-ranges
:h 10.3

Marks

You use marks to remember a position, that is line number and column, in a file.

Marks Set by.. Usage
a - z User Local to file, thus only valid within one file. Jumping to a lowercase mark, means jumping within the current file.
A - Z User Global, thus valid between files. Also called file marks. Jumping to a file mark may switch to another buffer.
0 - 9 viminfo 0 is the position when the viminfo file was written last. In practice this means when the last Vim process ended. 1 is the position of when the second last Vim process ended and so on.

Put '/g' or `/g` in front of a mark to form a motion.

Use mm to remember the current position with mark "m". Move around the file and then jump back via 'm (first non-blank) or `m (exact column). Lowercase marks will be remembered after exiting Vim, if you tell your viminfo file to do so, see :h viminfo-'.

Use mM to remember the current position with file mark "M". Switch to another buffer and switch back via 'M or `M.

Other motions include:

Motion Jump to..
'[, `[ First line or character of previously changed or yanked text.
'], `] Last line or character of previously changed or yanked text.
'<, `< Beginning line or character of last visual selection.
'>, `> Ending line or character of last visual selection.
'', `` Position before the latest jump.
'", `" Position when last exiting the current buffer.
'^, `^ Position where last insertion stopped.
'., `. Position where last change was made.
'(, `( Start of current sentence.
'), `) End of current sentence.
'{, `{ Start of current paragraph.
'}, `} End of current paragraph.

Marks can also be used in a range. You probably saw this before and wondered what it means: Select some text in visual mode and do :, the command-line will be prepended with :'<,'>, which means the following command would get a range that denotes the visual selection.

Use :marks to list all marks. Read everything in :h mark-motions.

Completion

Vim provides many kinds of insert mode completions. If there are multiple matches, a popup menu will let you navigate to the match of your choice.

Typical kinds of completion are tags, functions from imported modules or libraries, file names, dictionary or simply words from the current buffer.

Vim provides a mapping for each kind of completion and they all start with <c-x> (remember to use them in insert mode):

Mapping Kind Help
<c-x><c-l> whole lines :h i^x^l
<c-x><c-n> keywords from current file :h i^x^n
<c-x><c-k> keywords from 'dictionary' option :h i^x^k
<c-x><c-t> keywords from 'thesaurus' option :h i^x^t
<c-x><c-i> keywords from current and included files :h i^x^i
<c-x><c-]> tags :h i^x^]
<c-x><c-f> file names :h i^x^f
<c-x><c-d> definitions or macros :h i^x^d
<c-x><c-v> Vim commands :h i^x^v
<c-x><c-u> user defined (as specified in 'completefunc') :h i^x^u
<c-x><c-o> omni completion (as specified in 'omnifunc') :h i^x^o
<c-x>s spelling suggestions :h i^Xs

People might be confused about the difference between user defined completion and omni completion, but technically they do the same thing. They take a function that inspects the current position and return a list of suggestions. User defined completion is defined by the user for their own personal purposes. (Surprise!) It could be anything. Omni completion is meant for filetype-specific purposes, like completing struct members or class methods, and is often set by filetype plugins.

Vim also allows for completing multiple kinds at once by setting the 'complete' option. por defecto that option includes quite a lot, so be sure to trim it to your taste. You can trigger this completion by using either <c-n> (next) and <c-p> (previous), which also happen to be the keys used for choosing entries in the popup menu. See :h i^n and :h 'complete' for more on this.

Be sure to check out :h 'completeopt' for configuring the behaviour of the popup menu. The default is quite sane, but I prefer adding "noselect" as well.

Help:

:h ins-completion
:h popupmenu-keys
:h new-omni-completion

Motions, operators, text objects

Motions move the cursor. You all know h/j/k/l. Or w and b. Even / is a motion. They also take a count. 2?the<cr> jumps to the second last occurrence of "the".

See :h navigation and everything below for all available motions.

Operators act on a region of text, e.g. d, ~, gU, > to name just a few. They get used in two contexts, either in normal or visual mode. In normal mode, operators come first followed by a motion, e.g. >j. In visual mode, operators simply act on the selection, e.g. Vjd.

Like motions, operators take a count, e.g. 2gUw makes the rest of the current word and the next one uppercase. Since motions and operators take counts, 2gU2w works just as well and executes gU2w twice.

See :h operator for all available operators. Use :set tildeop to make ~ act as an operator.

Text objects act on the surrounding area, opposed to motions that act into one direction. Actually they work on objects, e.g. a whole word, a whole sentence, everything between parentheses, and so on.

Text objects can't be used to move the cursor in normal mode, because even the most-skilled cursors can't jump into two directions at the same time. It works in visual mode though, because then one side of the object is already selected and the cursor simply jumps to the other side.

Text objects start with either i (think inner) or a (think around) followed by a character denoting the object. With i it only acts on the object itself, with a on the object plus trailing whitespace. E.g. diw deletes the current word and ci( changes everything between parentheses.

Text objects take a count. Imagine ((( ))) and the cursor on or between the most inner parentheses, then d2a( will remove the 2 inner pairs of parentheses and everything in between.

See :h text-objects for all available text objects.

Autocmds

You can trigger an action after many events in Vim, such as a buffer being saved or Vim having started up, by so-called autocmds.

Vim relies extensively on autocmds. Don't believe me? Check :au, but don't let the output overwhelm you. These are all the autocmds that are in effect right now!

See :h {event} for a quick overview of all available events and :h autocmd-events-abc for more details.

A typical example would be filetype-specific settings:

autocmd FileType ruby setlocal shiftwidth=2 softtabstop=2 comments-=:#

But how does a buffer even know that it contains Ruby code? Because another autocmd detected it as that and set the filetype accordingly which again triggered the FileType event.

One of the first things everyone adds to their vimrc is filetype on. This simply means that filetype.vim is read at startup which sets autocmds for almost all filetypes under the sun.

If you're brave enough, have a look at it: :e $VIMRUNTIME/filetype.vim. Search for "Ruby" and you'll find that Vim simply uses the file extension .rb to detect Ruby files:

NOTE: Autocmds of the same event are executed in the order they were created. :au shows them in the correct order.

au BufNewFile,BufRead *.rb,*.rbw  setf ruby

The BufNewFile and BufRead events in this case are hardcoded in the C sources of Vim and get emitted everytime you open a file via :e and similar commands. Afterwards all the hundreds of filetypes from filetype.vim are tested for.

Putting it in a nutshell, Vim makes heavy use of events and autocmds but also exposes a clean interface to hook into that event-driven system for customization.

Help: :h autocommand

Changelist, jumplist

The positions of the last 100 changes are kept in the changelist. Several small changes on the same line will be merged together, but the position will be that of the last change nevertheless (in case you added something in the middle of the line).

Every time you jump, the position before the jump is remembered in the jumplist. A jumplist has up to 100 entries. Each window has its own jumplist. When you split a window, the jumplist is copied.

A jump is one of the following commands: ', `, G, /, ?, n, N, %, (, ), [[, ]], {, }, :s, :tag, L, M, H and commands that start editing a new file.

List List all entries Go to older position Go to newer position
jumplist :jumps [count]<c-o> [count]<c-i>
changelist :changes [count]g; [count]g,

When you list all entries, a marker > will be used to show the current position. Usually that will be below position 1, the latest position.

If you want both lists to persist after restarting Vim, you need to use the viminfo file and :h viminfo-'.

NOTE: The position before the latest jump is also kept as a mark and can be jumped to via `` or ''.

Help:

:h changelist
:h jumplist

Undo tree

The latest changes to the text state are remembered. You can use undo to revert changes and redo to reapply previously reverted changes.

The important bit to understand it that the data structure holding recent changes is not a queue but a tree! Your changes are nodes in the tree and each (but the top node) has a parent node. Each node keeps information about the changed text and time. A branch is a series of nodes that starts from any node and goes up to the top node. New branches get created when you undo a change and then insert something else.

ifoo<esc>
obar<esc>
obaz<esc>
u
oquux<esc>

Now you have 3 lines and the undo tree looks like this:

     foo(1)
       /
    bar(2)
   /      \
baz(3)   quux(4)

The undo tree has 4 changes. The numbers represent the time the nodes were created.

Now there are two ways to traverse this tree, let's call them branch-wise and time-wise.

Undo (u) and redo (<c-r>) work branch-wise. They go up and down the current branch. u will revert the text state to the one of node "bar". Another u will revert the text state even further, to the one of node "foo". Now <c-r> goes back to the state of node "bar" and another <c-r> to the state of node "quux". (There's no way to reach node "baz" using branch-wise commands anymore.)

Opposed to this, g- and g+ work time-wise. Thus, g- won't revert to the state of node "bar", like u does, but to the chronologically previous state, node "baz". Another g- would revert the state to the one of node "bar" and so on. Thus, g- and g+ simply go back and forth in time, respectively.

Command / Mapping Action
[count]u, :undo [count] Undo [count] changes.
[count]<c-r>, :redo Redo [count] changes.
U Undo all changes to the line of the latest change.
[count]g-, :earlier [count]? Go to older text state [count] times. The "?" can be either "s", "m", "h", "d", or "f". E.g. :earlier 2d goes to the text state from 2 days ago. :earlier 1f will go to the state of the latest file save.
[count]g+, :later [count]? Same as above, but other direction.

The undo tree is kept in memory and will be lost when Vim quits. See Undo files for how to enable persistent undo.

If you're confused by the undo tree, undotree does a great job at visualizing it.

Help:

:h undo.txt
:h usr_32

Quickfix and location lists

The quickfix list is a data structure that holds file positions. Essentially, each entry in the quickfix list consists of a file path, a line number and optional column, and a description.

Typical use cases are assembling compiler errors or results of a grep tool.

Vim has a special type of buffer for showing the quickfix list: the quickfix buffer. Each line in the quickfix buffer shows one entry from the quickfix list.

Usually you open a new window to display the quickfix list: the quickfix window. When that happens, the last window gets associated with the quickfix window.

In the quickfix buffer <cr> opens the selected entry in the associated window and <c-w><cr> in a new window.

The quickfix list was named after the "quick fix" feature from the Aztec C compiler.

Actually there are two kinds of lists: quickfix and location lists. They behave almost the same, but have the follwing differences:

  • There is only one quickfix list. There can be multiple location lists; one per window.
  • They use slightly different commands for navigation.
Action Quickfix Location
open window :copen :lopen
close window :cclose :lclose
next entry :cnext :lnext
previous entry :cprevious :lprevious
first entry :cfirst :lfirst
last entry :clast :llast

Mind that the quickfix and location windows don't need to be open for these commands to work.

See :h quickfix for more information and a full list of commands.

For conciseness, quickfix and location are often abbreviated as qf and loc respectively.

Example:

Let us use our good old friend grep for searching the files in the current directory recursively for a certain query and put the results in the quickfix list.

:let &grepprg = 'grep -Rn $* .'
:grep! foo
<grep output - hit enter>
:copen

Assuming any files contained the string "foo", it should be shown now in the quickfix window.

Macros

Vim allows recording typed characters into a register. It's a great way to automate certain tasks on the fly. (For more elaborate tasks, Vim scripting should be used instead.)

  • Start recording by typing q followed by the register, e.g. q. (The command-line will signify this via "recording @q".)
  • Stop recording by hitting q once again.
  • Execute the macro via [count]@q.
  • Repeat the last used macro via [count]@@.

Example 1:

Insert a line and repeat it 10 times:

qq
iabc<cr><esc>
q
10@q

(The same could be done without macros: oabc<esc>10.)

Example 2:

For adding line numbers in front of all lines, start on the first line and add "1. " to it manually. Increment the number under the cursor by using <c-a>, displayed as ^A.

qq
0yf jP0^A
q
1000@q

Here we simply hope that the file doesn't contain more than 1000 lines when using 1000@q, but we can also use a recursive macro, which executes until the macro can't be applied to a line anymore:

qq
0yf jP0^A@q
q
@q

(The same could be done without macros: :%s/^/\=line('.') . '. ')

Mind that I also show how to achieve the same without using macros, but this mostly works only for such simple examples. For more complex automation, macros are the bomb!

Also see: Quickly edit your macros

Help:

:h recording
:h 'lazyredraw'

Colorschemes

Colorschemes are the way to style your Vim. Vim consists of many components and each of those can be customized with different colors for the foreground, background and a few other attributes like bold text etc. They can be set like this:

:highlight Normal ctermbg=1 guibg=red

This would paint the background of the editor red. See :h :highlight for more information.

So, colorschemes are mostly collections of :highlight commands.

Actually, most colorschemes are really 2 colorschemes! The example above sets colors via ctermbg and guibg. The former definition (cterm*) will only be used if Vim was started in a terminal emulator, e.g. xterm. The latter (gui*) will be used in graphical environments like gvim or MacVim.

If you ever happen to use a colorscheme in terminal Vim and the colors don't look like the ones in the screenshot at all, chances are that the colorscheme only defines colors for the GUI. Conversely, if you use a graphical Vim (e.g. gvim or MacVim) and the colors look off, the colorscheme might only define colors for the terminal.

The latter case can be "solved" by enabling true colors in Neovim or Vim 7.4.1830 and newer. This makes terminal Vim use the GUI definitions instead, but also requires the terminal emulator itself and all software in between (e.g. tmux) to be capable of handling true colors. (This gist gives a good overview about the topic.)

Help:

Folding

Every text (or source code) has a certain structure. If you have a structure, it means you have regions of logically separated text. Folding allows to "fold" such a region into a single line and displaying a short description. There are many commands that act on these regions called folds. Folds can be nested.

Vim distinguishes between several types of fold methods:

'foldmethod' Usage
diff Used in diff windows to fold unchanged text.
expr Uses 'foldexpr' to basically create a new fold method.
indent Folds based on indentation.
manual Create folds yourself via zf, zF, and :fold.
marker Folds based on markers in the text (often in comments).
syntax Folds based on syntax, e.g. folding if blocks.

NOTE: Folding can be computationally intensive! If you experience any performance drawbacks (small delays when typing), have a look at FastFold, which prevents Vim from updating folds when it's not needed.

Help:

:h usr_28
:h folds

Sessions

If you save a view (:h :mkview), the current state of the window (and options and mappings) gets saved for later use (:h :loadview).

A session saves the views of all windows plus global settings. It basically makes a snapshot of your current Vim instance and saves it in a session file. Let me stress this: it saves the current state; everything done after saving a session won't be part of the session file. To "update" a session, simply write it out again.

This makes it perfect for saving your projects and easy to switch between them.

Try it right now! Open a few windows and tabs and do :mksession Foo.vim. If you omit the filename, Session.vim will be assumed. The file will be saved to the current working directory, check :pwd. Restart Vim and do :source Foo.vim and voilà, the buffer list, window layout, mappings, working directory etc. should all be the same as before you saved the session. Do some more work and update the session by overwriting the already existing session file with :mksession! Foo.vim.

Note that a session file is really just a collection of Vim commands that are supposed to restore a certain state of a Vim instance, so feel free to take a look at it: :vs Foo.vim.

You can tell Vim what things to save in a session by setting 'sessionoptions'.

For scripting purposes Vim keeps the name of the last sourced or written session in the internal variable v:this_session.

Help:

:h Session
:h 'sessionoptions'
:h v:this_session

Locality

Many of the concepts mentioned above also have local counterparts:

Global Local Scope Help
:set :setlocal buffer or window :h local-options
:map :map <buffer> buffer :h :map-local
:autocmd :autocmd * <buffer> buffer :h autocmd-buflocal
:cd :lcd window :h :lcd
<leader> <localleader> buffer :h maplocalleader

Variables also have different scopes.

Usage

Getting help offline

Vim comes with great documentation in the form of single text files with a special layout. Vim uses a system based on tags for accessing certain parts of those help files.

First of all, read this: :help :help. This will open the file $VIMRUNTIME/doc/helphelp.txt in a new window and jump to the :help tag within that file.

A few simple rules:

  • options are enclosed in single quotes, e.g. :h 'textwidth'
  • VimL functions end in (), e.g. :h reverse()
  • commands start with :, e.g. :h :echo

You can use <c-d> (this is ctrl+d) to list all tags that match the currently entered query. E.g. :h tab<c-d> will get you a list of all tags from tab over 'softtabstop' to setting-guitablabel.

You want to list all VimL functions? Simple: :h ()<c-d>. You want to list all VimL functions that concern windows? :h win*()<c-d>.

This quickly becomes second nature, but especially in the beginning, you sometimes don't know any part of the tag you are looking for. You can only imagine some keywords that could be involved. :helpgrep to the rescue!

:helpgrep backwards

This will look for "backwards" in all documentation files and jump to the first match. The matches will be assembled in the quickfix list. Use :cn/:cp to jump to the next/previous match. Or use :copen to open the quickfix window, navigate to an entry and hit <cr> to jump to that match. See :h quickfix for the whole truth.

Getting help offline (alternative)

This list was compiled by @chrisbra, one of the most active Vim developers, and posted to vim_dev.

It's reposted here with minor changes.


If you know what you are looking for, it is usually easier to search for it using the help system, because the subjects follow a certain style guide.

Also, the help has the advantage of belonging to your particular Vim version, so that obsolete topics or topics that have been added later won't turn up.

Therefore, it is essential to learn the help system and the language it uses. Here are some examples (not necessarily complete and I might have forgotten something).

  1. Options are enclosed in single quotes. So you would use :h 'list' to go to the help topic for the list option. If you only know, you are looking for a certain option, you can also do :h options.txt to open the help page which describes all option handling and then you can search using regular expressions e.g. /width. Certain options have their own namespace, e.g. :h cpo-a, :h cpo-A, :h cpo-b, and so on.

  2. Normal mode commands are just that. Use :h gt to go to the help page for the "gt" command.

  3. Regexp items always start with "/", so :h /\+ takes you to the help item for the "+" quantifier in Vim regexes. If you need to know anything about regular expressions, start reading at :h pattern.txt.

  4. Key combinations. They usually start with a single letter indicating the mode for which they can be used. E.g. :h i_CTRL-X takes you to the family of CTRL-X commands for insert mode which can be used to auto complete different things. Note that certain keys will always be written the same, e.g. Control will always be CTRL. Note, for normal mode commands, the "n" is left away, e.g. :h CTRL-A. In contrast, :h c_CTRL-R will describe what CTRL-R does when entering commands in the command line and :h v_Ctrl-A talks about incrementing numbers in visual mode and :h g_CTRL-A talks about the g command (thus you have to press "g" then ). Here the "g" stand for the normal command "g" which always expect a second key before doing something similar to the commands starting with "z".

  5. Registers always start with "quote" so use :h quote to find out about the special ":" register.

  6. Vim script (VimL) is available at :h eval.txt. Certain aspects of the language are available at :h expr-X where 'X' is a single letter, e.g. :h expr-! will take you to the topic describing the '!' (Not) operator for VimL. Also important, see :h function-list to find a short description of all functions available.

  7. Mappings are talked about in the help page :h map.txt. Use :h mapmode-i to find out about the :imap command. Also use :map-topic to find out about certain subtopics particular for mappings (e.g. :h :map-local for buffer-local mappings or :h map_bar for how the '|' is handled in mappings.

  8. Command definitions are talked about at :h command-*, so use :h command-bar to find out about the '!' argument for custom commands.

  9. Window management commands always start with CTRL-W, so you find the corresponding help at :h CTRL-W_* (e.g. :h CTRL-W_p for switch to the previously accessed window). You can also access :h windows.txt and read your way through, if you are looking for window handling command.

  10. Ex commands always start with ":", so :h :s covers the ":s" command.

  11. Use CTRL-D after typing a topic and let Vim try to complete to all available topics.

  12. Use :helpgrep to search in all help pages (usually also includes help pages by installed plugins). See :h :helpgrep for how to use it. Once you have searched for a topic, all matches are available in the quickfix (or location) window which can be opened with :copen or :lopen. There you can also use / to further filter the matches.

  13. :h helphelp contains some information on how to use the help.

  14. The user manual. This describes help topics for beginners in a rather friendly way. Start at :h usr_toc.txt to find the table of content (as you might have guessed). Skimming over that help to find certain topics, .e.g you will find an entry "Digraphs" and "Entering special characters" in chapter 24 (so use :h usr_24.txt to go to that particular help page).

  15. Highlighting groups always start with hl-*. E.g. :h hl-WarningMsg talks about the "WarningMsg" highlighting group.

  16. Syntax highlighting is namespaced to ":syn-topic", e.g. :h :syn-conceal talks about the conceal argument for the :syn command.

  17. Quickfix commands usually start with ":c", while location list commands usually start with ":l".

  18. :h BufWinLeave talks about the BufWinLeave autocmd. Also, :h autocommands-events talks about all possible events.

  19. Startup arguments always start with "-", so :h -f takes you to the help of the "-f" command switch of Vim.

  20. Compiled extra features always start with "+", so :h +conceal talks about the conceal support.

  21. Error codes can be looked up directly in the help. :h E297 takes you exactly to the description of the error message. Sometimes however, those error codes are not described, but rather are listed at the Vim command that usually causes this. E.g. :h hE128 takes you directly to the :function command.

  22. Documentation for included syntax files is usually available at :h ft-*-syntax. E.g. :h ft-c-syntax talks about the C syntax file and the options it provides. Sometimes, additional sections for omni completion (:h ft-php-omni) or filetype plugins (:h ft-tex-plugin) are available.

Also, a link to the user documentation (which describes certain commands more from a user perspective and less detailed) will be mentioned at the top of help pages if they are available. So :h pattern.txt mentions the user guide topics :h 03.9 and :h usr_27.

Getting help online

If you have an issue you can't resolve or are in need of general guidance, see the vim_use mailing list. Another great resource is using IRC. The channel #vim on Freenode is huge and usually full of helpful people.

If you want to report a Vim bug, use the vim_dev mailing list.

Autocmds in practice

You can trigger any event right now: :doautocmd BufRead.

User events

Especially for plugins it's useful to create your own "User" events:

function! Chibby()
  " A lot of stuff is happening here.
  " And at last..
  doautocmd User ChibbyExit
endfunction

Now users of your plugin can execute anything when Chibby finishes running:

autocmd User ChibbyExit call ChibbyCleanup()

By the way, if there's no "catching" :autocmd, :doautocmd will output a pesky "No matching autocommands" message. That's why many plugins use silent doautocmd ... instead. But this has the disadvantage, that you can't simply use echo "foo" in the :autocmd, you have to use unsilent echo "foo" instead..

That's why it's better to check if there even is a receiving autocmd and not bothering emitting the event otherwise:

if exists('#User#ChibbyExit')
  doautocmd User ChibbyExit
endif

Help: :h User

Nested autocmds

por defecto, autocmds do not nest! If an autocmd executes a command, which in turn would usually trigger another event, it won't happen.

Let's say every time you start Vim, you want to automatically open your vimrc:

autocmd VimEnter * edit $MYVIMRC

When you now start Vim, it will open your vimrc, but the first thing you'll notice is that there won't be any highlighting although usually there would be.

The problem is that :edit in your non-nested autocmd won't trigger the "BufRead" event, so the filetype never gets set to "vim" and $VIMRUNTIME/syntax/vim.vim never sourced. See :au BufRead *.vim. Use this instead:

autocmd VimEnter * nested edit $MYVIMRC

Help: :h autocmd-nested

Clipboard

Required features: +clipboard and optionally +xterm_clipboard if you want to use the 'clipboard' option on a Unix system with a Vim that doesn't have GUI support.

Help:

:h 'clipboard'
:h gui-clipboard
:h gui-selections

Also see: Bracketed paste (or why do I have to set 'paste' all the time?)

Clipboard usage (Windows, macOS)

Windows comes with a clipboard and macOS comes with a pasteboard.

Both work like most users would expect them to work. You copy selected text with ctrl+c/cmd+c and paste them in another application with ctrl+v/cmd+v.

Note that copied text is actually transferred to the clipboard, so you can close the application you copied from before pasting in another application without problems.

Whenever this happens, the clipboard register * gets filled with the selection. From Vim use "*y and "*p to yank and paste from the clipboard respectively.

If you don't even want to specify the * register all the time, put this in your vimrc:

set clipboard=unnamed

Usually all yank/delete/put operations fill the " register, now the * register is used for the same operations, therefore simply y and p will be enough.

Let me repeat: Using the option above means that every yank/paste, even when only used in the same Vim window, will alter the clipboard. Decide for yourself if this is useful or not.

If you're even too lazy to type y, you can send every visual selection to the clipboard by using these settings:

set clipboard=unnamed,autoselect
set guioptions+=a

Help:

:h clipboard-unnamed
:h autoselect
:h 'go_a'

Clipboard usage (Linux, BSD, ...)

If your OS uses X, things work a bit different. X implements the X Window System Protocol which happens to be at major version 11 since 1987, hence X is also often called X11.

Prior, in X10, cut buffers were introduced that kind of worked like a clipboard as in copied text was actually held by X and it was accessible by all other applications. This mechanism still exists in X, but its use is deprecated now and most software doesn't use it anymore.

Nowadays data is transferred between applications by the means of selections. From the 3 selection atoms defined, only 2 are used in practice: PRIMARY and CLIPBOARD.

Selections work roughly like this:

Program A: <ctrl+c>
Program A: assert ownership of CLIPBOARD
Program B: <ctrl+v>
Program B: note that ownership of CLIPBOARD is hold by Program A
Program B: request data from Program A
Program A: respond to request and send data to Program B
Program B: receives data from Program A and inserts it into the window
Selection When used? How to paste? How to access from Vim?
PRIMARY Selecting text middle-click, shift+insert * register
CLIPBOARD Selecting text and ctrl+c ctrl+v + register

NOTE: Selections (no, not even the CLIPBOARD selection) are never kept in the X server! Thus, you lose the data copied with ctrl+c when the application closes.

Use "*p to paste the PRIMARY selection or "+y1G to yank the entire file to the CLIPBOARD selection.

If you happen to access one of the two registers all the time, consider using:

set clipboard^=unnamed      " * register
" or
set clipboard^=unnamedplus  " + register

(The ^= is used to prepend to the default value, :h :set^=.)

This will make all yank/delete/put operations use either * or + instead of the unnamed register ". Afterwards you can simply use y or p for accessing your chosen X selection.

Help:

:h clipboard-unnamed
:h clipboard-unnamedplus

Restore cursor position when opening file

When you open a file, the cursor will be positioned at line 1, column 1. Fortunately the viminfo file remembers marks. The " mark contains the position in the buffer where you left off.

autocmd BufReadPost *
    \ if line("'\"") > 1 && line("'\"") <= line("$") |
    \   execute "normal! g`\"" |
    \ endif

Read: If the mark " contains a line number greater than line 1 but not greater than the last line in the file, jump to it.

:h viminfo-'
:h `quote
:h g`

Temporary files

Backup files

Before saving a file, Vim creates a backup file. If writing to disk was successful, the backup file will be deleted.

With :set backup, the backup will persist. This means, the backup file will always have the same content as the original file before the most recent save. It's up to you to decide whether this is useful or not.

You can disable backups entirely with :set nobackup nowritebackup, but you shouldn't need to nowadays. 'writebackup' is a security feature that makes sure that you don't lose the original file in case saving it should ever fail, no matter whether you keep the backup file afterwards or not.

If you frequently use Vim to edit huge files, and you probably shouldn't, you can exclude those from backups with 'backupskip'.

Vim knows different ways to create a backup: copying and renaming.

  • Copying
    1. A full copy of the original file is created and used as backup.
    2. The original file gets emptied and then filled with the content of the Vim buffer.
  • Renaming
    1. The original file is renamed to the backup file.
    2. The content of the Vim buffer gets written to a new file with the name of the original file.

See :h 'backupcopy' for all the nitty-gritty details.


Demo:

:set backup backupskip= backupdir=. backupext=-backup
:e /tmp/foo
ifoo<esc>
:w
" original file gets created, no need for backup file
obar<esc>
:w
" backup file is created, original file gets updated
$ diff -u /tmp/foo-backup /tmp/foo
--- /tmp/foo-backup     2017-04-22 15:05:13.000000000 +0200
+++ /tmp/foo    2017-04-22 15:05:25.000000000 +0200
@@ -1 +1,2 @@
 foo
+bar

:h backup
:h write-fail

Archivos Swap

Cuando editas un archivos, los cambios aun no guardados se escriben en un swap file.

Obten el nombre del archivo swap que estas editando con :swapname. Desabitalo con :set noswapfile.

A swap file gets updated either all 200 characters or when nothing was typed for 4 seconds. They get deleted when you stop editing the file. You can change these numbers with :h 'updatecount' and :h 'updatetime'.

If Vim gets killed (e.g. power outage), you lose all changes since the last time the file was written to disk, but the swap file won't be deleted. Now, if you edit the file again, Vim will offer the chance to recover the file from the swap file.

Cuando dos personas tratan de editar el mismo archivo, la segunda persona obtendra un aviso que el swap file ya existe. Esto previene que hayan dos versiones de un archivo. Si tu no quieres esto revisa :h 'directory'.

:h swap-file
:h usr_11

Archivos Undo

El undo tree es guardado en memoria y se pierde cuando cierras vim. Si tu quieres que se guarden, :set undofile. Esto hara que se guarde en ~/foo.c o ~/foo.c.un~.

:h 'undofile'
:h undo-persistence

Los Archivos de Viminfo

Cuando los archivos de copia de seguridad, intercambio y deshacer tienen que ver con el estado del texto, los archivos viminfo son se utiliza para guardar todo lo demás que de otro modo se perdería al salir de Vim. El archivo viminfo guarda historiales (línea de comando, búsqueda, entrada), registros, marcas, lista de búfer, variables globales, etc.

Por defecto, la información de vim se guarda en ~/.viminfo.

:h viminfo
:h 'viminfo'

Configuración de ejemplo para archivos temporales

Pon todos los archivos temporales en su propio directorio: ~/.vim/files:

" crea el directorio si es necesario
if !isdirectory($HOME.'/.vim/files') && exists('*mkdir')
  call mkdir($HOME.'/.vim/files')
endif

" archivos de backup
set backup
set backupdir   =$HOME/.vim/files/backup/
set backupext   =-vimbackup
set backupskip  =
" archivos swap
set directory   =$HOME/.vim/files/swap//
set updatecount =100
" archivos undo
set undofile
set undodir     =$HOME/.vim/files/undo/
" archivos de viminfo
set viminfo     ='100,n$HOME/.vim/files/info/viminfo

Editando archivos remotos

Vim viene con el plugin netrw que habilita editar archivos remotos. Transfiere los archivos remotos a un archivo temporal local via scp, abre un buffer usando el archivo local, y guarda los cambios en el archivo remoto.

Esto es muy util si tu quieres user tu configuración local opuesto a ssh'ing en un servidor y usar lo que el admind quiere que uses.

:e scp://bram@awesome.site.com/.vimrc

Si tu tienes ~/.ssh/config ya habilitado, este se usa automáticamente:

Host awesome
    HostName awesome.site.com
    Port 1234
    User bram

Asumiendo que el contenido de arriba esta en ~/.ssh/config, esto tambien funcionaria:

:e scp://awesome/.vimrc

Algo similar se puede hacer con ~/.netrc, revisa :h netrw-netrc.

Asegurate de leer :h netrw-ssh-hack y :h g:netrw_ssh_cmd.


Otra posibildad es usar sshfs el cual usa FUSE para montar un sistema de archivos remoto en tu sistema local de archivos.

Manejando Plugins

Pathogen fue la primera herramienta para manjear plugins. Solo ajusta el runtimepath (:h 'rtp') para incluir todas las cosas en cierto directorio. Tu tienes que clonar los repositorios de los plugins por tu cuenta.

Los manejadores de Plugins reales tienen comandos que te ayudan a instalar plugins dentro de vim.

Listsa de manejadores de Plugins

Block insert

This is a technique to insert the same text on multiple consecutive lines at the same time. See this demo.

Switch to visual block mode with <c-v>. Afterwards go down for a few lines. Hit I or A and start entering your text.

It might be a bit confusing at first, but text is always entered for the current line and only after finishing the current insertion, the same text will be applied to all other lines of the prior visual selection.

So a simple example is <c-v>3jItext<esc>.

If you have lines of different length and want to append the same text right after the end of each line, do this: <c-v>3j$Atext<esc>.

Sometime you need to place the cursor somewhere after the end of the current line. You can't do that por defecto, but you can set the virtualedit option:

set virtualedit=all

Afterwards $10l or 90| work even after the end of the line.

See :h blockwise-examples for more info. It might seem complicated at first, but quickly becomes second nature.

If you want to get real fancy, have a look at multiple-cursors.

Running external programs and using filters

Disclaimer: Vim is single-threaded, so running an external program in the foreground will block everything else. Sure, you can use one of Vim's programming interfaces, e.g. Lua, and use its thread support, but during that time the Vim process is blocked nevertheless. Neovim fixed that by adding a proper job API.

(Apparently Bram is thinking about adding job control to Vim as well. If you have a very recent version, see :helpgrep startjob.)

Use :! to start a job. If you want to list the files in the current working directory, use :!ls. Use | for piping in the shell as usual, e.g. :!ls -1 | sort | tail -n5.

Without a range, the output of :! will be shown in a scrollable window. On the other hand, if a range is given, these lines will be filtered. This means they will be piped to the stdin of the filter program and after processing be replaced by the stdout of the filter. E.g. for prepending numbers to the next 5 lines, use this:

:.,+4!nl -ba -w1 -s' '

Since manually adding the range is quite burdensome, Vim also provides some helpers for convenience. As always with ranges, you can also select lines in visual mode and then hit :. There's also an operator ! that takes a motion. E.g. !ip!sort will sort the lines of the current paragraph.

A good use case for filtering is the Go programming language. The indentation is pretty opinionated, it even comes with a filter called gofmt for indenting Go source code properly. So plugins for Go often provide helper commands called :Fmt that basically do :%!gofmt, so they indent all lines in the file.

People often use :r !prog to put the output of prog below the current line, which is fine for scripts, but when doing it on the fly, I find it easier to use !!ls instead, which replaces the current line.

:h filter
:h :read!

Cscope

Cscope does more things than ctags, but only supports C (and C++ and Java to some extent).

Whereas a tags file only knows where a symbol was defined, a cscope database knows much more about your data:

  • Where is this symbol defined?
  • Where is this symbol used?
  • What is this global symbol's definition?
  • Where did this variable get its value?
  • Where is this function in the source files?
  • What functions call this function?
  • What functions are called by this function?
  • Where does the message "out of space" come from?
  • Where is this source file in the directory structure?
  • What files include this header file?

1. Build the database

Do this in the root of your project:

$ cscope -bqR

This will create 3 files: cscope{,.in,.po}.out in the current working directory. Think of them as your database.

Unfortunately cscope only analyzes *.[c|h|y|l] files por defecto. If you want to use cscope for a Java project instead, do this:

$ find . -name "*.java" > cscope.files
$ cscope -bq

2. Add the database

Open a connection to your freshly built database:

:cs add cscope.out

Verify that the connection was made:

:cs show

(Yes, you can add multiple connections.)

3. Query the database

:cs find <kind> <query>

E.g. :cs find d foo will list all functions that are called by foo(...).

Kind Explanation
s symbol: find all references to the token
g global: find global definition(s) of the token
c calls: find all calls to the function
t text: find all instances of the text
e egrep: egrep search for the word
f file: open the filename
i includes: find files that include the filename
d depends: find functions called by this function

I suggest some convenience mappings e.g.:

nnoremap <buffer> <leader>cs :cscope find s  <c-r>=expand('<cword>')<cr><cr>
nnoremap <buffer> <leader>cg :cscope find g  <c-r>=expand('<cword>')<cr><cr>
nnoremap <buffer> <leader>cc :cscope find c  <c-r>=expand('<cword>')<cr><cr>
nnoremap <buffer> <leader>ct :cscope find t  <c-r>=expand('<cword>')<cr><cr>
nnoremap <buffer> <leader>ce :cscope find e  <c-r>=expand('<cword>')<cr><cr>
nnoremap <buffer> <leader>cf :cscope find f  <c-r>=expand('<cfile>')<cr><cr>
nnoremap <buffer> <leader>ci :cscope find i ^<c-r>=expand('<cfile>')<cr>$<cr>
nnoremap <buffer> <leader>cd :cscope find d  <c-r>=expand('<cword>')<cr><cr>

So, when :tag (or <c-]>) jumps to a definition from the tags file, :cstag does the same, but also takes connected cscope databases into account. The option 'cscopetag' makes :tag act like :cstag automatically. This is very convenient if you already have tag-related mappings.

Help: :h cscope

MatchIt

Since Vim is written in C, a lot of features assume C-like syntax. Por defecto, if your cursor is on { or #endif, you can use % to jump to the corresponding } or #ifdef respectively.

Vim comes bundled with a plugin called matchit.vim which is not enabled by default. It makes % also cycle through HTML tags, if/else/endif constructs in VimL etc. and introduces a few new commands.

Installation for Vim 8

" vimrc
packadd! matchit

Installation for Vim 7 and older

" vimrc
runtime macros/matchit.vim

Since the documentation of matchit is pretty extensive, I suggest also doing the following once:

:!mkdir -p ~/.vim/doc
:!cp $VIMRUNTIME/macros/matchit.txt ~/.vim/doc
:helptags ~/.vim/doc

Small intro

The plugin is ready to use now. See :h matchit-intro for the supported commands and :h matchit-languages for the supported languages.

That said, it's easy to define your own matching pairs:

autocmd FileType python let b:match_words = '\<if\>:\<elif\>:\<else\>'

Afterwards you can cycle through these 3 statements in any Python file by using % (forward) or g% (backward).

Help:

:h matchit-install
:h matchit
:h b:match_words

True colors

Using true colors in a terminal emulator means being able to use 24 bits for RGB colors. That makes 16777216 (2^24) colors instead of the usual 256.

As explained here, colorschemes can actually be two colorschemes by having definitions for terminals (xterm) and for GUIs (gvim). This made sense before terminal emulators learned about true colors.

After :set termguicolors, Vim starts emitting escape sequences only understood by a terminal emulator that supports true colors. When your colors look weird, chances are your terminal emulator doesn't support true colors or your colorcheme has no GUI colors defined.

Many people use the terminal multiplexer tmux which basically sits in between the terminal emulator and Vim. To make tmux forward the true color escape sequences emitted by Vim, you have to put the following in the user's .tmux.conf:

set-option -g  default-terminal 'tmux-256color'
set-option -ga terminal-overrides ',xterm-256color:Tc'
  • The first line should be the same for most people and denotes the $TERM to be used within tmux.
  • The second line adds the tmux-specific Tc (true color) capability to the other terminfo entries of xterm-256color. Obviously this assumes that the user is using TERM=xterm-256color outside of tmux.

So, here is the checklist for enabling true colors:

  • Read :h 'termguicolors'.
  • Put set termguicolors in your vimrc.
  • Make sure your colorscheme has color definitions for GUIs. (It should contain lines with guifg and guibg.)
  • Make sure your terminal emulator of choice supports true colors.
  • Using tmux? Configure it to add the Tc capability.

A popular reference for colors in the terminal: https://gist.github.com/XVilka/8346728

Tips

Go to other end of selected text

o and O in a visual selection make the cursor go to the other end. Try with blockwise selection to see the difference. This is useful for quickly changing the size of the selected text.

:h v_o
:h v_O

Saner behavior of n and N

The direction of n and N depends on whether / or ? was used for searching forward or backward respectively. This is pretty confusing to me.

If you want n to always search forward and N backward, use this:

nnoremap <expr> n  'Nn'[v:searchforward]
xnoremap <expr> n  'Nn'[v:searchforward]
onoremap <expr> n  'Nn'[v:searchforward]

nnoremap <expr> N  'nN'[v:searchforward]
xnoremap <expr> N  'nN'[v:searchforward]
onoremap <expr> N  'nN'[v:searchforward]

Saner command-line history

If you're anything like me, you're used to going to next and previous items via <c-n> and <c-p> respectively. Por defecto, this also works in the command-line and recalls older or more recent command-lines from history.

So far, so good. But <up> and <down> are even smarter! They recall the command-line whose beginning matches the current command-line. E.g. :echo <up> may change to :echo "Vim rocks!".

Of course, I don't want you to reach to the arrow keys, just map it instead:

cnoremap <c-n>  <down>
cnoremap <c-p>  <up>

I depend on this behaviour several times a day.

Saner CTRL-L

By default, <c-l> clears and redraws the screen (like :redraw!). The following mapping does the same, plus de-highlighting the matches found via /, ? etc., plus fixing syntax highlighting (sometimes Vim loses highlighting due to complex highlighting rules), plus force updating the syntax highlighting in diff mode:

nnoremap <leader>l :nohlsearch<cr>:diffupdate<cr>:syntax sync fromstart<cr><c-l>

Disable audible and visual bells

set noerrorbells
set novisualbell
set t_vb=

See Vim Wiki: Disable beeping.

Quickly move current line

Sometimes I need a quick way to move the current line above or below:

nnoremap [e  :<c-u>execute 'move -1-'. v:count1<cr>
nnoremap ]e  :<c-u>execute 'move +'. v:count1<cr>

These mappings also take a count, so 2]e moves the current line 2 lines below.

Quickly add empty lines

nnoremap [<space>  :<c-u>put! =repeat(nr2char(10), v:count1)<cr>'[
nnoremap ]<space>  :<c-u>put =repeat(nr2char(10), v:count1)<cr>

Now 5[<space> inserts 5 blank lines above the current line.

Quickly edit your macros

This is a real gem! The mapping takes a register (or * by default) and opens it in the cmdline-window. Hit <cr> when you're done editing for setting the register.

I often use this to correct typos I did while recording a macro.

nnoremap <leader>m  :<c-u><c-r><c-r>='let @'. v:register .' = '. string(getreg(v:register))<cr><c-f><left>

Use it like this <leader>m or "q<leader>m.

Notice the use of <c-r><c-r> to make sure that the <c-r> is inserted literally. See :h c_^R^R.

Quickly jump to header or source file

This technique can probably be applied to many filetypes. It sets file marks (see :h marks) when leaving a source or header file, so you can quickly jump back to the last accessed one by using 'C or 'H (see :h 'A).

autocmd BufLeave *.{c,cpp} mark C
autocmd BufLeave *.h       mark H

NOTE: The info is saved in the viminfo file, so make sure that :set viminfo? includes :h viminfo-'.

Quickly change font size in GUI

I think this was taken from tpope's config:

command! Bigger  :let &guifont = substitute(&guifont, '\d\+$', '\=submatch(0)+1', '')
command! Smaller :let &guifont = substitute(&guifont, '\d\+$', '\=submatch(0)-1', '')

Change cursor style dependent on mode

I like to use a block cursor in normal mode, i-beam cursor in insert mode, and underline cursor in replace mode.

if empty($TMUX)
  let &t_SI = "\<Esc>]50;CursorShape=1\x7"
  let &t_EI = "\<Esc>]50;CursorShape=0\x7"
  let &t_SR = "\<Esc>]50;CursorShape=2\x7"
else
  let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
  let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
  let &t_SR = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=2\x7\<Esc>\\"
endif

This simply tells Vim to print a certain sequence of characters (escape sequence) when entering/leaving insert mode. The underlying terminal, or programs like tmux that sit between Vim and the terminal, will process and evaluate it.

There's one drawback though: there are many terminal emulator implementations and not all use the same sequences for doing the same things. The sequences used above might not work with your implementation. Your implementation might not even support different cursor styles. Check the documentation.

The example above works with iTerm2.

Don't lose selection when shifting sidewards

If you select one or more lines, you can use < and > for shifting them sidewards. Unfortunately you immediately lose the selection afterwards.

You can use gv to reselect the last selection (see :h gv), thus you can work around it like this:

xnoremap <  <gv
xnoremap >  >gv

Now you can use >>>>> on your visual selection without any problems.

NOTE: The same can be achieved using ., which repeats the last change.

Reload a file on saving

Using autocmds you can do anything on saving a file, e.g. sourcing it in case of a dotfile or running a linter to check for syntactical errors in your source code.

autocmd BufWritePost $MYVIMRC source $MYVIMRC
autocmd BufWritePost ~/.Xdefaults call system('xrdb ~/.Xdefaults')

Smarter cursorline

I love the cursorline, but I only want to use it in the current window and not when being in insert mode:

autocmd InsertLeave,WinEnter * set cursorline
autocmd InsertEnter,WinLeave * set nocursorline

Faster keyword completion

The keyword completion (<c-n>/<c-p>) tries completing whatever is listed in the 'complete' option. By default, this also includes tags (which can be annoying) and scanning all included files (which can be very slow). If you can live without these things, disable them:

set complete-=i   " disable scanning included files
set complete-=t   " disable searching tags

Cosmetic changes to colorschemes

Always use a dark gray statusline, no matter what colorscheme is chosen:

autocmd ColorScheme * highlight StatusLine ctermbg=darkgray cterm=NONE guibg=darkgray gui=NONE

This triggers every time you use :colorscheme .... If you want it to trigger only for a certain colorscheme:

autocmd ColorScheme desert highlight StatusLine ctermbg=darkgray cterm=NONE guibg=darkgray gui=NONE

This triggers only for :colorscheme desert.

Commands

Useful commands that are good to know. Use :h :<command name> to learn more about them, e.g. :h :global.

:global and :vglobal

Execute a command on all matching lines. E.g. :global /regexp/ print will use :print on all lines that contain "regexp".

Fun fact: You probably all know good old grep, the filter program written by Ken Thompson. What does it do? It prints all lines matching a certain regular expression! Now guess the short form of :global /regexp/ print? That's right! It's :g/re/p. Ken Thompson was inspired by vi's :global when he wrote grep.

Despite its name, :global only acts on all lines by default, but it also takes a range. Assume you want use :delete on all lines from the current line to the next blank line (matched by the regular expression ^$) that contain "foo":

:,/^$/g/foo/d

For executing commands on all lines that do not match a given pattern, use :global! or its alias :vglobal (think inVerse) instead.

:normal and :execute

These commands are commonly used in Vim scripts.

With :normal you can do normal mode mappings from the command-line. E.g. :normal! 4j will make the cursor go down 4 lines (without using any custom mapping for "j" due to the "!").

Mind that :normal also takes a range, so :%norm! Iabc would prepend "abc" to every line.

With :execute you can mix commands with expressions. Assume you edit a C source file and want to switch to its header file:

:execute 'edit' fnamemodify(expand('%'), ':r') . '.h'

Both commands are often used together. Assume you want to make the cursor go down "n" lines:

:let n = 4
:execute 'normal!' n . 'j'

:redir and execute()

Many commands print messages and :redir allows to redirect that output. You can redirect to files, registers or variables.

:redir => var
:reg
:redir END
:echo var
:" For fun let's also put it onto the current buffer.
:put =var

In Vim 8 there is an even shorter way:

:put =execute('reg')

Help:

:h :redir
:h execute()

Debugging

General tips

If you encounter a strange behaviour, try reproducing it like this:

vim -u NONE -N

This will start Vim without vimrc (thus default settings) and in nocompatible mode (which makes it use Vim defaults instead of vi defaults). (See :h --noplugin for other combinations of what to load at start.)

If you can still reproduce it now, it's most likely a bug in Vim itself! Report it to the vim_dev mailing list. Most of the time the issue won't be resolved at this time and you'll have to further investigate.

Plugins often introduce new/changed/faulty behaviour. E.g. if it happens on saving, check :verb au BufWritePost to get a list of potential culprits.

If you're using a plugin manager, comment them out until you find the culprit.

Issue is still not resolved? If it's not a plugin, it must be your other settings, so maybe your options or autocmds etc.

Time to use binary search. Repeatedly split the search space in two until you find the culprit line. Due to the nature of binary division, it won't take many steps.

In practice, it works like this: Put the :finish command in the middle of your vimrc. Vim will skip everything after it. If it still happens, the problem is in the active upper half. Move the :finish to the middle of that half. Otherwise, the issue is in the inactive lower half. Move the :finish to the middle of that half. And so on.

Verbosity

Another useful way for observing what Vim is currently doing is increasing the verbosity level. Currently Vim supports 9 different levels. See :h 'verbose' for the full list.

:e /tmp/foo
:set verbose=2
:w
:set verbose=0

This would show all the files that get sourced, e.g. the undo file or various plugins that act on saving.

If you only want increase verbosity for a single command, there's also :verbose, which simply gets put in front of any other command. It takes the verbosity level as count and defaults to 1:

:verb set verbose
"  verbose=1
:10verb set verbose
"  verbose=10

It's very often used with its default verbosity level 1 to show where an option was set last:

:verb set ai?
"      Last set from ~/.vim/vimrc

Naturally, the higher the verbosity level the more overwhelming the output. But fear no more, you can simply redirect the output to a file:

:set verbosefile=/tmp/foo | 15verbose echo "foo" | vsplit /tmp/foo

You can also enable verbosity at starting time, with the -V option. It defaults to verbosity level 10. E.g. vim -V5.

Profiling startup time

Vim startup feels slow? Time to crunch some numbers:

vim --startuptime /tmp/startup.log +q && vim /tmp/startup.log

The first column is the most important as it shows the elapsed absolute time. If there is a big jump in time between two lines, the second line is either a very big file or a file with faulty VimL code that is worth investigating.

Profiling at runtime

Required feature: +profile

Vim provides a built-in capability for profiling at runtime and is a great way to find slow code in your environment.

The :profile command takes a bunch of sub-commands for specifying what to profile.

If you want to profile everything, do this:

:profile start /tmp/profile.log
:profile file *
:profile func *
<do something in Vim>
:qa

Vim keeps the profiling information in memory and only writes it out to the logfile on exit. (Neovim has fixed this using :profile dump).

Have a look at /tmp/profile.log. All code that was executed during profiling will be shown. Every line, how often it was executed and how much time it took.

Jump to the bottom of the log. Here are two different sections FUNCTIONS SORTED ON TOTAL TIME and FUNCTIONS SORTED ON SELF TIME that are worth gold. At a quick glance you can see which functions are taking the longest.

You can use :profile during startup as well:

$ vim --cmd 'prof start prof.log | prof file * | prof func *' test.c
:q
$ tail -50 prof.log

Debugging Vim scripts

If you ever used a command-line debugger before, :debug will quickly feel familiar.

Simply prepend :debug to any other command and you'll be put into debug mode. That is, the execution will stop at the first line about to be executed and that line will be displayed.

See :h >cont and below for the 6 available debugger commands and note that, like in gdb and similar debuggers, you can also use their short forms: c, q, n, s, i, and f.

Apart from that those, you're free to use any Vim command, e.g. :echo myvar, which gets executed in the context of the current position in the code.

You basically get a REPL by simply using :debug 1.

It would be a pain if you had to single-step through every single line, so of course we can define breakpoints, too. (Breakpoints are called breakpoints, because the execution stops when they're hit, thus you can simply skip code you're not interested in.) See :h :breakadd, :h :breakdel, and :h :breaklist for further details.

Let's assume you want to know what code is run every time you save a file:

:au BufWritePost
" signify  BufWritePost
"     *         call sy#start()
:breakadd func *start
:w
" Breakpoint in "sy#start" line 1
" Entering Debug mode.  Type "cont" to continue.
" function sy#start
" line 1: if g:signify_locked
>s
" function sy#start
" line 3: endif
>
" function sy#start
" line 5: let sy_path = resolve(expand('%:p'))
>q
:breakdel *

As you can see, using <cr> will repeat the previous debugger command, s in this case.

:debug can be used in combination with the verbose option.

Debugging syntax files

Syntax files are often the cause for slowdowns due to wrong and/or complex regular expressions. If the +profile feature is compiled in, Vim provides the super useful :syntime command.

:syntime on
" hit <c-l> a few times to redraw the window which causes the syntax rules to get applied again
:syntime off
:syntime report

The output contains important metrics. E.g. you can see which regexp takes too long and should be optimized or which regexps are used all the time but never even match.

See :h :syntime.

Miscellaneous

Additional resources

Resource Description
Seven habits of effective text editing By Bram Moolenaar, the author of Vim.
Seven habits of effective text editing 2.0 (PDF) See above.
IBM DeveloperWorks: Scripting the Vim editor Five-part series on Vim scripting.
Learn Vimscript the Hard Way Develop a Vim plugin from scratch.
Practical Vim (2nd Edition) Hands down the best book about Vim.
Why, oh WHY, do those #?@! nutheads use vi? Common misconceptions explained.
Your problem with Vim is that you don't grok vi Concise, informative and correct. A real gem.

Screencasts

Vim distributions

Vim distributions are bundles of custom settings and plugins for Vim.

More advanced users know how to configure their editor anyway, so distributions are mostly targeted at beginners. If you think about that, it's quite paradoxical though: Making it easier by adding even more things to learn about?

I know that many people don't want to spend hours and hours on customizing an editor (and actually you never stop customizing your vimrc when you finally got hooked), but eventually you only get efficient in Vim when you take the time to learn it properly.

Repeat after me: "A programmer should know their tools."

Anyway, if you know what you're doing, you might draw some inspiration from looking at a few distributions:

Standard plugins

Many people are surprised by the fact that Vim comes with a handful of standard plugins. Some get loaded by default (:e $VIMRUNTIME/plugin) and some are not (:e $VIMRUNTIME/pack/dist/opt). Read :h pack-add on how to source the latter.

Most of the plugins that get loaded by default will never get used, though. Disable them as you see fit. They will still be shown as sourced (:scriptnames), but only the first lines actually get read before Vim bails out. No further code (mappings, commands, logic) will be processed.

Plugin Disable it using.. Help
2html let g:loaded_2html_plugin = 1 :h 2html
getscript let g:loaded_getscriptPlugin = 1 :h pi_getscript
gzip let g:loaded_gzip = 1 :h pi_gzip
logipat let g:loaded_logipat = 1 :h pi_logipat
matchparen let g:loaded_matchparen = 1 :h pi_paren
netrw let g:loaded_netrwPlugin = 1 :h pi_netrw
rrhelper let g:loaded_rrhelper = 1 :e $VIMRUNTIME/plugin/rrhelper.vim
spellfile let g:loaded_spellfile_plugin = 1 :h spellfile.vim
tar let g:loaded_tarPlugin = 1 :h pi_tar
vimball let g:loaded_vimballPlugin = 1 :h pi_vimball
zip let g:loaded_zipPlugin = 1 :h pi_zip

Map CapsLock to Control

CapsLock belongs to the most useless keys on your keyboard, but it's much easier to reach than the Control key, since it lies on your home row. Mapping CapsLock to Control is a great way to prevent or at least reduce RSI if you program a lot.

Attention: When you get used to it, you can't live without it anymore.

macOS:

System Preferences -> Keyboard -> Keyboard Tab -> Modifier Keys. Change "CapsLock" to "Control".

Linux:

To change the keys in X, put this in your ~/.xmodmap:

remove Lock = Caps_Lock
keysym Caps_Lock = Control_L
add Control = Control_L

Afterwards source it via $ xmodmap ~/.xmodmap.

An alternative would be using caps2esc or xcape.

Windows:

See superuser.com: Map Caps-Lock to Control in Windows 8.1.

Generating HTML from buffer

Generate HTML from any buffer using :TOhtml from the 2html standard plugin. The output can be used for printing or easy web publishing.

The command creates a new buffer of the same name with .html appended. The colors are the same as seen in Vim. They depend on the colorscheme.

The plugin knows several options to finetune the output, e.g. for setting the encoding and font.

See :h :TOhtml.

Easter eggs

Command Message
:Ni! Do you demand a shrubbery?
:h 'sm' NOTE: Use of the short form is rated PG.
:h 42 What is the meaning of life, the universe and everything? Douglas Adams, the only person who knew what this question really was about is now dead, unfortunately. So now you might wonder what the meaning of death is...
:h UserGettingBored When the user presses the same key 42 times. Just kidding! :-)
:h bar Ceci n'est pas une pipe.
:h holy-grail You found it, Arthur!
:h map-modes :nunmap can also be used outside of a monastery.
:help! E478: Don't panic! (Glitch? When used in a help buffer (buftype=help) this works like :h help.txt instead.)
:smile Try it out yourself. ;-) Added in 7.4.1005.

Why hjkl for navigation?

When Bill Joy created vi, a predecessor of Vim, he did it on a ADM-3A which had no extra cursor buttons but used, you might already guessed it, hjkl instead.

Keyboard layout: click

This also shows why ~ is used to denote the home directory on Unix systems.

Common problems

Editing small files is slow

There are two things which can have a huge impact on performance:

  1. Complex regular expressions. Particular the Ruby syntax file caused people to have slowdowns in the past. (Also see Debugging syntax files.)
  2. Screen redraws. Some features force all lines to redraw.
Typical culprit Why? Solution?
:set cursorline Causes all lines to redraw. :set nocursorline
:set cursorcolumn Causes all lines to redraw. :set nocursorcolumn
:set relativenumber Causes all lines to redraw. :set norelativenumber
:set foldmethod=syntax If the syntax file is slow already, this makes it even worse. :set foldmethod=manual, :set foldmethod=marker or FastFold
:set synmaxcol=3000 Due to internal representation, Vim has problems with long lines in general. Highlights columns till column 3000. :set synmaxcol=200
matchparen.vim Loaded by default. Uses regular expressions to find the accompanying parenthesis. Disable plugin: :h matchparen

NOTE: You only need to do this if you experience actual performance drawbacks. In most cases using the things mentioned above is absolutely fine.

Editing huge files is slow

The biggest issue with big files is, that Vim reads the whole file at once. This is done due to how buffers are represented internally. (Discussion on vim_dev@)

If you only want to read, tail hugefile | vim - is a good workaround.

If you can live without syntax, settings and plugins for the moment:

$ vim -u NONE -N

This should make navigation quite a lot faster, especially since no expensive regular expressions for syntax highlighting are used. You should also tell Vim not to use swapfiles and viminfo files to avoid long delays on writing:

$ vim -n -u NONE -i NONE -N

Putting it in a nutshell, try to avoid using Vim when intending to write really huge files. :\

Bracketed paste (or why do I have to set 'paste' all the time?)

Bracketed paste mode allows terminal emulators to distinguish between typed text and pasted text.

Did you ever tried pasting code into Vim and afterwards everything seemed messed up?

This only happens if you paste via cmd+v, shift-insert, middle-click etc. because then you're just throwing text at the terminal emulator. Vim doesn't know that you just pasted the text, it thinks you're an extremely fast typist. Accordingly, it tries to indent the lines and fails.

Obviously this is not an issue, if you paste using Vim's registers, e.g. "+p, because then Vim knows that you're actually pasting.

To workaround this, you have to :set paste, so it gets pasted as-is. See :h 'paste' and :h 'pastetoggle'.

If you're fed up with toggling 'paste' all the time, have a look at this fine plugin that does it for you: bracketed-paste.

Additional read from the same author as the plugin: here.

Neovim: Neovim tries to make all of this much more seamless and sets bracketed paste mode automatically if the terminal emulator supports it.

Delays when using escape key in terminal

If you live in the command-line, you probably use a so-called terminal emulator like xterm, gnome-terminal, iTerm2, etc. (opposed to a real terminal).

Like their ancestors, terminal emulators use escape sequences (or control sequences) to control things like moving the cursor, changing text colors, etc. They're simply strings of ASCII characters starting with an escape character (displayed in caret notation as ^[). When such a string arrives, the terminal emulator looks up the accompanying action in the terminfo database.

To make the problem clearer, I'll explain mapping timeouts first. They always happen when there's ambiguity between mappings:

:nnoremap ,a  :echo 'foo'<cr>
:nnoremap ,ab :echo 'bar'<cr>

Las 2 combinaciones funcionan como se espera, pero cuando presionamos ,a, abra un retraso de 1 segundo, porque Vim espera a confirmar que el usuario teclee otra b o no.

Las secuencias de escape plantean el mismo problema:

  • <esc> is used a lot for returning to normal mode or quitting an action.
  • Cursor keys are encoded using escape sequences.
  • Vim expects Alt (also called Meta key) to send a proper 8-bit encoding with the high bit set, but many terminal emulators don't support it (or don't enable it by default) and send an escape sequence instead.

Puede probar lo anterior de esta manera: vim -u NONE -N y escribai <c-v> <left>y verá una secuencia insertada que comienza con ^ [ que denota el caracter de escape.

En pocas palabras, Vim tiene dificultades para distinguir entre una carácter <esc> y una secuencia de escape adecuada.

Por defecto, Vim usa :set timeout timeoutlen=1000, por lo que retrasa la ambigüedad de las asignaciones y códigos clave en 1 segundo. Este es un valor sensato para las asignaciones, pero se puede definir el tiempo de espera del código clave por sí solo. La solución alternativa para todo este problema es:

set timeout           " para los mappings
set timeoutlen=1000   " valores predeterminados
set ttimeout          " para los códigos clave
set ttimeoutlen=10    " valor pequeño imperceptible

En :h ttimeout encuentras una pequeña tabla que muestra la relación entre estas opciones.

Si está utilizando tmux entre Vim y su emulador de terminal, también coloque esto en tu ~/.tmux.conf:

set -sg escape-time 0

Función de buscar en undo

  • Un patrón de búsqueda en un comando (/, : subdstitute, ...) cambia el "último usado patrón de búsqueda ". (Se guarda en el registro/; imprímalo con:echo @/).
  • Un simple cambio de texto se puede rehacer con .. (Se guarda en el registro del .; puedes imprimirlo con : echo @.).

Sin embargo, ambas cosas no son el caso, si las haces desde una función. Asi tu no puedes resaltar fácilmente palabras de una función o rehacer los cambios de texto realizados poreso.

Ayuda: :h function-search-undo

Peculiaridades técnicas

Nuevas lineas usadas por NUL

Los caracteres NUL (\0) en un archivo, son guardados como una nueva linea (\n) en memoria y mostrados en el buffer como ^@.

Revisa man 7 ascii y :h NL-used-for-Nul para mas información.

Terminologia

Vim script? Vimscript? VimL?

Vim script, Vimscript, y VimL hacen referencia a la misma cosa: El lenguaje de programación para hacer scripts en vim . Aunque en la versión 8.0.360 cambiaron todas las referencias de VimL a Vim script, que ahora puede ser considerado el termino oficial , VimL sigue siendo usado por todo el internet.

Por lo general no importa que termino uses, es probable que te entiendan igual.