If you forgot to sudo vi, you've already edited the file, saving the file as root without first saving it as your own and then having to move it:
<ESC>:w !sudo tee %
Pipes the content of the file to a tee process as root and lets tee save it under the current file name. Vim will tell you the file has changed on disk and ask if it should reload it afterwards.
Make sure you are 100% confident that you know the proper syntax for this when you use it.
I once blanked by mistake an important file, lucky for me I had a backup.
Generally a good idea, before you sudo anything. That's one of the reasons to prefer this approach to `sudo vim`, actually - that's essentially "sudo of anything vim does", and that's a lot of very different things just a couple keystrokes away.
Not really a trick of Vim itself, but when using Vim from the terminal I find ctrl-z very useful to background Vim, type in a few shell commands for git or whatever and then use "fg" to hop back into Vim.
Ctrl-Z only gets converted to SIGTSTP if the terminal has ISIG set. For example, try `stty -isig; sleep 5` and try to suspend or interrupt the sleep command.
Many of the things here, as of writing, are quite elementary Vim tips. A lesser known trick that I learnt quite recently and have found very useful is `gn`, which visually selects the next search hit (similarly `gN` for the previous hit). That's not so useful in itself, but it can be combined with an operation, such as `c` or `y`, etc., which can then be repeated using the `.`.
Macros, Macros, Macros. These are a game changer when editing large files. Use the `q` key and followed by any letter you like, I default to `a`. Perform some action, like deleting a line, appending to the start of a line, or searching for a word then deleting it. Press `esc`, then type in the number of times you want to repeat the action, followed by `@` and the letter you chose. I.E `10@a` and it will perform that action 10 times.
Also fun: macros can call themselves. So if you want to repeat something across a whole file, it's sometimes easiest to write an infinitely recursive macro and let it error when it bumps up against the bottom of the file.
Vim can be great for quickly doing tedious text transformations. Far easier to get right than doing it the 'proper way' with a script in Python/Perl/whatever.
To do something like scan through a JSON or XML document and split a 'name' field/tag into 'firstName'/'lastName', Vim is the tool I'd reach for.
I think of it as 'cursor-oriented programming', but what I do with it isn't really programming, it's generally of the pattern of 1. Find start of pattern 2. Transform pattern 3. GOTO 1
Or at worst, the decorate/sort/undecorate pattern.
A useful thing to know when using macros is that the letter you press after `q` is just the register in which Vim stores the macro. Registers are also used when copying and pasting. As such, if you want to edit a macro, you can just paste it into a new buffer (e.g., `"ap` for register `a`), edit it as you wish, then copy it back into that register (`:%y a`). You can even use this method to write macros from scratch, rather than recording them first.
`Ctrl + v` to visually select one character at a time (instead of say `Shift + v` that selects a whole line) and then use the movement keys to select a block of characters horizontally as well as vertically.
Imagine several well indented HTML <li class="something"> elements, you could for instance delete/modify all the class attributes on all lines visually in one go (to insert text use `Shift + i`, type, then Esc).
You want to change all the instances of "wrong" to "right". So you put the cursor on the first "w", then `Ctrl-V` to enter blockwise visual mode, then `e2j` to select the "wrong" words, then `c` to remove all of them and enter insert mode to type a replacement. The replacement text is then applied to each line separately. Full series of keystrokes (starting with the cursor on the "w" in the first line) if you want to follow along:
Quick renaming of variables:
what to type"explanation
gd" go to definition of variable
:%s/" beginning of a replace...
Ctrl-r /" inserts the last word searched into the command, so what "gd" found
/newname/gc" finish the replace command, g=global replace, c=confirm each replace
Save a character going to a line:
instead of using :42<enter> to go to line 42, can use 42G
Auto-indent: =
Go to last file: Ctrl-^
Abbreviations:
put this in your ~/.vimrc
iab cmain int main() {
\<CR> return 0;
\<CR>}
Insert the contents of a file:
:r <filename>
I like to have a ~/gitmessage.txt which has a template I like, then when I do git commit all I have to do is:
:r ~/gitmessage.txt
Vim + Ctags:
Ctags link usages and definitions so you can navigate through code like in an IDE without the bloat of an IDE. Works best with C, but works pretty well with any language with C-like syntax (and more).
Goto tag (definition) of what's under cursor: Ctrl-]
Let’s say you have a Makefile based project and the dependencies aren’t as complete as they ought to be. With your cursor on this line in the Makefile:
SOURCES = \
You can say
:r !ls src/*.c
That will put the complete list of extant C source files into the file at that position, complete with the “src/“ path prefix. Then to format the list properly for “make” syntax, use Shift-V to select the list, hit the right angle bracket (“>”) once to indent it a level, then say:
:s/$/ \/
This trick of replacing the start (“^”) or end (“$”) of a line is very often helpful. Here I’ve used it to ask Vim to put a space and backslash after every line to allow the SOURCES variable definition to continue from one line to the next.
(This will look like “:’<,’>s...” in your editor, with the bit between the colon and s being inserted by Vim; it means “front the start of the selection to the end.”)
Remove the final backslash and it’s done.
The advantage of working this way is that you aren’t manually transcribing things the computer already knows and can report on command.
The possibilities here are vast. For instance, if your C source files are buried under subdirectories of `src`, say this instead:
`gq` will work with a text object, so you don't need to go to the trouble of visually selecting a block. Say, for example, you have a mis-wrapped paragraph in a text file, providing your cursor is anywhere within that paragraph, `gqip` will rewrap the whole paragraph.
The nice thing about using `=` instead of `gq` is that you can “set equalprg” to something smarter than the internal Vim formatter, such as `fmt` or `par`:
These formatters will do nice things like choose line breaks intelligently to reduce the raggedness of the right edge. I just tested `gqip` on a paragraph in a Markdown document here that was formatted with `fmt`: the `fmt` output put breaks in such that all but the last line was within one character of equal, whereas `gqip` had line lengths varying as much as 5 characters on a 72 character line length.
A quicker alternative to Shift-V, arrows, then `=` to reformat a paragraph with `fmt` is this:
:map <F2> !}fmt -w72<CR>
That works anywhere inside the paragraph like with your `gqip`, but it uses the smarter `fmt` paragraph formatter.
Select your keystroke to taste. I chose F2 so long ago that I forget why that was a good idea at the time.
* ctrl+z; kill %1
* Open a new terminal and ignore the one with vim running.
* ZZ
* Pull the power cord, erasing any sign of it running.
* ESC :q!
* ESC :wq
* ESC :exit
* ESC :quit
Mine is playing with errorformat (personal blogspam: http://flukus.github.io/vim-errorformat-demystified.html) and combining this with :cf (read errors from file) or :cb (read errors from buffer) to parse a file/buffer into the quicklist. Great for dealing with log files.
Not sure if most people don't know it, but this is useful (in Windows vim):
In Unix vi(m), you use Ctrl-V to quote a special character to actually insert it into the text (or into a last line mode command; see example below).
So in Unix if you want to insert a carriage return (Ctrl-M) into a file or a command, you do Ctrl-V Ctrl-M. That does not work in Windows with gVim because Ctrl-V means paste from clipboard. So you use Ctrl-Q instead of Ctrl-V, like in this example, where you want to use vim to remove all the carriage returns (CRs) from the file (say if you were going to use the file on Unix later [1]):
:%s/Ctrl-QEnter//g
where instead of typing the letters Enter, you hit the Enter key.
The %s means do the command for all lines in the file (% for all lines, s for substitute), the command is search-and-replace (old pattern with new pattern, here Ctrl-M with nothing), and the g(lobal) at the end means do it for all occurrences in the line (otherwise it does it only for the first occurrence on the line).
This will show on your screen as:
:%s/^M//g (the Ctrl-Q does not show on screen)
where the ^M represents the CR or Enter.
The same command on Unix would be:
:%s/Ctrl-VEnter//g
This will show on your screen as:
:%s/^M//g (the Ctrl-V does not show on screen)
[1] Of course there are other ways to remove the CRs from the file, like a) using a dos2unix utility, a) many modern editors will do it for you (via a setting or a menu option), c) push it to Git from Windows and then pull it from Unix (with appropriate Git settings for line-ending handling), etc.
I forgot to mention that on for both the Unix and Windows versions of that above command, you have to hit Enter at the end of it (after the g), because last line mode (or ex mode) commands require that, unlike regular vim commands which run immediately, without needing an Enter.
Better keyboard scrolling with this simple mapping:
nmap <C-j> 3j3<C-e>
nmap <C-k> 3k3<C-y>
This maps the <C-j> and <C-k> keys to a scroll action similar to mouse scrolling: the cursors stays in a fixed position while the whole screen moves up or down 3 rows.
:diffoff is another great thing to know, particularly when using vimdiff to merge things (e.g. in git). I find that turning diffing off and on for various windows can more quickly give a clear picture of what changed where.
If you like these, it's worth skimming `:help index` and `:help option-summary` occasionally. You're likely to find at least one interesting new keybinding or setting.
I think that's probably more to people not wanting to learn how to do it right. For the longest time, I only taught myself just enough vim to be able to use it for basic editing, because it's convenient and it's better than nano.
One of my favorite Vim tricks (which also works in vi) is the general technique of piping a specified range of text through a command (a Unix-style filter that reads from standard input and writes to standard output), with the output of that command then replacing that range of text.
The text can be anything from a single line, some arbitrary range of lines (defined via vim marks like a and b or other letters, some paragraphs (see example below), to the entire file - and the filter command can be anything at all, too. The Cartesian product of those two things makes it a very powerful technique.
An example is this key mapping of the character v to a command that format paragraphs of text using the fmt command [1]:
map v !}fmt -w 64<CR>
This says: map the letter v to the command following it (after the space), which is:
!}fmt -w 64<CR>
which runs/pipes (!) the current paragraph (when at top of a para, the cursor movement } defines a para) through the fmt -w 64 command, which formats its input text into lines of not more than 64 characters each.
(I just used v because it was one of the characters that Vim does not already assign a command to - any other available character will work.)
I have the mapping in my _vimrc on Windows and .vimrc on Unix.
With that mapping, I can reformat any paragraph (where paragraphs in vim are defined by a blank line either above and below them or both), just by going to the top of the paragraph (with { ) and typing v (no Enter needed).
For example, if I have this (single) line in a file in vim:
the quick brown fox jumped the quick brown fox jumped the quick brown fox jumped the quick brown fox jumped the quick brown fox jumped
and I press v when at the start of that line, it gets reformatted into this para:
the quick brown fox jumped the quick
brown fox jumped the quick brown fox
jumped the quick brown fox jumped the
quick brown fox jumped
I typically use this technique when writing text content (non-programming content, such as documentation, tech articles, blog posts, etc.) or sometimes even for block comments of text in programs.
You can also create a different version of that formatting command to filter the entire text file through fmt in one shot (that would be "!Gfmt -w 64" when at top of file, where G moves to the last line), but I tend not to use that approach much, because it sometimes messes up some paragraphs which should not be reformatted. So I do it a para at a time.
If you use the sort command instead of fmt, that will sort the range of lines you select, and the sorted lines replace the original lines. This is of course useful in text files and (text format) data files, but is also sometimes useful in source code, e.g. to sort lines of import statements (say in Python or Go - although Go has commands for that), ranges of variable declarations into alphabetical order, array literals, etc.).
[1] (Fmt is a Unix command, but you can probably get it in many of the Unix subsystems that run on Windows too, like Cygwin, UWin, Windows Subsystem for Linux too).
c
The command that you run the selected text through, can also be a Unix or Windows pipeline, which makes the technique even more powerful.
<ESC>:w !sudo tee %
Pipes the content of the file to a tee process as root and lets tee save it under the current file name. Vim will tell you the file has changed on disk and ask if it should reload it afterwards.