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’).
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:
- 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
- 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
- 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
$ 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 filegg
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
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
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
: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
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
: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:
- Using tabs
- Using buffers
$ 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
: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:
- Vim plugins to extend functionality
- Vim genius to train your vims muscle memory
- Vim adventure to have fun and train your vim skills
And there are more tools and games out there. Have fun!