Vim expert

Working in the Linux terminal every day, for me it is a no-brainer to use vi, more specifically vim. It’s installed by default on every Linux system (vi is anyway) and it is very, very powerful. The only thing that could hold you back is, as it is jokingly called, the vi ‘learning wall’ (in contrast to ‘learning curve’).

Of course, there are some great Integrated Developer Environments (IDEs), Visual Studio Code by far being the most popular one now, that can make editing a lot smoother. For normal, day to day operations and development this is the way to go, but in case you find yourself often in the terminal, especially remote, vim is undeniably an important tool in your toolbox.
Note: vim is really a lot different than vi and by default not installed on many Enterprise Linux (EL) systems. Using EL 8, install it with:

$ sudo dnf install epel-release
$ sudo dnf install vim
Modes

First the basics in a nutshell. In vim you can use 3 modes:

  1. Command mode. You start out in this mode and has many functions like super fast copy and pasting or deleting of text. Return to it from the other modes with the ESC key
  2. Insert mode. The mode to insert text. You can enter this mode in different ways, most often via the i, a, I or Akeys in command mode
  3. Last line mode. When you press the : key from command mode, you’ll end up in last line mode. As with the command mode you can use this in many ways. Simply quitting and saving are mostly used here

Basics like navigating through the file when you do not have arrow keys (h, j, k and l), inserting (i) and adding (a) text and quitting (:q or :q!) or saving (:w or :x) are outside the scope of this post.

General
Here are things I’m using every day, so it should be a very practical post. In no order. An error (in a log, PHP error, whatever) often comes with a line number where the error originates. To open the file and immediately jump to the correct line (in this example line number 114):

$ vim +114 /path/to/file

This is the same with the read only variant of vim: view. I use view when I’m certain I’m not going to or don’t want to edit the file:

$ view +114 /path/to/file

Let’s say I’m in view mode and decide I DO want to edit the line, for instance comment the current line out, I can do so by adding or inserting like normal (a or i). It will give a warning, but that’s OK. When you’re done you can write and exit with the ! to write the file anyway:

:x!

This only works when you have enough privileges to the file to begin with. When you’re in a file and you have to edit it with elevated permissions, you can also do this from the last line mode:

:x! sudo tee %

Both can also be run with w, where you only write the file instead of writing and quiting. And not unimportantly, the user you are attempting this with needs sudo privileges. When you’re in a file, you can set the line numbers. This can also be set by default in your .vimrc file, but that’s probably for a later post. Display line numbers in your file:

:set nu

Disable them again:

:set nonu

Also, a bit basic, but navigation wise I use these shortcuts daily, in command mode:

  • G jump to the end of the file
  • gg to jump to the first line of the file
  • :89 jump to line 89
  • {} jump paragraphs up and down
  • $ jump to the end of the line
  • ^ jump to the start of the line
Deleting
Deleting stuff! I delete a lot of stuff apparently because I think I know and use every delete option available. Single characters, typos, an extra letter for example, are simply deleted in command mode with the x. In this way you don’t even have to enter insert mode. I often also must replace just a single character: move your cursor to the character to be replaced, type r and then the new character. Power deleting a bunch of stuff at the same time is just as easy from the command mode. For the current word:

dw

Next five words:

5dw

Current line:

dd

Next 8 lines:

8dd

Easy as pie (or vi, if you want). Also know that deleting the next 8 lines for example, places them in your paste buffer. Comes in handy when you want to move a couple of lines to another location. It’s just for the very last thing you deleted though, so don’t delete an extra blank line afterwards for instance. Deleting the rest of the line (from my cursor):

D

And deleting the rest of my file (from my cursor):

dG
Copying
Let’s do some copying around in the file. For this we’re using the y for yank. As with deleting words, you can now predict the commands for yanking. Yanking the current word:

yw

Next 10 words:

10yw

Current line:

yy

Next 6 lines:

6yy

When the text is in your buffer, you can paste it with p after the cursor and P before the cursor.
Miscellaneous

I briefly mentioned inserting text with i (insert), I (insert at start of the line), a (add) and A (add at the end of the line). What I’m probably using more often though to enter text is o (insert a new line after my cursor) and O (insert a new line before my cursor). Just so that you know.

Undoing when you made a mess is a push of a button in command mode: just the letter u. When you made several typos on the same line undo them all with U. Redoing is also possible with the dot (.). When you want to be sure not to save anything, quite the file without saving with :q!

Searching
Searching in large files is very valuable. First understand that every search is case sensitive by default. You can make your searches case insensitive by this last line command:

:set ic

Revert it to the default case sensitive:

:set noic

Now start your search by pressing the / key and entering the text to search for, followed by an enter to search. To find the next occurrence of your search term press n and N for the previous. To reverse search, begin your search with a ?instead of a /. Not too complicated huh. Search and replacing, essential for a lot of files I’m working on, needs just a little bit more attention. From last line mode:

:s/server01/server02/g

This will replace every occurrence of server01 in the current line to server02. You can also do the entire file at once:

:%s/server01/server02/g

Add a c at the end to confirm every occurrence. These two I use a lot, but there are more powerful commands to be used. I believe this page has some more good stuff.
Marking
There can be a lot of jumping around in vim. There are many shortcuts to jump a file and I think marks are quite unique. First mark a line you want to return to later:

