vim-galore 0,3,2,3,4,0,15,3

:mortar_board: All things Vim!




vim-galore logo



translation: chinese tranlsation: japanese translation: portuguese

Licensed under CC BY-SA 4.0.


Intro

Basics

Usage

Tips

Commands

Debugging

Miscellaneous

Common problems

Technical quirks

List of colorschemes

List of plugins


Intro

What is Vim?

Vim is a text editor with a long line of ancestors that goes back to qed. Bram Moolenaar released it in 1991.

The project is hosted online at vim.org.

Getting Vim: Use your favourite package manager or visit the download page from vim.org.

Discussions and user questions are best done on the vim_use mailing list or using IRC (Freenode) in the #vim channel.

Development happens on Github, discussions on the vim_dev mailing list.

Read Why, oh WHY, do those #[email protected]! nutheads use vi? to see common misconceptions about Vim explained.

The Vim Philosophy

Vim adheres to the modal editing philosophy. This means that it provides multiple modes and the meaning of keys changes according to the mode. You navigate files in normal mode, you insert text in insert mode, you select lines in visual mode, you access commands in command-line mode and so on. This might sound complicated at first, but has a huge advantage: you don't have to break your fingers by holding several keys at once, most of the time you simply press them one after the other. The more common the task, the fewer keys are needed.

A related concept that works well with modal editing are operators and motions. Operators start a certain action, e.g. changing, removing, or selecting text. Afterwards you specify the region of text you want to act on using a motion. To change everything between parentheses, use ci( (read change inner parentheses). To remove an entire paragraph of text, use dap (read delete around paragraph).

If you see advanced Vim users working, you'll notice that they speak the language of Vim as well as pianists handle their instruments. Complex operations are done using only a few key presses. They don't even think about it anymore as muscle memory took over already. This reduces cognitive load and helps to focus on the actual task.

First steps

Vim comes bundled with an interactive tutorial that teaches the most basic things you need to know about. You can start it from the shell:

$ vimtutor

Don't be put off by how boring it looks like and work through the exercises. The editors or IDEs you used before were most probably all non-modal, so working by switching modes will seem awkward at first, but the more you use Vim, the more it becomes muscle memory.

Vim was bolted on Stevie, a vi clone, and supports two operating modes: "compatible" and "nocompatible". Using Vim in compatible mode means using vi defaults for all options, opposed to Vim defaults. As long as you didn't create a user vimrc yet or started Vim with vim -N, compatible mode is assumed! Don't use Vim in compatible mode. Just don't.

Next steps:

  1. Create your own vimrc.
  2. Have some cheatsheets ready for the first weeks.
  3. Read through the basics section to learn what is even possible.
  4. Learn on demand! You never finish learning Vim. If you encounter any problems, just look for it on the internet. Your problem was solved already. Vim comes with great documentation and knowing how to navigate it is a must: Getting help offline.
  5. Have a look at the additional resources.

One last advice: Please learn how to use Vim properly before starting to add all kinds of hyped plugins that only implement features that Vim already supports natively.

Minimal vimrc

The user vimrc can be put into ~/.vimrc or for the sake of better separation into ~/.vim/vimrc. The latter makes it easy to put the entire configuration under version control and upload it to, let's say Github.

You find many "minimal vimrcs" all over the net, and maybe my version isn't as minimal as it should be, but it provides a good set of sane settings that I deem to be useful for starting out.

Eventually you have to read up on all the mentioned settings anyway and decide for yourself. :-)

So here it is: minimal-vimrc

In case you're interested, here's my vimrc.

TIP: Most plugin authors maintain several plugins and also publish their vimrc on Github (often in a repository called "vim-config" or "dotfiles"), so whenever you find a plugin you like, look up its maintainer's Github page and look through the repositories.

What kind of Vim am I running?

Looking at :version will give you all the information you need to know about how the currently running Vim binary was compiled.

The first line tells you when the binary was compiled and the version, e.g. 7.4. One of the next lines states Included patches: 1-1051, which is the patch level. Thus, your exact Vim version is 7.4.1051.

Another line states something like Tiny version without GUI or Huge version with GUI. The obvious information from that is whether your Vim includes GUI support, e.g. for starting gvim from the shell or running :gui from Vim within a terminal emulator. The other important information is the Tiny and Huge. Vim distinguishes between feature sets called tiny, small, normal, big, and huge, all enabling different subsets of features.

The majority of :version output is consumed by the feature list itself. +clipboard means the clipboard feature was compiled in, -clipboard means it wasn't compiled in.

A few Vim features need to be compiled in for them to work. E.g. for :prof to work, you need a Vim with a huge feature set, because that set enables the +profile feature.

If that's not the case and you installed Vim from a package manager, make sure to install a package called vim-x, vim-x11, vim-gtk, vim-gnome or similar, since these packages usually come with the huge feature set.

