[[
wikihub
]]
Search
⌘K
Explore
People
For Agents
Sign in
Explore
People
For Agents
Sign in
@harrisonqian / Awesome / wiki/editors/vim.md
Suggest edit
Cancel
Submit suggestion
Title
Name
Note
--- visibility: public --- # Vim **repo:** [mhinz/vim-galore](https://github.com/mhinz/vim-galore) **category:** [[editors|Editors]] **related:** [[neovim|Neovim]] · [[emacs|Emacs]] · [[sublime-text|Sublime Text]] --- ### [Intro](#intro-1) - [What is Vim?](#what-is-vim) - [The Vim Philosophy](#the-vim-philosophy) - [First steps](#first-steps) - [Minimal vimrc](#minimal-vimrc) - [What kind of Vim am I running?](#what-kind-of-vim-am-i-running) - [Cheatsheets](#cheatsheets) ### [Basics](#basics-1) - [Buffers, [windows](/@harrisonqian/awesome/wiki/platforms/windows), tabs](#buffers-windows-tabs) - [Active, loaded, listed, named buffers](#active-loaded-listed-named-buffers) - [Argument list](#argument-list) - [Mappings](#mappings) - [Mapleader](#mapleader) - [Registers](#registers) - [Ranges](#ranges) - [Marks](#marks) - [Completion](#completion) - [Motions, operators, text objects](#motions-operators-text-objects) - [Autocmds](#autocmds) - [Changelist, jumplist](#changelist-jumplist) - [Undo tree](#undo-tree) - [Quickfix and location lists](#quickfix-and-location-lists) - [Macros](#macros) - [Colorschemes](#colorschemes) - [Folding](#folding) - [Sessions](#sessions) - [Locality](#locality) ### [Usage](#usage-1) - [Getting help offline](#getting-help-offline) - [Getting help offline (alternative)](#getting-help-offline-alternative) - [Getting help online](#getting-help-online) - [Autocmds in practice](#autocmds-in-practice) - [User events](#user-events) - [Nested autocmds](#nested-autocmds) - [Clipboard](#clipboard) - [Clipboard usage (Windows, macOS)](#clipboard-usage-[windows](/@harrisonqian/awesome/wiki/platforms/windows)-macos) - [Clipboard usage (Linux, BSD, ...)](#clipboard-usage-[linux](/@harrisonqian/awesome/wiki/platforms/linux)-bsd-) - [Restore cursor position when opening file](#restore-cursor-position-when-opening-file) - [Temporary files](#temporary-files) - [Backup files](#backup-files) - [Swap files](#swap-files) - [Undo files](#undo-files) - [Viminfo files](#viminfo-files) - [Example configuration for temporary files](#example-configuration-for-temporary-files) - [Editing remote files](#editing-remote-files) - [Managing plugins](#managing-plugins) - [Block insert](#block-insert) - [Running external programs and using filters](#running-external-programs-and-using-filters) - [Cscope](#cscope) - [MatchIt](#matchit) - [True colors](#true-colors) ### [Tips](#tips-1) - [Go to other end of selected text](#go-to-other-end-of-selected-text) - [Saner behavior of n and N](#saner-behavior-of-n-and-n) - [Saner command-line history](#saner-command-line-history) - [Saner CTRL-L](#saner-ctrl-l) - [Disable audible and visual bells](#disable-audible-and-visual-bells) - [Quickly [move](/@harrisonqian/awesome/wiki/programming-languages/move) current line](#quickly-move-current-line) - [Quickly add empty lines](#quickly-add-empty-lines) - [Quickly edit your macros](#quickly-edit-your-macros) - [Quickly jump to header or source file](#quickly-jump-to-header-or-source-file) - [Quickly change font size in GUI](#quickly-change-font-size-in-gui) - [Change cursor style dependent on mode](#change-cursor-style-dependent-on-mode) - [Don't lose selection when shifting sidewards](#dont-lose-selection-when-shifting-sidewards) - [Reload a file on saving](#reload-a-file-on-saving) - [Smarter cursorline](#smarter-cursorline) - [Faster keyword completion](#faster-keyword-completion) - [Cosmetic changes to colorschemes](#cosmetic-changes-to-colorschemes) ### [Commands](#commands-1) - [:global and :vglobal](#global-and-vglobal) - Execute a command on all matching lines. - [:normal and :execute](#normal-and-execute) - The scripting dream team. - [:redir and execute()](#redir-and-execute) - Capture command output. ### [Debugging](#debugging-1) - [General tips](#general-tips) - [Verbosity](#verbosity) - [Profiling startup time](#profiling-startup-time) - [Profiling at runtime](#profiling-at-runtime) - [Debugging Vim scripts](#debugging-vim-scripts) - [Debugging syntax files](#debugging-syntax-files) ### [Miscellaneous](#miscellaneous-1) - [Additional resources](#additional-resources) - [Vim distributions](#vim-distributions) - [Standard plugins](#standard-plugins) - [Map CapsLock to Control](#map-capslock-to-control) - [Generating HTML from buffer](#generating-html-from-buffer) - [Easter eggs](#easter-eggs) - [Why hjkl for navigation?](#why-hjkl-for-navigation) ### [Common problems](#common-problems-1) - [Editing small files is slow](#editing-small-files-is-slow) - [Editing huge files is slow](#editing-huge-files-is-slow) - [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) - [Delays when using escape key in terminal](#delays-when-using-escape-key-in-terminal) - [Function search undo](#function-search-undo) ### [Technical quirks](#technical-quirks-1) - [Newline used for NUL](#newline-used-for-nul) ### [Terminology](#terminology-1) - [Vim script? Vimscript? VimL?](#vim-script-vimscript-viml) ### [List of colorschemes](PLUGINS.md#colorschemes-1) ### [List of plugins](PLUGINS.md) <br> # Intro ## What is Vim? [Vim](http://www.vim.org) is a text editor with a long line of ancestors that goes back to [qed](https://en.wikipedia.org/wiki/QED_(text_editor)). [Bram Moolenaar](https://en.wikipedia.org/wiki/Bram_Moolenaar) released it in 1991. The project is hosted online at [vim.org](http://www.vim.org/index.php). Getting Vim: Use your favourite package manager or visit the [download page](http://www.vim.org/download.php) from vim.org. Discussions and user questions are best done on the [vim_use](https://groups.google.com/forum/#!forum/vim_use) mailing list or using IRC ([Freenode](https://freenode.net)) in the `#vim` channel. Development happens on [GitHub](https://github.com/vim/vim), discussions on the [vim_dev](https://groups.google.com/forum/#!forum/vim_dev) mailing list. Read [Why, oh WHY, do those #?@! nutheads use vi?](http://www.viemu.com/a-why-vi-vim.html) 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](https://en.wikipedia.org/wiki/Muscle_memory) took over already. This reduces [cognitive load](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Muscle_memory). Vim was bolted on [Stevie](https://en.wikipedia.org/wiki/Stevie_(text_editor)), a [vi](https://en.wikipedia.org/wiki/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](#minimal-vimrc). 2. Have some [cheatsheets](#cheatsheets) ready for the first weeks. 3. Read through the [basics](#basics-1) 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](#getting-help-offline). 5. Have a look at the [additional resources](#additional-resources). One last advice: Please learn how to use Vim properly before starting to add all kinds of hyped [plugins](#managing-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](static/minimal-vimrc.vim) In case you're interested, here's [my vimrc](https://github.com/mhinz/dotfiles/blob/master/.vim/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: ```vim " 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 - http://people.csail.mit.edu/vgod/vim/vim-cheat-sheet-en.png - https://cdn.shopify.com/s/files/1/0165/4168/files/preview.png - http://michael.peopleofhonoronly.com/vim/vim_cheat_sheet_for_programmers_screen.png - http://www.rosipov.com/images/posts/vim-movement-commands-cheatsheet.png Or quickly open a cheatsheet from within Vim: [vim-cheat40](https://github.com/lifepillar/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](#buffers-windows-tabs) 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: ```vim :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: ```vim :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": ```vim :nmap b :echo "Foo"<cr> ``` But what if you want to map the default behavior of `b` (going one word back) to another key? ```vim :nmap a b ``` If you hit <kbd>a</kbd>, 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: ```vim :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. ```vim nnoremap <leader>h :helpgrep<space> ``` This mapping is triggered by `\h`. If you want to use `<space>h` instead: ```vim 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 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: `<c-r>=5+5<cr>` 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 <kbd>n</kbd> 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 --- *truncated — [full list on GitHub](https://github.com/mhinz/vim-galore)*