ma

This sets a mark named a at the current position. To later return to this exact position, use:

`a

To return to just the line you set the position, use:

'a

You can use any letter of the alphabet to set a mark. There is a lot more to be done with marks, but I only use it for this purpose. Pro tip when having more than 1 file open: leave a mark with a capital letter and you can jump between files. Marks are persistent, even after closing a file. Leave a mark with a capital letter, save and close, open another file, jump to the capital mark: this opens the first file at the correct mark, in a different buffer (more on buffers later).
See all marks:

:marks

Delete them:

:delm! | delm A-Z0-9
Last line magic
In the last line mode, you can do a lot more than saving and quitting your file. First here’s a basic but often overlooked trick before an important edit to a file:

:w ~/otherfile.txt

This saves the current state of the file, let’s say it is named myfile.txt, to a file otherfile.txt in the home directory. You’re still working in myfile.txt though. So, any edits after this save, are just as normal edited in the original myfile.txt. As easy you can write out files, you can also read them in. Say you want to insert a file in your current working file, at your current position:

:r ~/Documents/important.txt

You can use tab completion as well. Let’s say that you can’t find your document though. Let’s find it, right from within vim with the ! key that marks a command:

:! find ~ -name important.txt 2> /dev/null

This will jump out of vim and eventually give you the output of your command (I’m rerouting errors to /dev/null to avoid permission errors cluttering the output). Combining the two is also easy. Let’s say you for some reason want to read in the output of a command to your current file:

:r ! ls -al

Will insert the output of ls -al to your current position in your document.
Buffers

It seems there are a couple of ways you can open files simultaneously, edit them, save them, close them, switch between them, etc. The two main ways in vim:

  1. Using tabs
  2. Using buffers
Although tabs feel more intuitive, buffers are the vim mentality of opening and editing multiple files at once. Open multiple files at once:

$ vim myfile.txt otherfile.txt justanother.txt

Three files are open, but you see only one. To see them all, let’s view all files in their own window:

:ball

This opens the files in the default horizontal split. My terminal is almost always full screen and I like the vertical mode more:

:vert ball

Now you don’t have to show all these files at once with the above commands… even when you see just one, the files are open, and you can see them with:

:ls

And switch between them with:

:bn

:bp

Which is for buffer next and buffer previous. To switch to a specific buffer number, which you’ve discovered with :ls, you can use:

:2b

Which jumps to buffer number 2. You can also use the filename directly and tab completion:

:b openfileinbuffer.txt

When you need full screen and have many files open at once, the above will work. With only a couple of files, I would like to see all my files I’m working on:

:vert ball

With all buffers open, switching between them is easy:

CTRL WW
OK, three files open. Let’s says we want to open a completely new one, in a new buffer and window. By default, this can be done with:

:new

But since I like vertical split more, I’m using:

:vnew

Give your new file a name immediately:

:vnew newfilefromvim.txt

Or edit an existing file:

:e ~/existingfile.txt

What the above does though and is a bit annoying, is it opens the file in the same window. The other file is still there, in its own buffer, but you must open it again to see it. Therefore, I like:

:vs ~/existingfile.txt

better, as it edits the existing file and opens it in its own, vertical window. There is also the build in vim file explorer, which you can open with a simple:

:Ex

This does, again, use the current window though which I find, again, a bit annoying. A

:Vex

solves this. Your view can get cluttered fast though, so I myself don’t like it that much. Close the file explorer with:

:close

All these files are in buffers, remember. Now we want to close one of these files. Jump to it with CTRL WW and quit it with :q or close the windows with :close. Have a look at your buffers like before with :ls. As you can see, the quitted file or closed window is still in your buffer. When you are working with buffers and really want to close one, user buffer wipe:

:bw

You might not care, but I like a clean workspace. So i’m guessing we’re having about 4 files open at this point? These might be files belonging to a particular project that needs working on tomorrow as well. You can easily save your current session with:

:mksession! ~/my.ses

Save and quit all files with:

:xa

And tomorrow start where you left off with:

$ vim -S ~/my.ses

Awesome and easy! The a in the :xa command stands for ‘save all buffers’. So, you can also quit all files with:

:qa!
Closing remarks

To be honest I don’t use buffers a lot anymore but doing a comprehensive post on vim without at least explaining a couple of the possibilities would feel incomplete. I think it emphasizes the many possibilities you have with vim.

There is a cool saying I’ve read a while ago, that I unfortunately can’t find the source for, but always sticked with me. It is something along the lines of, ‘When you’re logging in on a server with SSH, you’re doing it wrong’. Meaning that you should never login via SSH and only infrastructure and configuration management tools should touch your servers. Although this is a noble goal and absolutely something we should strive for, in practice I see that a lot of people end up in the terminal anyway. For instance, for troubleshooting. This post was for these people 😉

Next time I want to briefly discuss a terminal tool I use daily: screen. After that we will me moving on to some cool technologies like containers, Terraform, Ansible, etc.

Stuff i forgot

There is so much to tell about vim that I had to make choices and had to end the post somewhere. There are a couple of points I want to briefly mention though:

And there are more tools and games out there. Have fun!