You can also test for the version or features programmatically:

" Do something if running at least Vim 7.4.42 with +profile enabled.
if (v:version > 704 || v:version == 704 && has('patch42')) && has('profile')
  " do stuff
endif

Help:

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

Cheatsheets

Or quickly open a cheatsheet from within Vim: vim-cheat40.

Basics

Buffers, windows, tabs

Vim is a text editor. Every time text is shown, the text is part of a buffer. Each file will be opened in its own buffer. Plugins show stuff in their own buffers etc.

Buffers have many attributes, e.g. whether the text it contains is modifiable, or whether it is associated with a file and thus needs to be synchronized to disk on saving.

Windows are viewports onto buffers. If you want to view several files at the same time or even different locations of the same file, you use windows.

And please, please don't call them splits. You can split a window in two, but that doesn't make them splits.

Windows can be split vertically or horizontally and the heights and widths of existing windows can be altered, too. Therefore, you can use whatever window layout you prefer.

A tab page (or just tab) is a collection of windows. Thus, if you want to use multiple window layouts, use tabs.

Putting it in a nutshell, if you start Vim without arguments, you'll have one tab page that holds one window that shows one buffer.

By the way, the buffer list is global and you can access any buffer from any tab.

Active, loaded, listed, named buffers

Run Vim like this vim file1. The file's content will be loaded into a buffer. You have a loaded buffer now. The content of the buffer is only synchronized to disk (written back to the file) if you save it within Vim.

Since the buffer is also shown in a window, it's also an active buffer. Now if you load another file via :e file2, file1 will become a hidden buffer and file2 the active one.

Both buffers are also listed, thus they will get listed in the output of :ls. Plugin buffers or help buffers are often marked as unlisted, since they're not regular files you usually edit with a text editor. Listed and unlisted buffers can be shown via :ls!.

Unnamed buffers, also often used by plugins, are buffers that don't have an associated filename. E.g. :enew will create an unnamed scratch buffer. Add some text and write it to disk via :w /tmp/foo, and it will become a named buffer.

Argument list

The global buffer list is a Vim thing. Before that, in vi, there only used to be the argument list, which is also available in Vim.

Every filename given to Vim on the shell command-line, is remembered in the argument list. There can be multiple argument lists: by default all arguments are put into the global argument list, but you can use :arglocal to create a new argument list that is local to the window.

List the current arguments with :args. Switch between files from the argument list with :next, :previous, :first, :last and friends. Alter it with :argadd, :argdelete or :args with a list of files.

If you should prefer using the buffer or argument list for working with files is a matter of taste. My impression is that most people use the buffer list exclusively.

Nevertheless, there is one huge use case for the argument list: batch processing via :argdo! A simple refactoring example:

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

This replaces all occurrences of "foo" by "bar" in all C source and header files from the current directory and below.

Help: :h argument-list

Mappings

You can define your own mappings with the :map family of commands. Each command of that family defines a mapping for a certain set of modes. Technically Vim comes with a whopping 12 modes, 6 of them can be mapped. Additionally, some commands act on multiple modes at once.

Recursive Non-recursive Unmap Modes
: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

E.g. this defines the mapping for normal mode only:

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

Unmap it again by using :nunmap <space>.

For a few more but rather uncommon modes (or combinations of them), see :h map-modes.

So far, so good. There's only one problem that can be pretty confusing to beginners: :nmap is recursive! That is, the right-hand side takes other mappings into account.

So you defined a mapping that simply echoes "Foo":

:nmap b :echo "Foo"<cr>

But what if you want to map the default behavior of b (going one word back) to another key?

:nmap a b

If you hit a, we expect the cursor to go back a word, but instead "Foo" is printed in the command-line! Because the right-hand side, b, was mapped to another action already, namely :echo "Foo"<cr>.

The proper way to resolve this problem is to use a non-recursive mapping instead:

:nnoremap a b

Rule of thumb: Always use non-recursive mappings unless recursing is actually desired.

Look up your mappings by not giving a right-hand side. E.g. :nmap shows all normal mappings and :nmap <leader> shows all normal mappings that start with the mapleader.

If you want to disable a standard mapping, map them to the special <nop> character, e.g. :noremap <left> <nop>.

Help:

: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 \ by default.

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

