
At least one Vim trick you didn't know about
- Transfer
- Tutorial
I have been working at Vim for eight years and constantly discovering something new. It is considered to be a virtue of Vim. As for me, this is a lack of openness: a bunch of hidden functions are hidden too deeply.
They talk about the beauty of modal editing and text objects, but it seems to me that the essence of Vim is not that. Vim is a patchwork quilt of subsystems clogged with additional tools. Only in normal editing mode more than a hundred keyboard shortcuts! This density of toolkits largely explains why Vim is so useful. If “show all tags for a keyword” is simple
In systems with a lack of openness, one has to rely on leadership. But for Vim there are not so many of them. There are articles for beginners, such as
This article is about some of the little tricks I use in Vim. None of them are disassembled in all details, so if something interested, I recommend digging additional information. They are also not related to each other. But it normal. In general, there are more than enough of them to really help almost everyone.
Very rude, Vim users fall into two categories. Purists appreciate the small size and ubiquity. As a rule, they minimize the configuration in case you have to work on an unfamiliar computer (for example, via ssh). On the other hand, rasshiryalschiki fill Vim plugins, features and homegrown comparisons in a vain attempt to pretend that they are using Emacs. If you take vimrc from them, then the guys will remain completely helpless.
As you probably guess, I am much closer to the expanders than purists. I divided the tricks into two sections depending on whether changes are required in the base Vim.
For modal commands, standard representations from the help are used, i.e.
Register for "expressions." Here you can enter any vimL expression and insert it, use with ctrl-R, etc. Thus, for example, a local timestamp is inserted by input .
Increases and decreases the next number in the line at the cursor location or to the right of it. Since it immediately goes to the number, the combination can be used from anywhere.
Opens the history of previous teams. You can work with it as with any Vim text, but the changes are not saved. However, you can run the modified command with
Same as
Moves to the next or previous location in the jumplist. Useful for quick checking and then backtracking. It is very nice to read help files.
See this post for a deeper insight into the use of macros.
Selects the previous visual item.
Goes to the other side of the visual block. Useful if you started one line too low or something like that. In block mode, it goes to the opposite angle diagonally, and use to move to the opposite angle horizontally
In visual mode, ctrl-A simply increments the first number on each line. On the other hand,
You probably know that in visual mode you can select characters (v), lines (V) and blocks (ctrl-V). But these three combinations can be used as motion operators for the corresponding fragment. For example, you have the following text: If you place the cursor on the top and press , it will delete all three lines, because it moves line by line. If you click instead , the movement becomes block-by-block and only the middle column with three letters is deleted . One use case is delete in search. Normal moves character by character. Therefore, I use for line-by-line movement with deletion. There is another way to do this:
Movement n lines below the match, or as many lines up if the value is negative. As a side effect, movement occurs line by line. Thus, if you want to delete the first line that matches
You enter ex-commands in command mode, for example, a command
Runs the command only on lines matching the regular expression. For example, you can enter
Tricks become more powerful with norm and some others.
Acts as if you ran {Vim} on each line of the range. For example, it
Copies a range to the current line. You can specify arbitrary values instead of a point, for example,
Copies a range to a register
will copy to
Runs a command in all windows. For example,
Works very well with
Listed here are tricks that require saving in settings or changing a Vim session. Hypothetically, they can be used in the "puritanical" mode, simply by entering commands, but some involve quite serious changes that contradict the spirit of purism.
Here is only the most unusual. Many people prescribe
If you are constantly configuring your vimrc, please yourself and add a separate command for this:
I have all the settings, key bindings and functions stored in a single vimrc file. Splitting into multiple files makes searching difficult.
Most of the settings are not really any “tricks”. It's best to look at vim-sensible : almost all the settings from there will suit your vimrc.
Do not redraw the screen in the middle of a macro (to improve performance).
With these two settings, a search without capital letters becomes case insensitive, and a search with capital letters is case sensitive.
Saving actions, even if you close and open Vim, so that undo actions are always available. Very handy in combination with the undotree plugin.
Side column with collapsed blocks. The more
Only for Neovim. The setting
Determines what to display in the panel at the bottom of each window. Here formatting is much more complicated and finicky than in other settings, so you have to spend time explaining it. There are some simple tricks. First, look at the default Vim status bar:
Here it is easiest to replace
And replace the percentage of the file with the number of words in the document.
Or install
it will always show a date on top.
I have a lot of bindings.
A lot of convenient keys in Vim are stupidly assigned by default. For example, saving a keystroke
Without slowing down the transition to ex-mode, repeats the last macro.
It makes the key
nnoremap
Go to the window below. Appropriate destination for
nnoremap
Run the current line as if it is a command. Experiments are often more convenient than
The command activates the assignment of keys for this buffer only. It really works conveniently with auto-commands as a temporary key combination or when defining assignments through a function. Buffer assignments take precedence over global ones, that is, you can override the general command more useful in a specific situation. The command checks and uses the return value as the final remapping of the keys. One simple use case is binding based on conditions. I have these: What makes and move along the line until a number is found, and after that the key is canceled. Therefore, I can navigate long paragraphs of prose without violating combinations such as
The argument
Thanks to
Auto commands are great for configuration. Usually you configure them like this:
Then, if any of the {events} events occurs in the {file regex} file, the {command} command will fire. Events are listed
then vim will disable relativenumber for insert mode only.
The command applies the auto command only to the current buffer. Sometimes I use this to add short-term event handlers to a specific file.
Only in Markdown files is the TODO line highlighted, and code
Auto-teams allow you to do much more complex things. For example,
Most people know about popular plugins such as
In most text editors, undo actions occur linearly. If you make a change to A, undo it, and then make a change to B, then A is lost forever. However, Vim stores the entire tree of undone actions. The command
But this format is not very clear. It is much better to see the actual tree. This is exactly what it does
The plugin provides commands for exchanging arguments, so you can replace it
Connects a higher-level API to the neo / vim embedded terminal. For example,
Many topics are not covered in this article because they are too technical or need to be explained in detail, like function writing or the syntax system. And I don’t know much. I would like to study the following topics in more detail:
I sometimes use tools with these windows, but I don’t know how to manipulate them. I would like to add quickfix errors to my TLA + plugin . I also like the idea of putting supporting information and callback commands in the preview window. This opens up some possibilities that are difficult to reproduce in the IDE.
Neovim offers an advanced API for integrating Vim with external programs. Your Python script can send commands to the Neovim instance, and you can control the editor through the server, for example. I saw some cool conceptual demos where autocomplete happens based on information in a browser. It seems to be very cool!
Never created such.
So, this was a brief overview of some of the implicit functions of Vim. Hope you found out something useful!
They talk about the beauty of modal editing and text objects, but it seems to me that the essence of Vim is not that. Vim is a patchwork quilt of subsystems clogged with additional tools. Only in normal editing mode more than a hundred keyboard shortcuts! This density of toolkits largely explains why Vim is so useful. If “show all tags for a keyword” is simple
g]
, then this command will be used much more often.In systems with a lack of openness, one has to rely on leadership. But for Vim there are not so many of them. There are articles for beginners, such as
ciw
(not to be confused with the CIA, the CIA manual for Vim ) and the like. And there are articles of experts who are immersed in subsystems. But no one really talks about these special tricks that make you exclaim: damn it, as I needed it for the past six years! This article is about some of the little tricks I use in Vim. None of them are disassembled in all details, so if something interested, I recommend digging additional information. They are also not related to each other. But it normal. In general, there are more than enough of them to really help almost everyone.
Article structure
Very rude, Vim users fall into two categories. Purists appreciate the small size and ubiquity. As a rule, they minimize the configuration in case you have to work on an unfamiliar computer (for example, via ssh). On the other hand, rasshiryalschiki fill Vim plugins, features and homegrown comparisons in a vain attempt to pretend that they are using Emacs. If you take vimrc from them, then the guys will remain completely helpless.
As you probably guess, I am much closer to the expanders than purists. I divided the tricks into two sections depending on whether changes are required in the base Vim.
Purists
For modal commands, standard representations from the help are used, i.e.
means pressing the Enter key. When you need help :h
for a specific line, for example :h E676
, the line will be in parentheses.Various commands in normal mode
": and @:
":
is a register holding the last command executed. You can type ":p
to print it to the clipboard. @:
repeats the last command."=
Register for "expressions." Here you can enter any vimL expression and insert it, use with ctrl-R, etc. Thus, for example, a local timestamp is inserted by input .
"=strftime("%c")p
mA, 'A
m{letter}
sets the mark at the cursor position. Then '{letter}
proceed to this line. For lowercase letters, it acts on the buffer, so it is suitable for navigation. For capital letters, it acts globally: even if you are in another file, it 'A
will go to the file with the label А
. You can see all your tags with the command :marks:
.ctrl-A and ctrl-X
Increases and decreases the next number in the line at the cursor location or to the right of it. Since it immediately goes to the number, the combination can be used from anywhere.
10c-A
much easier than wwwwwciw20
.q:
Opens the history of previous teams. You can work with it as with any Vim text, but the changes are not saved. However, you can run the modified command with
. This allows you to very quickly change and restart commands or look for old ones for reuse.q /, q?
Same as
q:
search.ctrl-I, ctrl-O
Moves to the next or previous location in the jumplist. Useful for quick checking and then backtracking. It is very nice to read help files.
Macros
See this post for a deeper insight into the use of macros.
Visual mode
gv
Selects the previous visual item.
v_o
Goes to the other side of the visual block. Useful if you started one line too low or something like that. In block mode, it goes to the opposite angle diagonally, and use to move to the opposite angle horizontally
v_O
.g ctrl-A / ctrl-X
In visual mode, ctrl-A simply increments the first number on each line. On the other hand,
g ctrl-A
with each line it will increase the increase by one. This is much easier to explain in the table:selected | ctrl-A | g ctrl-A | 2 g ctrl-A |
---|---|---|---|
a 0 b 0 c d 0 | a 1 b 1 c d 1 | a 1 b 2 c d 3 | a 2 b 4 c d 6 |
Operators: v, V, cv (: h o_v)
You probably know that in visual mode you can select characters (v), lines (V) and blocks (ctrl-V). But these three combinations can be used as motion operators for the corresponding fragment. For example, you have the following text: If you place the cursor on the top and press , it will delete all three lines, because it moves line by line. If you click instead , the movement becomes block-by-block and only the middle column with three letters is deleted . One use case is delete in search. Normal moves character by character. Therefore, I use for line-by-line movement with deletion. There is another way to do this:
abc
abc
abc
b
d2j
j
d2j
b
d/
dV/
/ regex / {n}
Movement n lines below the match, or as many lines up if the value is negative. As a side effect, movement occurs line by line. Thus, if you want to delete the first line that matches
regex
, you can enter d/regex//0
.Ex-teams
You enter ex-commands in command mode, for example, a command
:s
. In addition to replacement, there are many other useful commands. All of these examples require a range such as %
.: g / regex / ex
Runs the command only on lines matching the regular expression. For example, you can enter
g/regex/d
to delete all lines matching regex. The command v
is similar to g
, but works on all lines that do not match the regular expression. Tricks become more powerful with norm and some others.
: norm {Vim}
Acts as if you ran {Vim} on each line of the range. For example, it
g/regex/norm f dw
deletes the first word after the first space in each line that matches the regex regular expression. This is often much simpler than a macro. norm
obeys all your comparisons. For example, if you assigned keys jk
to
in insert mode, then norm I jk$diw
add a space to the beginning of the line, leave insert mode , and then delete the last word in the line. I really like this functionality, but if you prefer not to use your mappings, you can then apply norm!
.: co.
Copies a range to the current line. You can specify arbitrary values instead of a point, for example,
+3
or 'a. mv
to move.: y {reg}
Copies a range to a register
{reg}
. If you {reg}
are in upper case, then it is added to an existing case. i.e., such a command let @a = '' | %g/regex/y A
will copy to
a
all lines corresponding regex
to the entire file. This helps to extract the broken text from the file and copy it to the system clipboard (using let @+ = @a
).: windo {ex}
Runs a command in all windows. For example,
:windo $
scrolls all the windows down. There is bufdo
, cdo
, tabdo
and others. Works very well with
g
and s
. To replace all the combinations AA
on BB
a preliminary view replacements, you can enter vimgrep AA
by downloading the coincidences in all quickfix, and then cdo s/AA/BB/cge
to search / replace all matches.Vim for Extenders
Listed here are tricks that require saving in settings or changing a Vim session. Hypothetically, they can be used in the "puritanical" mode, simply by entering commands, but some involve quite serious changes that contradict the spirit of purism.
Here is only the most unusual. Many people prescribe
H
for a cap ^
, so such things are not worth mentioning. It also makes no sense to talk about vim-sensible
or vim-surround
, but only about more exotic plugins. If you are constantly configuring your vimrc, please yourself and add a separate command for this:
command! Vimrc :vs $MYVIMRC
Settings
I have all the settings, key bindings and functions stored in a single vimrc file. Splitting into multiple files makes searching difficult.
Most of the settings are not really any “tricks”. It's best to look at vim-sensible : almost all the settings from there will suit your vimrc.
set lazyredraw
Do not redraw the screen in the middle of a macro (to improve performance).
set smartcase / ignorecase
With these two settings, a search without capital letters becomes case insensitive, and a search with capital letters is case sensitive.
set undofile
Saving actions, even if you close and open Vim, so that undo actions are always available. Very handy in combination with the undotree plugin.
set foldcolumn = {n}
Side column with collapsed blocks. The more
n
, the more collapsed blocks are shown in the column, and for the rest the number is indicated.set suffixesadd = {str}
gf
usually means "go to the file under the cursor", but requires a file extension in the line. suffixesadd
Adds the specified extension. If set suffixesadd=.md
, then the command gf
on the line 'foo' will look for files foo
and foo.md
.set inccommand = nosplit
Only for Neovim. The setting
incommand
shows in real time what changes the team will make. Now only supported s
, but even this is incredibly useful. If you enter :s/regex
, all matches are highlighted. If you then add it /change
, it will show all the replacements. Works with all regex properties, including backlinks and groups.set statusline (: h statusline)
Determines what to display in the panel at the bottom of each window. Here formatting is much more complicated and finicky than in other settings, so you have to spend time explaining it. There are some simple tricks. First, look at the default Vim status bar:
:set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
Here it is easiest to replace
%P
(percentage of file over cursor). The status bar format is the value after the percent sign in braces. Therefore, for Markdown files, you can write this: :set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %{wordcount()[\"words\"]}
And replace the percentage of the file with the number of words in the document.
Or install
tabline
. If you do not use tabs, then this line can be made a “global status line”. For example, set tabline=%{strftime('%c')}
it will always show a date on top.
Key Bindings
I have a lot of bindings.
A lot of convenient keys in Vim are stupidly assigned by default. For example, saving a keystroke
s
is a synonym cl
(saving one keystroke), but it U
is the same as saving the u
undo as a new change, which is functionally useless. Q
identical gQ
and in any case is a colossal trap. Z
used only for ZZ
and ZQ
. Hell, even the manual recommends Vim reassign keys _
and ,
on any function, because "you will probably never do not use them." I would prefer not to save one click, but to add completely new functions to the keyboard. Here are some of my bindings:nnoremap Q @@
Without slowing down the transition to ex-mode, repeats the last macro.
nnoremap s "_d
It makes the key
s
(with the appropriate assignments for ss
and S
) work like d, only without saving the deleted text in the register. Useful in order not to clog up the register.nnoremap j
Go to the window below. Appropriate destination for
h
, k
, l
. Working with windows is much easier.nnoremap e: exe getline (line ('.'))
Run the current line as if it is a command. Experiments are often more convenient than
q:
.Special arguments (: h map-arguments)
The command activates the assignment of keys for this buffer only. It really works conveniently with auto-commands as a temporary key combination or when defining assignments through a function. Buffer assignments take precedence over global ones, that is, you can override the general command more useful in a specific situation. The command checks and uses the return value as the final remapping of the keys. One simple use case is binding based on conditions. I have these: What makes and move along the line until a number is found, and after that the key is canceled. Therefore, I can navigate long paragraphs of prose without violating combinations such as
map lhs rhs
map {lhs} {expr}
{expr}
nnoremap k (v:count == 0 ? 'gk' : 'k')
nnoremap j (v:count == 0 ? 'gj' : 'j')
j
k
10j
. The argument
helps if any bindings trigger ex-commands.inoremaps
Thanks to
inoremap
binding, they work in insert mode. There they begin to work, therefore they inoremap ;a aaaa
will introduce 'aaaa' instead of '; a'. If you want to do something normally, use
. For example, if we have
it , it will set a label at this point .
I like to specify to use semicolons as a key for reassignments, because in normal texts there is almost always a space or a new line after the semicolon.inoremap ;1 ma
;1
'a
autocmd
Auto commands are great for configuration. Usually you configure them like this:
augroup {name}
autocmd! " Prevents duplicate autocommands
au {events} {file regex} {command}
augroup END
Then, if any of the {events} events occurs in the {file regex} file, the {command} command will fire. Events are listed
:h event
. For example, if you writeaugroup every
autocmd!
au InsertEnter * set norelativenumber
au InsertLeave * set relativenumber
augroup END
then vim will disable relativenumber for insert mode only.
The command applies the auto command only to the current buffer. Sometimes I use this to add short-term event handlers to a specific file.
au {event} {ex}
BufNewFile, BufRead
BufnewFile
it starts when a new file is created, BufRead
- when the buffer is first opened. They are usually used to add parameters and remaps to specific file types. I have one such:augroup md
autocmd!
au BufNewFile,BufRead *.md syntax keyword todo TODO
au BufNewFile,BufRead *.md inoremap ;` ``````
augroup END
Only in Markdown files is the TODO line highlighted, and code
;`
notation adds characters in insert mode. Auto-teams allow you to do much more complex things. For example,
au
to BufWriteCmd
override the default retention, allowing to implement custom logic. This goes beyond “tricks” and goes into the realm of “dark magic”.Plugins
Most people know about popular plugins such as
vim-surround
and NERDtree
. Here is a list of some little known ones that I find very useful.Undotree
In most text editors, undo actions occur linearly. If you make a change to A, undo it, and then make a change to B, then A is lost forever. However, Vim stores the entire tree of undone actions. The command
u
rolls back the action in the current tree branch, and g
goes to the previous chronological version. You can view the list of canceled actions by the team :undolist
. But this format is not very clear. It is much better to see the actual tree. This is exactly what it does
Undotree
: it lays out a good ASCII representation of the tree of canceled actions with convenient navigation.vim.swap
The plugin provides commands for exchanging arguments, so you can replace it
(a, f(b, c))
with a couple of keystrokes (f(b, c), a)
. I regularly have to make such edits, so this is a major improvement in the quality of life.Neoterm
Connects a higher-level API to the neo / vim embedded terminal. For example,
:T {text}
sends {text} to the console. Good for creating an interactive environment."TODO {{{
Many topics are not covered in this article because they are too technical or need to be explained in detail, like function writing or the syntax system. And I don’t know much. I would like to study the following topics in more detail:
Preview, Quickfix, and List windows
I sometimes use tools with these windows, but I don’t know how to manipulate them. I would like to add quickfix errors to my TLA + plugin . I also like the idea of putting supporting information and callback commands in the preview window. This opens up some possibilities that are difficult to reproduce in the IDE.
Neovim API
Neovim offers an advanced API for integrating Vim with external programs. Your Python script can send commands to the Neovim instance, and you can control the editor through the server, for example. I saw some cool conceptual demos where autocomplete happens based on information in a browser. It seems to be very cool!
Text objects
Never created such.
So, this was a brief overview of some of the implicit functions of Vim. Hope you found out something useful!