- Notifications
You must be signed in to change notification settings - Fork623
mhinz/vim-galore
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
- Buffers, windows, tabs
- Active, loaded, listed, named buffers
- Argument list
- Mappings
- Mapleader
- Registers
- Ranges
- Marks
- Completion
- Motions, operators, text objects
- Autocmds
- Changelist, jumplist
- Undo tree
- Quickfix and location lists
- Macros
- Colorschemes
- Folding
- Sessions
- Locality
- Getting help offline
- Getting help offline (alternative)
- Getting help online
- Autocmds in practice
- Clipboard
- Restore cursor position when opening file
- Temporary files
- Editing remote files
- Managing plugins
- Block insert
- Running external programs and using filters
- Cscope
- MatchIt
- True colors
- Go to other end of selected text
- Saner behavior of n and N
- Saner command-line history
- Saner CTRL-L
- Disable audible and visual bells
- Quickly move current line
- Quickly add empty lines
- Quickly edit your macros
- Quickly jump to header or source file
- Quickly change font size in GUI
- Change cursor style dependent on mode
- Don't lose selection when shifting sidewards
- Reload a file on saving
- Smarter cursorline
- Faster keyword completion
- Cosmetic changes to colorschemes
- :global and :vglobal - Execute a command on all matching lines.
- :normal and :execute - The scripting dream team.
- :redir and execute() - Capture command output.
- General tips
- Verbosity
- Profiling startup time
- Profiling at runtime
- Debugging Vim scripts
- Debugging syntax files
- Additional resources
- Vim distributions
- Standard plugins
- Map CapsLock to Control
- Generating HTML from buffer
- Easter eggs
- Why hjkl for navigation?
- Editing small files is slow
- Editing huge files is slow
- Bracketed paste (or why do I have to set 'paste' all the time?)
- Delays when using escape key in terminal
- Function search undo
Vim is a text editor with a long line of ancestors thatgoes back toqed.BramMoolenaar released it in 1991.
The project is hosted online atvim.org.
Getting Vim: Use your favourite package manager or visit thedownloadpage from vim.org.
Discussions and user questions are best done on thevim_use mailing list or usingIRC (Freenode) in the#vim
channel.
Development happens onGitHub, discussions on thevim_dev mailing list.
ReadWhy, oh WHY, do those #?@! nutheads usevi? to see common misconceptions aboutVim explained.
Vim adheres to the modal editing philosophy. This means that it providesmultiple modes and the meaning of keys changes according to the mode. Younavigate files innormal mode, you insert text ininsert mode, you selectlines invisual mode, you access commands incommand-line mode and so on.This might sound complicated at first, but has a huge advantage: you don't haveto break your fingers by holding several keys at once, most of the time yousimply press them one after the other. The more common the task, the fewer keysare 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 amotion.To change everything between parentheses, useci(
(readchange innerparentheses). To remove an entire paragraph of text, usedap
(readdeletearound paragraph).
If you see advanced Vim users working, you'll notice that they speak thelanguage of Vim as well as pianists handle their instruments. Complexoperations are done using only a few key presses. They don't even think about itanymore asmuscle memory tookover already. This reducescognitiveload and helps to focus on theactual task.
Vim comes bundled with an interactive tutorial that teaches the most basicthings 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. Theeditors or IDEs you used before were most probably all non-modal, so working byswitching modes will seem awkward at first, but the more you use Vim, the moreit becomesmuscle memory.
Vim was bolted onStevie, avi clone, and supports two operating modes:"compatible" and "nocompatible". Using Vim in compatible mode means using videfaults for all options, opposed to Vim defaults. As long as you didn't createa user vimrc yet or started Vim withvim -N
, compatible mode is assumed! Don'tuse Vim in compatible mode. Just don't.
Next steps:
- Create your ownvimrc.
- Have somecheatsheets ready for the first weeks.
- Read through thebasics section to learn what is even possible.
- Learn on demand! You never finish learning Vim. If you encounter anyproblems, 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.
- Have a look at theadditional resources.
One last advice: Please learn how to use Vim properly before starting to add allkinds of hypedplugins that only implement features thatVim already supports natively.
The user vimrc can be put into~/.vimrc
or for the sake of better separationinto~/.vim/vimrc
. The latter makes it easy to put the entire configurationunder 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 asminimal as it should be, but it provides a good set of sane settings that I deemto be useful for starting out.
Eventually you have to read up on all the mentioned settings anyway and decidefor yourself. :-)
So here it is:minimal-vimrc
In case you're interested, here'smy vimrc.
TIP: Most plugin authors maintain several plugins and also publish theirvimrc on GitHub (often in a repository called "vim-config" or "dotfiles"), sowhenever you find a plugin you like, look up its maintainer's GitHub page andlook through the repositories.
Looking at:version
will give you all the information you need to know abouthow 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 statesIncluded patches: 1-1051
, which is the patchlevel. Thus, your exact Vim version is 7.4.1051.
Another line states something likeTiny version without GUI
orHuge version with GUI
. The obvious information from that is whether your Vim includes GUIsupport, e.g. for startinggvim
from the shell or running:gui
from Vimwithin a terminal emulator. The other important information is theTiny
andHuge
. Vim distinguishes between feature sets calledtiny
,small
,normal
,big
, andhuge
, 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 itwasn't compiled in.
A few Vim features need to be compiled in for them to work. E.g. for:prof
towork, 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 sureto install a package calledvim-x
,vim-x11
,vim-gtk
,vim-gnome
orsimilar, 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 stuffendif
Help:
:h :version:h feature-list:h +feature-list:h has-patch
- 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.
Vim is a text editor. Every time text is shown, the text is part of abuffer. Each file will be opened in its own buffer. Plugins show stuff intheir 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 todisk on saving.
Windows are viewportsonto buffers. If you want to view several files atthe same time or even different locations of the same file, you use windows.
And please, please don't call themsplits. You can split a window in two, butthat doesn't make themsplits.
Windows can be split vertically or horizontally and the heights and widths ofexisting windows can be altered, too. Therefore, you can use whatever windowlayout you prefer.
Atab page (or just tab) is a collection of windows. Thus, if you want touse multiple window layouts, use tabs.
Putting it in a nutshell, if you start Vim without arguments, you'll have onetab page that holds one window that shows one buffer.
By the way, the buffer list is global and you can access any buffer from anytab.
Run Vim like thisvim file1
. The file's content will be loaded into a buffer.You have aloaded buffer now. The content of the buffer is only synchronizedto disk (written back to the file) if you save it within Vim.
Since the buffer is also shown in a window, it's also anactive buffer. Nowif you load another file via:e file2
,file1
will become ahidden bufferandfile2
the active one.
Both buffers are alsolisted, thus they will get listed in the output of:ls
. Plugin buffers or help buffers are often marked as unlisted, sincethey're not regular files you usually edit with a text editor. Listed andunlisted buffers can be shown via:ls!
.
Unnamed buffers, also often used by plugins, are buffers that don't have anassociated filename. E.g.:enew
will create an unnamed scratch buffer. Addsome text and write it to disk via:w /tmp/foo
, and it will become a namedbuffer.
Theglobal buffer list is a Vim thing. Before that, invi, 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 theargument list. There can be multiple argument lists: by default all argumentsare put into the global argument list, but you can use:arglocal
to create anew argument list that is local to the window.
List the current arguments with:args
. Switch between files from the argumentlist 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 isa matter of taste. My impression is that most people use the buffer listexclusively.
Nevertheless, there is one huge use case for the argument list: batch processingvia: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 filesfrom the current directory and below.
Help::h argument-list
You can define your own mappings with the:map
family of commands. Eachcommand of that family defines a mapping for a certain set of modes. TechnicallyVim comes with a whopping 12 modes, 6 of them can be mapped. Additionally, somecommands 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 tobeginners::nmap
isrecursive! That is, the right-hand side takes othermappings into account.
So you defined a mapping that simply echoes "Foo":
:nmapb:echo "Foo"<cr>
But what if you want to map the default behavior ofb
(going one word back) toanother key?
:nmapab
If you hita, we expect the cursor to go back a word, but instead"Foo" is printed in the command-line! Because the right-hand side,b
, wasmapped to another action already, namely:echo "Foo"<cr>
.
The proper way to resolve this problem is to use anon-recursive mappinginstead:
:nnoremapab
Rule of thumb: Always use non-recursive mappings unless recursing is actuallydesired.
Look up your mappings by not giving a right-hand side. E.g.:nmap
shows allnormal mappings and:nmap <leader>
shows all normal mappings that start withthe 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
The mapleader is simply a placeholder than can be used with custom mappings andis 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 ineffect already, won't change just because the mapleader was changed.:nmap <leader>
will show all normal mode leader mappings with the mapleader resolvedalready, so use it to double-check your mappings.
See:h mapleader
and:h maplocalleader
for more.
Registers are slots that save text. Copying text into a register is calledyanking and extracting text from a register is calledpasting.
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 to9 | vim | [ ] | Register0 : Last yank. Register1 : Last deletion. Register2 : Second last deletion. And so on. Think of registers1 -9 as a read-onlyqueue with 9 elements. |
Small delete | - | vim | [ ] | Last deletion that was less than one line. |
Named | a toz ,A toZ | user | [ ] | If you yank to registera , you replace its text. If you yank to registerA , you append to the text in registera . |
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 theclipboard 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'
Afterwardsn would jump to the next occurrence of "register".
There are numerous exceptions when registers get implicitly filled, so be sureto read:h registers
.
Yank withy
and paste withp
/P
, but mind that Vim distinguishes betweencharacterwise and linewise visual selections. See:h linewise
.
Example: linewise
yy
(or justY
) yanks the current line, move the cursor somewhere else, usep
to paste below the current lineP
for pasting above it.
Example: charwise
Yank the first word with0yw
, move somewhere else, paste after the cursor onthe current line withp
and before the cursor withP
.
Example: explicit naming of register
"aY
yanks the current line into registera
. Move to another line."AY
appends the current line to registera
.
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 (orreinserting previouslykilled text) not copying.
Ranges are pretty easy to understand, but many Vimmers don't know about theirfull 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. 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 for1,$ ). |
:.,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 bymark 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 thatin the case offrom,to
, theto is relative to the current line, but whenusingfrom;to
, theto is relative to the address offrom! Assuming you'reon line 5,:1,+1d
would delete lines 1 to 6, whereas:1;+1d
would onlydelete lines 1 and 2.
The/
address can be preceded with another address. This allows you tostackpatterns, e.g.:
:/foo//bar//quux/d
This would delete the first line containing "quux" after the first linecontaining "bar" after the first line containing "foo" after the current line.
Sometimes Vim automatically prepends the command-line with a range. E.g. start avisual line selection withV
, select some lines and type:
. The command-linewill be populated with the range'<,'>
, which means the following command willuse the previously selected lines as a range. (This is also why you sometimessee mappings like:vnoremap foo :<c-u>command
. Here<c-u>
is used to removethe range, because Vim will throw an error when giving a range to a command thatdoesn't support it.)
Another example is using!!
in normal mode. This will populate thecommand-line with:.!
. If followed by an external program, that program'soutput would replace the current line. So you could replace the currentparagraph with the output of ls by using:?^$?+1,/^$/-1!ls
. Fancy!
Help:
:h cmdline-ranges:h 10.3
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 calledfile 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.
Usemm
to remember the current position with mark "m". Move around the fileand then jump back via'm
(first non-blank) or`m
(exact column).Lowercase marks will be remembered after exiting Vim, if you tell your viminfofile to do so, see:h viminfo-'
.
UsemM
to remember the current position with file mark "M". Switch to anotherbuffer 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 arange. You probably saw this before andwondered what it means: Select some text in visual mode and do:
, thecommand-line will be prepended with:'<,'>
, which means the following commandwould get a range that denotes the visual selection.
Use:marks
to list all marks. Read everything in:h mark-motions
.
Vim provides many kinds of insert mode completions. If there are multiplematches, a popup menu will let you navigate to the match of your choice.
Typical kinds of completion are tags, functions from imported modules orlibraries, 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 completionand omni completion, but technically they do the same thing. They take afunction 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-specificpurposes, like completing struct members or class methods, and is often set byfiletype 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 totrim 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 forchoosing entries in the popup menu. See:h i^n
and:h 'complete'
for more onthis.
Be sure to check out:h 'completeopt'
for configuring the behaviour of thepopup 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 move the cursor. You all knowh
/j
/k
/l
. Orw
andb
. Even/
is a motion. They also take a count.2?the<cr>
jumps to the second lastoccurrence 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 afew. They get used in two contexts, either in normal or visual mode. In normalmode, 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 currentword and the next one uppercase. Since motions and operators take counts,2gU2w
works just as well and executesgU2w
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 intoone direction. Actually they work on objects, e.g. a whole word, a wholesentence, everything between parentheses, and so on.
Text objects can't be used to move the cursor in normal mode, because even themost-skilled cursors can't jump into two directions at the same time. It worksin visual mode though, because then one side of the object is already selectedand the cursor simply jumps to the other side.
Text objects start with eitheri
(thinkinner) ora
(thinkaround)followed by a character denoting the object. Withi
it only acts on the objectitself, witha
on the object plus trailing whitespace. E.g.diw
deletes thecurrent word andci(
changes everything between parentheses.
Text objects take a count. Imagine((( )))
and the cursor on or between themost inner parentheses, thend2a(
will remove the 2 inner pairs of parenthesesand everything in between.
See:h text-objects
for all available text objects.
You can trigger an action after many events in Vim, such as a buffer beingsaved or Vim having started up, by so-calledautocmds.
Vim relies extensively on autocmds. Don't believe me? Check:au
, but don't letthe output overwhelm you. These are all the autocmds that are in effect rightnow!
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:
autocmdFileTyperubysetlocalshiftwidth=2softtabstop=2comments-=:#
But how does a buffer even know that it contains Ruby code? Because anotherautocmd detected it as that and set the filetype accordingly which againtriggered theFileType
event.
One of the first things everyone adds to their vimrc isfiletype on
. Thissimply means thatfiletype.vim
is read at startup which sets autocmds foralmost all filetypes under the sun.
If you're brave enough, have a look at it::e $VIMRUNTIME/filetype.vim
. Searchfor "Ruby" and you'll find that Vim simply uses the file extension.rb
todetect Ruby files:
NOTE: Autocmds of the same event are executed in the order they werecreated.:au
shows them in the correct order.
auBufNewFile,BufRead*.rb,*.rbwsetfruby
TheBufNewFile
andBufRead
events in this case are hardcoded in the Csources of Vim and get emitted every time you open a file via:e
and similarcommands. Afterwards all the hundreds of filetypes fromfiletype.vim
aretested for.
Putting it in a nutshell, Vim makes heavy use of events and autocmds but alsoexposes a clean interface to hook into that event-driven system forcustomization.
Help::h autocommand
The positions of the last 100 changes are kept in thechangelist. Severalsmall changes on the same line will be merged together, but the position will bethat of the last change nevertheless (in case you added something in the middleof the line).
Every time you jump, the positionbefore the jump is remembered in thejumplist. A jumplist has up to 100 entries. Each window has its ownjumplist. 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 commandsthat 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 currentposition. Usually that will be below position 1, the latest position.
If you want both lists to persist after restarting Vim, you need to use theviminfo file and:h viminfo-'
.
NOTE: The position before the latest jump is also kept as amarkand can be jumped to via``
or''
.
Help:
:h changelist:h jumplist
The latest changes to the text state are remembered. You can useundo torevert changes andredo to reapply previously reverted changes.
The important bit to understand it that the data structure holding recentchanges is not aqueue but atree! Your changes arenodes in the tree and each (but the top node) has a parent node. Each node keepsinformation about the changed text and time. A branch is a series of nodes thatstarts from any node and goes up to the top node. New branches get created whenyou undo a change and then insert something else.
ifoo<esc>obar<esc>obaz<esc>uoquux<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 thetime the nodes werecreated.
Now there are two ways to traverse this tree, let's call thembranch-wise andtime-wise.
Undo (u
) and redo (<c-r>
) work branch-wise. They go up and down the currentbranch.u
will revert the text state to the one of node "bar". Anotheru
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-
andg+
work time-wise. Thus,g-
won't revert to thestate of node "bar", likeu
does, but to the chronologically previous state,node "baz". Anotherg-
would revert the state to the one of node "bar" and soon. Thus,g-
andg+
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. SeeUndofiles for how to enable persistent undo.
If you're confused by the undo tree,undotree does a great job at visualizingit.
Help:
:h undo.txt:h usr_32
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 andoptional 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 quickfixbuffer. 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 windowand<c-w><cr>
in a new window.
The quickfix list was named after the "quick fix" feature from theAztec Ccompiler.
Actually there are two kinds of lists: quickfix and location lists. They behavealmost the same, but have the follwing differences:
- There is only one quickfix list. There can be multiple location lists; one perwindow.
- 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 thesecommands to work.
See:h quickfix
for more information and a full list of commands.
For conciseness,quickfix andlocation are often abbreviated asqf andloc respectively.
Example:
Let us use our good old friendgrep
for searching the files in the currentdirectory recursively for a certain query and put the results in the quickfixlist.
:let &grepprg='grep -Rn $* .':grep! foo<grep output - hit enter>:copen
Assuming any files contained the string "foo", it should be shown now in thequickfix window.
Vim allowsrecording typed characters into aregister. It's agreat way to automate certain tasks on the fly. (For more elaborate tasks, Vimscripting should be used instead.)
- Start recording by typing
q
followed by the register, e.g.q
. (Thecommand-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:
qqiabc<cr><esc>q10@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
.
qq0yf jP0^Aq1000@q
Here we simply hope that the file doesn't contain more than 1000 lines whenusing1000@q
, but we can also use arecursive macro, which executes untilthe macro can't be applied to a line anymore:
qq0yf jP0^A@qq@q
(The same could be done without macros::%s/^/\=line('.') . '. '
)
Mind that I also show how to achieve the same without using macros, but thismostly works only for such simple examples. For more complex automation, macrosare the bomb!
Also see:Quickly edit your macros
Help:
:h recording:h 'lazyredraw'
Colorschemes are the way to style your Vim. Vim consists of many components andeach 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 likethis:
:highlightNormal ctermbg=1 guibg=red
This would paint the background of the editor red. See:h :highlight
for moreinformation.
So, colorschemes are mostly collections of:highlight
commands.
Actually, most colorschemes are really 2 colorschemes! The example above setscolors viactermbg
andguibg
. The former definition (cterm*
) will only beused 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'tlook like the ones in the screenshot at all, chances are that the colorschemeonly 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 definecolors for the terminal.
The latter case can be "solved" by enabling true colors in Neovim or Vim7.4.1830 and newer. This makes terminal Vim use the GUI definitions instead, butalso requires the terminal emulator itself and all software in between (e.g.tmux) to be capable of handling true colors. (Thisgist gives a good overview about thetopic.)
Help:
:h 'termguicolors'
- List of colorschemes
- Cosmetic changes to colorschemes
Every text (or source code) has a certain structure. If you have a structure, itmeans you have regions of logically separated text. Folding allows to "fold"such a region into a single line and displaying a short description. There aremany commands that act on these regions calledfolds. 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 viazf ,zF , and:fold . |
marker | Folds based on markers in the text (often in comments). |
syntax | Folds based on syntax, e.g. foldingif blocks. |
NOTE: Folding can be computationally intensive! If you experience anyperformance drawbacks (small delays when typing), have a look atFastFold, which prevents Vim fromupdating folds when it's not needed.
Help:
:h usr_28:h folds
If you save aview (:h :mkview
), the current state of the window (andoptions and mappings) gets saved for later use (:h :loadview
).
Asession saves the views of all windows plus global settings. It basicallymakes 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 asession won't be part of the session file. To "update" a session, simply writeit out again.
This makes it perfect for saving yourprojects and easy to switch betweenthem.
Try it right now! Open a few windows and tabs and do:mksession Foo.vim
. Ifyou omit the filename,Session.vim
will be assumed. The file will be saved tothe current working directory, check:pwd
. Restart Vim and do:source Foo.vim
and voilà, the buffer list, window layout, mappings, working directoryetc. should all be the same as before you saved the session. Do some more workand 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 aresupposed to restore a certain state of a Vim instance, so feel free to take alook 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 sessionin the internal variablev:this_session
.
Help:
:h Session:h 'sessionoptions':h v:this_session
Many of the concepts mentioned above also havelocal 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.
Vim comes with great documentation in the form of single text files with aspecial layout. Vim uses a system based on tags for accessing certain parts ofthose 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
tagwithin 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 isctrl+d) to list all tags thatmatch the currently entered query. E.g.:h tab<c-d>
will get you a list of alltags fromtab
over'softtabstop'
tosetting-guitablabel
.
You want to list all VimL functions? Simple::h ()<c-d>
. You want to list allVimL functions that concern windows?:h win*()<c-d>
.
This quickly becomes second nature, but especially in the beginning, yousometimes don't know any part of the tag you are looking for. You can onlyimagine 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 firstmatch. The matches will be assembled in the quickfix list. Use:cn
/:cp
tojump 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
forthe whole truth.
This list was compiled by @chrisbra, one of the most active Vim developers, andposted tovim_dev.
It's reposted here with minor changes.
If you know what you are looking for, it is usually easier to search for itusing the help system, because the subjects follow a certain style guide.
Also, the help has the advantage of belonging to your particular Vim version, sothat 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 forgottensomething).
Options are enclosed in single quotes. So you would use
:h 'list'
to go tothe help topic for the list option. If you only know, you are looking for acertain option, you can also do:h options.txt
to open the help page whichdescribes all option handling and then you can search using regularexpressions e.g./width
. Certain options have their own namespace, e.g.:h cpo-a
,:h cpo-A
,:h cpo-b
, and so on.Normal mode commands are just that. Use
:h gt
to go to the help page forthe "gt" command.Regexp items always start with "/", so
:h /\+
takes you to the help itemfor the "+" quantifier in Vim regexes. If you need to know anything aboutregular expressions, start reading at:h pattern.txt
.Key combinations. They usually start with a single letter indicating the modefor which they can be used. E.g.
:h i_CTRL-X
takes you to the family ofCTRL-X commands for insert mode which can be used to auto complete differentthings. Note that certain keys will always be written the same, e.g. Controlwill 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 doeswhen entering commands in the command line and:h v_Ctrl-A
talks aboutincrementing numbers in visual mode and:h g_CTRL-A
talks about the gcommand (thus you have to press "g" then ). Here the "g" stand forthe normal command "g" which always expect a second key before doingsomething similar to the commands starting with "z".Registers always start with "quote" so use
:h quote
to find out about thespecial ":" register.Vim script (VimL) is available at
:h eval.txt
. Certain aspects of thelanguage 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 forVimL. Also important, see:h function-list
to find a short description ofall functions available.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 outabout certain subtopics particular for mappings (e.g.:h :map-local
forbuffer-local mappings or:h map_bar
for how the '|' is handled in mappings.Command definitions are talked about at
:h command-*
, so use :h command-barto find out about the '!' argument for custom commands.Window management commands always start with CTRL-W, so you find thecorresponding help at
:h CTRL-W_*
(e.g.:h CTRL-W_p
for switch to thepreviously accessed window). You can also access:h windows.txt
and readyour way through, if you are looking for window handling command.Ex commands always start with ":", so
:h :s
covers the ":s" command.Use CTRL-D after typing a topic and let Vim try to complete to all availabletopics.
Use
:helpgrep
to search in all help pages (usually also includes helppages by installed plugins). See:h :helpgrep
for how to use it. Once youhave searched for a topic, all matches are available in the quickfix (orlocation) window which can be opened with:copen
or:lopen
. There youcan also use/
to further filter the matches.:h helphelp
contains some information on how to use the help.The user manual. This describes help topics for beginners in a ratherfriendly way. Start at
:h usr_toc.txt
to find the table of content (as youmight have guessed). Skimming over that help to find certain topics, .e.gyou will find an entry "Digraphs" and "Entering special characters" inchapter 24 (so use:h usr_24.txt
to go to that particular help page).Highlighting groups always start with
hl-*
. E.g.:h hl-WarningMsg
talksabout the "WarningMsg" highlighting group.Syntax highlighting is namespaced to ":syn-topic", e.g.
:h :syn-conceal
talks about the conceal argument for the :syn command.Quickfix commands usually start with ":c", while location list commandsusually start with ":l".
:h BufWinLeave
talks about the BufWinLeave autocmd. Also,:h autocommands-events
talks about all possible events.Startup arguments always start with "-", so
:h -f
takes you to the help ofthe "-f" command switch of Vim.Compiled extra features always start with "+", so
:h +conceal
talks aboutthe conceal support.Error codes can be looked up directly in the help.
:h E297
takes youexactly to the description of the error message. Sometimes however, thoseerror codes are not described, but rather are listed at the Vim command thatusually causes this. E.g.:h hE128
takes you directly to the:function
command.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 theoptions 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 morefrom a user perspective and less detailed) will be mentioned at the top of helppages if they are available. So:h pattern.txt
mentions the user guide topics:h 03.9
and:h usr_27
.
If you have an issue you can't resolve or are in need of general guidance, seethevim_use mailing list.Another great resource is usingIRC. The channel#vim
onFreenode is huge and usually full of helpful people.
If you want to report a Vim bug, use thevim_dev mailing list.
You can trigger any event right now::doautocmd BufRead
.
Especially for plugins it's useful to create your own "User" events:
function!Chibby()" A lot of stuff is happening here." And at last.. doautocmdUser ChibbyExitendfunction
Now users of your plugin can execute anything when Chibby finishes running:
autocmdUserChibbyExitcallChibbyCleanup()
By the way, if there's no "catching" :autocmd, :doautocmd will output a pesky"No matching autocommands" message. That's why many plugins usesilent doautocmd ...
instead. But this has the disadvantage, that you can't simply useecho "foo"
in the :autocmd, you have to useunsilent echo "foo"
instead..
That's why it's better to check if there even is a receiving autocmd and notbothering emitting the event otherwise:
ifexists('#User#ChibbyExit') doautocmdUser ChibbyExitendif
Help::h User
By default, autocmds do not nest! If an autocmd executes a command, which inturn would usually trigger another event, it won't happen.
Let's say every time you start Vim, you want to automatically open your vimrc:
autocmdVimEnter*edit$MYVIMRC
When you now start Vim, it will open your vimrc, but the first thing you'llnotice 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 thisinstead:
autocmdVimEnter* nestededit$MYVIMRC
Help::h autocmd-nested
Requiredfeatures:+clipboard
and optionally+xterm_clipboard
if you want to use the'clipboard'
option on a Unix systemwith 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 thetime?)
Windows comes with aclipboardand macOS comes with apasteboard.
Both work like most users would expect them to work. You copy selected text withctrl+c
/cmd+c
and paste them in another application withctrl+v
/cmd+v
.
Note that copied text is actually transferred to the clipboard, so you can closethe application you copied from before pasting in another application withoutproblems.
Whenever this happens, the clipboard register*
gets filled with theselection. From Vim use"*y
and"*p
to yank and paste from the clipboardrespectively.
If you don't even want to specify the*
register all the time, put this inyour vimrc:
setclipboard=unnamed
Usually all yank/delete/put operations fill the"
register, now the*
register is used for the same operations, therefore simplyy
andp
will beenough.
Let me repeat: Using the option above means that every yank/paste, even whenonly used in the same Vim window, will alter the clipboard. Decide for yourselfif this is useful or not.
If you're even too lazy to typey
, you can send every visual selection to theclipboard by using these settings:
setclipboard=unnamed,autoselectsetguioptions+=a
Help:
:h clipboard-unnamed:h autoselect:h 'go_a'
If your OS usesX, things work a bit different. Ximplements theX Window SystemProtocol whichhappens to be at major version 11 since 1987, hence X is also often called X11.
Prior, in X10,cutbufferswere introduced that kind of worked like aclipboard as in copied text wasactually held by X and it was accessible by all other applications. Thismechanism still exists in X, but its use is deprecated now and most softwaredoesn't use it anymore.
Nowadays data is transferred between applications by the means ofselections.From the 3selection atoms defined, only 2 are used in practice: PRIMARY andCLIPBOARD.
Selections work roughly like this:
Program A: <ctrl+c>Program A: assert ownership of CLIPBOARDProgram B: <ctrl+v>Program B: note that ownership of CLIPBOARD is hold by Program AProgram B: request data from Program AProgram A: respond to request and send data to Program BProgram 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 andctrl+c | ctrl+v | + register |
NOTE: Selections (no, not even the CLIPBOARD selection) are never kept inthe X server! Thus, you lose the data copied withctrl+c
when the applicationcloses.
Use"*p
to paste the PRIMARY selection or"+y1G
to yank the entire file tothe CLIPBOARD selection.
If you happen to access one of the two registers all the time, consider using:
setclipboard^=unnamed" * register" orsetclipboard^=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 ofthe unnamed register"
. Afterwards you can simply usey
orp
for accessingyour chosen X selection.
Help:
:hclipboard-unnamed:hclipboard-unnamedplus
When you open a file, the cursor will be positioned at line 1, column 1.Fortunately the viminfo file remembersmarks. The"
mark containsthe position in the buffer where you left off.
autocmdBufReadPost*\ifline("'\"") >1&&line("'\"")<=line("$") |\execute"normal! g`\"" |\endif
Read: If the mark"
contains a line number greater than line 1 but not greaterthan the last line in the file, jump to it.
:h viminfo-':h `quote:h g`
Before saving a file, Vim creates a backup file. If writing to disk wassuccessful, the backup file will be deleted.
With:set backup
, the backup will persist. This means, the backup file willalways have the same content as the original filebefore 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 youshouldn't need to nowadays.'writebackup'
is a security feature that makessure 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 probablyshouldn't, you can exclude those from backups with'backupskip'
.
Vim knows different ways to create a backup:copying andrenaming.
- Copying
- A full copy of the original file is created and used as backup.
- The original file gets emptied and then filled with the content of theVim buffer.
- Renaming
- The original file is renamed to the backup file.
- The content of the Vim buffer gets written to a new file with the name ofthe original file.
See:h 'backupcopy'
for all the nitty-gritty details.
Demo:
:setbackupbackupskip=backupdir=.backupext=-backup:e/tmp/fooifoo<esc>:w" original file gets created, no need for backup fileobar<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
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 for4 seconds. They get deleted when you stop editing the file. You can change thesenumbers with:h 'updatecount'
and:h 'updatetime'
.
If Vim gets killed (e.g. power outage), you lose all changes since the last timethe file was written to disk, but the swap file won't be deleted. Now, if youedit the file again, Vim will offer the chance to recover the file from the swapfile.
When two people try to edit the same file, the second person will get a noticethat the swap file already exists. It prevents people from trying to savedifferent versions of a file. If you don't want that behaviour, see:h 'directory'
.
:h swap-file:h usr_11
Theundo 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
When backup, swap, and undo files are all about text state, viminfo files areused 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'
Put all temporary files in their own directory under~/.vim/files
:
" create directory if neededif!isdirectory($HOME.'/.vim/files')&&exists('*mkdir')callmkdir($HOME.'/.vim/files')endif" backup filessetbackupsetbackupdir=$HOME/.vim/files/backup/setbackupext=-vimbackupsetbackupskip=" swap filessetdirectory=$HOME/.vim/files/swap//setupdatecount=100" undo filessetundofilesetundodir=$HOME/.vim/files/undo/" viminfo filessetviminfo='100,n$HOME/.vim/files/info/viminfo
Vim comes with the netrw plugin that enables editing remote files. Actually ittransfers the remote file to a local temporary file via scp, opens a bufferusing 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 tossh'ing into a server and use whatever the admins want you to use.
:e scp://bram@awesome.site.com/.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 usingsshfswhich usesFUSE tomount a remote filesystem into your local filesystem.
Pathogen was the first popular tool formanaging plugins. Actually it just adjusts theruntimepath (:h 'rtp'
) toinclude all the things put under a certain directory. You have to clone therepositories of the plugins there yourself.
Real plugin managers expose commands that help you to install and update pluginsfrom within Vim.
This is a technique to insert the same text on multiple consecutive lines at thesame time. See thisdemo.
Switch to visual block mode with<c-v>
. Afterwards go down for a few lines.HitI
orA
and start entering your text.
It might be a bit confusing at first, but text is always entered for the currentline and only after finishing the current insertion, the same text will beapplied 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 rightafter 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 currentline. You can't do that by default, but you can set thevirtualedit
option:
setvirtualedit=all
Afterwards$10l
or90|
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 atmultiple-cursors.
Disclaimer: Vim is single-threaded, so running an external program in theforeground will block everything else. Sure, you can use one of Vim'sprogramming interfaces, e.g. Lua, and use its thread support, but during thattime the Vim process is blocked nevertheless. Neovim fixed that by adding aproper job API.
(Apparently Bram is thinking about adding job control to Vim as well. If youhave a very recent version, see:helpgrep startjob
.)
Use:!
to start a job. If you want to list the files in the current workingdirectory, 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 theother hand, if a range is given, these lines will befiltered. This means theywill be piped to thestdinof the filter program and after processing be replaced by thestdoutof 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 somehelpers for convenience. As always with ranges, you can also select lines invisual 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 theGo programminglanguage. The indentation is pretty opinionated, it evencomes with a filter calledgofmt
for indenting Go source code properly. Soplugins 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 does more things thanctags, but only supports C (and C++ and Java tosome extent).
Whereas a tags file only knows where a symbol was defined, a cscope databaseknows 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?
Do this in the root of your project:
$ cscope -bqR
This will create 3 files:cscope{,.in,.po}.out
in the current workingdirectory. Think of them as your database.
Unfortunatelycscope
only analyzes*.[c|h|y|l]
files by default. If you wantto use cscope for a Java project instead, do this:
$ find. -name"*.java"> cscope.files$ cscope -bq
Open a connection to your freshly built database:
:csaddcscope.out
Verify that the connection was made:
:cs show
(Yes, you can add multiple connections.)
:csfind<kind><query>
E.g.:cs find d foo
will list all functions that are called byfoo(...)
.
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. Theoption'cscopetag'
makes:tag
act like:cstag
automatically. This is veryconvenient if you already have tag-related mappings.
Help::h cscope
Since Vim is written in C, a lot of features assume C-like syntax. By default,if your cursor is on{
or#endif
, you can use%
to jump to thecorresponding}
or#ifdef
respectively.
Vim comes bundled with a plugin called matchit.vim which is not enabled bydefault. It makes%
also cycle through HTML tags, if/else/endif constructs inVimL etc. and introduces a few new commands.
" vimrcpackadd! matchit
" vimrcruntime macros/matchit.vim
Since the documentation of matchit is pretty extensive, I suggest also doing thefollowing once:
:!mkdir-p~/.vim/doc:!cp$VIMRUNTIME/macros/matchit.txt~/.vim/doc:helptags~/.vim/doc
The plugin is ready to use now. See:h matchit-intro
for the supportedcommands and:h matchit-languages
for the supported languages.
That said, it's easy to define your own matching pairs:
autocmdFileTypepythonletb:match_words='\<if\>:\<elif\>:\<else\>'
Afterwards you can cycle through these 3 statements in any Python file by using%
(forward) org%
(backward).
Help:
:h matchit-install:h matchit:h b:match_words
Using true colors in a terminal emulator means being able to use 24 bits for RGBcolors. That makes 16777216 (2^24) colors instead of the usual 256.
As explainedhere, colorschemes can actually betwocolorschemes 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 understoodby a terminal emulator that supports true colors. When your colors look weird,chances are your terminal emulator doesn't support true colors or yourcolorcheme has no GUI colors defined.
Many people use the terminal multiplexertmux which basically sits in between theterminal emulator and Vim. To make tmuxforward the true color escapesequences 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
tobe usedwithin tmux. - The second line adds the tmux-specific
Tc
(true color) capability to theother terminfo entries ofxterm-256color
. Obviously this assumes that theuser is usingTERM=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 containlines with
guifg
andguibg
.) - 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
o
andO
in a visual selection make the cursor go to the other end. Try withblockwise selection to see the difference. This is useful for quickly changingthe size of the selected text.
:h v_o:h v_O
The direction ofn
andN
depends on whether/
or?
was used forsearching forward or backward respectively. This is pretty confusing to me.
If you wantn
to always search forward andN
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]
If you're anything like me, you're used to going to next and previous items via<c-n>
and<c-p>
respectively. By default, this also works in thecommand-line and recalls older or more recent command-lines from history.
So far, so good. But<up>
and<down>
are even smarter! They recall thecommand-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 for the arrow keys:
cnoremap<expr><c-n>wildmenumode() ? "\<c-n>" : "\<down>"cnoremap<expr><c-p>wildmenumode() ? "\<c-p>" : "\<up>"
Here we also distinguish between command-line history and the wildmenu. See:h 'wildmenu'
.
I depend on this behaviour several times a day.
By default,<c-l>
clears and redraws the screen (like:redraw!
). Thefollowing mapping does the same, plus de-highlighting the matches found via/
,?
etc., plus fixing syntax highlighting (sometimes Vim loses highlighting dueto complex highlighting rules), plus force updating the syntax highlighting indiff mode:
nnoremap<leader>l :nohlsearch<cr>:diffupdate<cr>:syntax sync fromstart<cr><c-l>
setnoerrorbellssetnovisualbellsett_vb=
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, so2]e
moves the current line 2 lines below.
nnoremap[<space>:<c-u>put! =repeat(nr2char(10), v:count1)<cr>'[nnoremap]<space>:<c-u>put =repeat(nr2char(10), v:count1)<cr>
Now5[<space>
inserts 5 blank lines above the current line.
This is a real gem! The mapping takes a register (or*
by default) and opensit in the cmdline-window. Hit<cr>
when you're done editing for setting theregister.
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 insertedliterally. See:h c_^R^R
.
This technique can probably be applied to many filetypes. It setsfile marks(see:h marks
) when leaving a source or header file, so you can quickly jumpback to the last accessed one by using'C
or'H
(see:h 'A
).
autocmdBufLeave*.{c,cpp}mark CautocmdBufLeave*.hmark H
NOTE: The info is saved in the viminfo file, so make sure that:set viminfo?
includes:h viminfo-'
.
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','')
I like to use a block cursor in normal mode, i-beam cursor in insert mode, andunderline cursor in replace mode.
ifempty($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"elselet &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 (escapesequence) when entering/leavinginsert mode. The underlying terminal, or programs liketmux that sit between Vim and the terminal, willprocess and evaluate it.
There's one drawback though: there are many terminal emulator implementationsand not all use the same sequences for doing the same things. The sequences usedabove might not work with your implementation. Your implementation might noteven support different cursor styles. Check the documentation.
The example above works with iTerm2.
If you select one or more lines, you can use<
and>
for shifting themsidewards. Unfortunately you immediately lose the selection afterwards.
You can usegv
to reselect the last selection (see:h gv
), thus you can workaround it like this:
xnoremap<<gvxnoremap>>gv
Now you can use>>>>>
on your visual selection without any problems.
NOTE: The same can be achieved using.
, which repeats the last change.
Usingautocmds you can do anything on saving a file, e.g. sourcingit in case of a dotfile or running a linter to check for syntactical errors inyour source code.
autocmdBufWritePost$MYVIMRCsource$MYVIMRCautocmdBufWritePost~/.Xdefaultscallsystem('xrdb ~/.Xdefaults')
I love the cursorline, but I only want to use it in the current window and notwhen being in insert mode:
autocmdInsertLeave,WinEnter*setcursorlineautocmdInsertEnter,WinLeave*setnocursorline
The keyword completion (<c-n>
/<c-p>
) tries completing whatever is listed inthe'complete'
option. By default, this also includes tags (which can beannoying) and scanning all included files (which can be very slow). If you canlive without these things, disable them:
setcomplete-=i" disable scanning included filessetcomplete-=t" disable searching tags
Always use a dark gray statusline, no matter what colorscheme is chosen:
autocmdColorScheme*highlightStatusLine ctermbg=darkgray cterm=NONE guibg=darkgraygui=NONE
This triggers every time you use:colorscheme ...
. If you want it to triggeronly for a certain colorscheme:
autocmdColorSchemedeserthighlightStatusLine ctermbg=darkgray cterm=NONE guibg=darkgraygui=NONE
This triggers only for:colorscheme desert
.
Useful commands that are good to know. Use:h :<command name>
to learn moreabout them, e.g.:h :global
.
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 KenThompson. What does it do? It prints all lines matching a certain regularexpression! 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 takesa range. Assume you want use:delete
on all lines from the current line to thenext blank line (matched by the regular expression^$
) that contain "foo":
:,/^$/g/foo/d
For executing commands on all lines that donot match a given pattern, use:global!
or its alias:vglobal
(thinkinVerse) instead.
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 custommapping for "j" due to the "!").
Mind that:normal
also takes arange, so:%norm! Iabc
wouldprepend "abc" to every line.
With:execute
you can mix commands with expressions. Assume you edit a Csource 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 godown "n" lines:
:letn=4:execute'normal!'n .'j'
Many commands print messages and:redir
allows to redirect that output. Youcan redirect to files,registers or variables.
:redir=>var:reg:redir END:echovar:" 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()
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 nocompatiblemode (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! Reportit to thevim_dev mailinglist. Most of the time the issue won't be resolved at this time and you'll haveto further investigate.
Plugins often introduce new/changed/faulty behaviour. E.g. if it happens onsaving, 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 othersettings, so maybe your options or autocmds etc.
Time to use binary search. Repeatedly split the search space in two until youfind the culprit line. Due to the nature of binary division, it won't take manysteps.
In practice, it works like this: Put the:finish
command in the middle of yourvimrc. Vim will skip everything after it. If it still happens, the problem is inthe active upper half. Move the:finish
to the middle ofthat half.Otherwise, the issue is in the inactive lower half. Move the:finish
to themiddle ofthat half. And so on.
Another useful way for observing what Vim is currently doing is increasing theverbosity level. Currently Vim supports 9 different levels. See:h 'verbose'
for the full list.
:e/tmp/foo:setverbose=2:w:setverbose=0
This would show all the files that get sourced, e.g. the undo file or variousplugins 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 theverbosity level as count and defaults to 1:
:verbsetverbose" verbose=1:10verbsetverbose" verbose=10
It's very often used with its default verbosity level 1 to show where an optionwas set last:
:verbsetai?" Last set from ~/.vim/vimrc
Naturally, the higher the verbosity level the more overwhelming the output. Butfear no more, you can simply redirect the output to a file:
:setverbosefile=/tmp/foo |15verboseecho"foo" |vsplit/tmp/foo
You can also enable verbosity at starting time, with the-V
option. Itdefaults to verbosity level 10. E.g.vim -V5
.
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. Ifthere is a big jump in time between two lines, the second line is either a verybig file or a file with faulty VimL code that is worth investigating.
Requiredfeature:+profile
Vim provides a built-in capability for profiling at runtime and is a great wayto find slow code in your environment.
The:profile
command takes a bunch of sub-commands for specifying what toprofile.
If you want to profileeverything, 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 thelogfile on exit. (Neovim has fixed this using:profile dump
).
Have a look at/tmp/profile.log
. All code that was executed during profilingwill 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 sectionsFUNCTIONS SORTED ON TOTAL TIME
andFUNCTIONS SORTED ON SELF TIME
that are worth gold. At aquick 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
If you ever used a command-line debugger before,:debug
will quickly feelfamiliar.
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 thatline 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
, andf
.
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 aREPL bysimply using:debug 1
.
It would be a pain if you had to single-step through every single line, so ofcourse we can define breakpoints, too. (Breakpoints are called breakpoints,because the execution stops when they're hit, thus you can simply skip codeyou'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:
:auBufWritePost" signify BufWritePost" * call sy#start():breakaddfunc*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
inthis case.
:debug
can be used in combination with theverbose option.
Syntax files are often the cause for slowdowns due to wrong and/or complexregular expressions. If the+profile
featureis compiled in, Vim provides the super useful:syntime
command.
:syntimeon" hit <c-l> a few times to redraw the window which causes the syntax rules to get applied again:syntimeoff:syntimereport
The output contains important metrics. E.g. you can see which regexp takes toolong and should be optimized or which regexps are used all the time but nevereven match.
See:h :syntime
.
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. |
Vim distributions are bundles of custom settings and plugins for Vim.
More advanced users know how to configure their editor anyway, so distributionsare mostly targeted at beginners. If you think about that, it's quiteparadoxical 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 aneditor (and actually you never stop customizing your vimrc when you finally gothooked), but eventually you only get efficient in Vim when you take the time tolearn it properly.
Repeat after me: "A programmer should know their tools."
Anyway, if you know what you're doing, you might draw some inspiration fromlooking at a few distributions:
Many people are surprised by the fact that Vim comes with a handful of standardplugins. 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 thelatter.
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 bailsout. 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 |
CapsLock belongs to the most useless keys on your keyboard, but it's much easierto reach than the Control key, since it lies on yourhomerow.Mapping CapsLock to Control is a great way to prevent or at least reduceRSI if youprogram 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_Lockkeysym Caps_Lock = Control_Ladd Control = Control_L
Afterwards source it via$ xmodmap ~/.xmodmap
.
An alternative would be usingcaps2esc orxcape.
Windows:
Seesuperuser.com: Map Caps-Lock to Control in Windows8.1.
Generate HTML from any buffer using:TOhtml
from the 2htmlstandardplugin. The output can be used for printing or easy webpublishing.
The command creates a new buffer of the same name with.html
appended. Thecolors are the same as seen in Vim. They depend on thecolorscheme.
The plugin knows several options to finetune the output, e.g. for setting theencoding and font.
See:h :TOhtml
.
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. |
:hi! | Greetings, Vim user! |
WhenBill Joy createdvi, a predecessor of Vim, he did it on aADM-3A which had no extra cursor buttonsbut 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.
There are two things which can have a huge impact on performance:
- Complexregular expressions. Particular the Ruby syntax file causedpeople to have slowdowns in the past. (Also seeDebugging syntax files.)
- 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 orFastFold |
: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 performancedrawbacks. In most cases using the things mentioned above is absolutely fine.
The biggest issue with big files is, that Vim reads the whole file at once. Thisis 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 expensiveregular expressions for syntax highlighting are used. You should also tell Vimnot 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 reallyhuge files. :\
Bracketed paste mode allows terminal emulators to distinguish between typed textand pasted text.
Did you ever tried pasting code into Vim and afterwards everything seemed messedup?
This only happens if you paste viacmd+v
,shift-insert
,middle-click
etc.because then you're just throwing text at the terminal emulator. Vim doesn'tknow 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 fineplugin 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 setsbracketed paste mode automatically if the terminal emulator supports it.
If you live in the command-line, you probably use a so-calledterminalemulator like xterm, gnome-terminal, iTerm2, etc. (opposed to a realterminal).
Like their ancestors, terminal emulators useescapesequences (orcontrolsequences) to control things like moving the cursor, changing text colors, etc.They're simply strings of ASCII characters starting with an escape character(displayed incaret notation as^[
). When such a string arrives, the terminal emulator looks up theaccompanying action in theterminfodatabase.
To make the problem clearer, I'll explain mapping timeouts first. They alwayshappen when there's ambiguity between mappings:
:nnoremap,a:echo 'foo'<cr>:nnoremap,ab:echo 'bar'<cr>
Both mappings work as expected, but when typing,a
, there will be a delay of 1second, because Vim waits whether the user keys in anotherb
or not.
Escape sequences pose the same problem:
<esc>
is used a lot for returning to normal mode or quitting an action.- Cursor keys are encoded using escape sequences.
- Vim expectsAlt (also calledMeta key) to send a proper 8-bitencoding 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.
You can test the above like this:vim -u NONE -N
and typei<c-v><left>
andyou'll see a sequence inserted that starts with^[
which denotes the escapecharacter.
Putting it in a nutshell, Vim has a hard time distinguishing between a typed<esc>
character and a proper escape sequence.
By default, Vim uses:set timeout timeoutlen=1000
, so it delays on ambiguityof mappingsand key codes by 1 second. This is a sane value for mappings, butyou can define the key code timeout on its own which is the most commonworkaround for this entire issue:
settimeout" for mappingssettimeoutlen=1000" default valuesetttimeout" for key codessetttimeoutlen=10" unnoticeable small value
Under:h ttimeout
you find a small table showing the relationship betweenthese options.
If you're using tmux between Vim and your terminal emulator, also put this inyour~/.tmux.conf
:
set -sg escape-time 0
- A search pattern in a command (
/
,:substitute
, ...) changes the "last usedsearch pattern". (It's saved in the/
register; print it with:echo @/
). - A simple text change can be redone with
.
. (It's saved in the.
register;print it with:echo @.
).
Both things arenot the case, if you do them from a function, though! Thus youcan't easily highlight words from a function or redo the text changes made byit.
Help::h function-search-undo
NUL characters (\0
) in a file, are stored as newline (\n
) in memory anddisplayed in a buffer as^@
.
Seeman 7 ascii
and:h NL-used-for-Nul
for more information.
Vim script
,Vimscript
, andVimL
all refer to the same thing: Theprogramming language used for scripting Vim. Even though8.0.360changed all references fromVimL
toVim script
, which can now be consideredthe official term,VimL
is still widespread all over the internet.
No matter which term you use, everyone will understand it.
About
🎓 All things Vim!
Topics
Resources
License
Code of conduct
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.