` 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 provides the following registers: | Type | Character | 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](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) 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: `=5+5` and "10" will be inserted in the buffer. | | Selection | `+`, `*` | vim | [ ] | `*` and `+` are the [clipboard](#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: ```vim :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 by default. - Only `:write` and `:global` act on all lines by default. 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](#marks) 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.: ```vim :/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 :command`. Here `` 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](#ranges). 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 `` (remember to use them in insert mode): | Mapping | Kind | Help | |---------|------|--------------| | `` | whole lines | `:h i^x^l` | | `` | keywords from current file | `:h i^x^n` | | `` | keywords from `'dictionary'` option | `:h i^x^k` | | `` | keywords from `'thesaurus'` option | `:h i^x^t` | | `` | keywords from current and included files | `:h i^x^i` | | `` | tags | `:h i^x^]` | | `` | file names | `:h i^x^f` | | `` | definitions or macros | `:h i^x^d` | | `` | Vim commands | `:h i^x^v` | | `` | user defined (as specified in `'completefunc'`) | `:h i^x^u` | | `` | omni completion (as specified in `'omnifunc'`) | `:h i^x^o` | | `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. By default that option includes quite a lot, so be sure to trim it to your taste. You can trigger this completion by using either `` (next) and `` (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` 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 On many occasions, Vim emits events. You hook into these events by using autocmds. You wouldn't use Vim if there weren't autocmds. They're used all the time, even if you don't notice it. 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 setting filetype-specific settings: ```vim 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. ```vim 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]` | `[count]` | | 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](#marks) 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](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) but a [tree](https://en.wikipedia.org/wiki/Tree_(data_structure))! 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 obar obaz u oquux ``` 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 (``) 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 `` goes back to the state of node "bar" and another `` 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]`, `: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 [Handling backup, swap, undo, and viminfo files](#handling-backup-swap-undo-and-viminfo-files) for how to enable persistent undo. If you're confused by the undo tree, [undotree](https://github.com/mbbill/undotree) does a great job at visualizing it. Help: ``` :h undo.txt :h usr_32 ``` ## Quickfix and location lists Every time an action has to return a list of locations, _quickfix_ or _location_ lists can be used. In this case a location is a file, a line number and optionally a column. Examples are compiler errors assembled in a quickfix list or matches of an external grep tool assembled in a location list. The big advantage over just putting that stuff in an empty buffer is that you get a nice uniform interface for browsing the entries. At all time there's only one quickfix list, but every window can have its own location list. Both type of lists _feel_ the same, but use slightly different commands for navigation. Most common commands: | 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` | See `:h :cc` and everything below for all commands. **Example**: Let's 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. ```vim :let &grepprg = 'grep -Rn $* .' :grep! foo :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](#registers). It's a great way to automate certain tasks on the fly. (For more elaborate tasks, [Vim scripting](#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 q [email protected] ``` (The same could be done without macros: `oabc10.`) **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 ``, displayed as `^A`. ``` qq 0yf jP0^A q [email protected] ``` Here we simply hope that the file doesn't contain more than 1000 lines when using `[email protected]`, but we can also use a _recursive macro_, which executes until the macro can't be applied to a line anymore: ``` qq 0yf jP0^[email protected] 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](#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: ```vim :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](https://gist.github.com/XVilka/8346728) gives a good overview about the topic.) Help: - `:h 'termguicolors'` - [List of colorschemes](#list-of-colorschemes-1) - [Cosmetic changes to colorschemes](#cosmetic-changes-to-colorschemes) ## 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](https://github.com/Konfekt/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 | `:h :map-local` | | `:autocmd` | `:autocmd * ` | buffer | `:h autocmd-buflocal` | | `:cd` | `:lcd` | window | `:h :lcd` | | `` | `` | buffer | `:h maplocalleader` | Variables also sport different scopes, but will be explained in [Vim scripting](http://vimdoc.sourceforge.net/htmldoc/usr_41.html). # 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 `` (this is ctrl+d) to list all tags that match the currently entered query. E.g. `:h tab` will get you a list of all tags from `tab` over `'softtabstop'` to `setting-guitablabel`. You want to list all VimL functions? Simple: `:h ()`. You want to list all VimL functions that concern windows? `:h win*()`. 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 `` 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](https://groups.google.com/forum/#!forum/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](https://groups.google.com/forum/#!forum/vim_use) mailing list. Another great resource is using [IRC](https://de.wikipedia.org/wiki/Internet_Relay_Chat). The channel `#vim` on [Freenode](https://freenode.net) is huge and usually full of helpful people. If you want to report a Vim bug, use the [vim_dev](https://groups.google.com/forum/#!forum/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: ```vim 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: ```vim 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: ```vim if exists('#User#ChibbyExit') doautocmd User ChibbyExit endif ``` Help: `:h User` ### Nested autocmds By default, 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: ```vim 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: ```vim autocmd VimEnter * nested edit $MYVIMRC ``` Help: `:h autocmd-nested` ## Clipboard Required [features](#what-kind-of-vim-am-i-running): `+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?)](#bracketed-paste-or-why-do-i-have-to-set-paste-all-the-time) ### Clipboard usage (Windows, macOS) Windows comes with a [clipboard](https://msdn.microsoft.com/en-us/library/windows/desktop/ms649012(v=vs.85).aspx) and macOS comes with a [pasteboard](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PasteboardGuide106/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008100-SW1). 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: ```vim 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: ```vim 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](http://www.x.org/wiki), things work a bit different. X implements the [X Window System Protocol](http://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html) which happens to be at major version 11 since 1987, hence X is also often called X11. Prior, in X10, [cut buffers](http://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html#Peer_to_Peer_Communication_by_Means_of_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 ofter 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](http://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html#Peer_to_Peer_Communication_by_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: Program A: assert ownership of CLIPBOARD Program B: 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: ```vim 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: ```vim :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](#marks). The `"` mark contains the position in the buffer where you left off. ```vim 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](#editing-huge-files-is-slow), 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. 1. 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. 1. 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: ```vim :set backup backupskip= backupdir=. backupext=-backup :e /tmp/foo ifoo :w " original file gets created, no need for backup file obar :w " backup file is created, original file gets updated ``` ```diff $ 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 ### Swap files When editing a file, unsaved changes get written to a swap file. Get the name of the current swap file with `:swapname`. Disable them with `: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. When two persons try to edit the same file, the second person will get a notice that the swap file already exists. It prevents people from trying to save different versions of a file. If you don't want that behaviour, see `:h 'directory'`. :h swap-file :h usr_11 ### Undo files The [undo tree](#undo-tree) is kept in memory and will be lost when Vim quits. If you want it to persist, `:set undofile`. This will save the undo file for `~/foo.c` in `~/foo.c.un~`. :h 'undofile' :h undo-persistence ### Viminfo files When backup, swap, and undo files are all about text state, viminfo files are used for saving everything else that would otherwise be lost when quitting Vim. The viminfo file keeps histories (command line, search, input), registers, marks, buffer list, global variables etc. By default, the viminfo is written to `~/.viminfo`. :h viminfo :h 'viminfo' ### Example configuration for temporary files Put all temporary files in their own directory under `~/.vim/files`: ```vim " create directory if needed if !isdirectory($HOME.'/.vim/files') && exists('*mkdir') call mkdir($HOME.'/.vim/files') endif " backup files set backup set backupdir =$HOME/.vim/files/backup/ set backupext =-vimbackup set backupskip = " swap files set directory =$HOME/.vim/files/swap// set updatecount =100 " undo files set undofile set undodir =$HOME/.vim/files/undo/ " viminfo files set viminfo ='100,n$HOME/.vim/files/info/viminfo ``` ## Editing remote files Vim comes with the netrw plugin that enables editing remote files. Actually it transfers the remote file to a local temporary file via scp, opens a buffer using that file, and writes the changes back to the remote file on saving. This is extremely useful if you want to use your local configuration opposed to ssh'ing into a server and use whatever the admins want you to use. ``` :e scp://[email protected]/.vimrc ``` If you have a `~/.ssh/config` set up already, this gets used automatically: ``` Host awesome HostName awesome.site.com Port 1234 User bram ``` Assuming the above content in `~/.ssh/config`, this works just as well: ``` :e scp://awesome/.vimrc ``` Similar can be done with a `~/.netrc`, see `:h netrw-netrc`. Make sure to read `:h netrw-ssh-hack` and `:h g:netrw_ssh_cmd`. --- Another possibility is using [sshfs](https://wiki.archlinux.org/index.php/Sshfs) which uses [FUSE](https://en.wikipedia.org/wiki/Filesystem_in_Userspace) to mount a remote filesystem into your local filesystem. ## Managing plugins [Pathogen](https://github.com/tpope/vim-pathogen) was the first popular tool for managing plugins. Actually it just adjusts the _runtimepath_ (`:h 'rtp'`) to include all the things put under a certain directory. You have to clone the repositories of the plugins there yourself. Real plugin managers expose commands that help you to install and update plugins from within Vim. Hereinafter is a list of commonly used plugin managers: - [dein](https://github.com/Shougo/dein.vim) - [plug](https://github.com/junegunn/vim-plug) - [vim-add

Related Repositories

awesome

awesome

:sunglasses: Curated list of awesome lists ...

vim-signify

vim-signify

:heavy_plus_sign: Show a diff using Vim its sign column. ...

learn-vim

learn-vim

vim 实操教程 ...

awesome-LaTeX

awesome-LaTeX

Curated list of LaTeX awesomeness ...

vim-practice

vim-practice

:heart_decoration: Vim is awesome! Here is my awesome practice and study log. ...


Top Contributors

mhinz codeurge ahmedelgabri george-b romanlevin davidosomething kcwu mortonfox razzius EvanHahn Wideshanks StevenMaude TroJan bogem gitetsu ninrod peter50216 thijsdv wsdjeg

Releases

-   v1.2 zip tar
-   v1.1 zip tar
-   v1.0 zip tar