Vim tips, tricks and useful .vimrc modifications (Part 1).

JasKinasis

Super Moderator
Staff member
Gold Supporter
Joined
Apr 25, 2017
Messages
1,881
Reaction score
2,768
Credits
16,359
Introduction
Originally I planned to use this thread to share some of my favourite .vimrc modifications for Vim.
But as I started writing and planning - the whole article just got bigger and bigger and the scope widened to include more information and other tips and tricks - so I've decided to try to split this up into a series - only focusing on a few modifications at a time. That way - I can present some simple modifications and give some more detailed information about them. And then the community can discuss them, or ask questions about them below. And I'll create additional threads for each subsequent part of the series.

And for this series of posts, I'm going to assume that you have at least some familiarity with Vim.
e.g.
You've at least used Vim a few times, you've ran through vimtutor a few times, you know about Vim's different modes ('normal', 'insert', 'command', 'ex', 'Visual', 'Visual Line', 'Visual Block' etc). You're getting the hang of basic editing in vim and you're interested in learning how to enhance your experience in Vim by modifying your .vimrc.

If you haven't ran through vimtutor already, I suggest you do so now... It's fine, I'll just wait for you! Come back whenever you're ready. Take your time, ha ha!

The main reason I use Vim is because I have arthritis and carpel tunnel in my hands. I find the Vim keybinds extremely intuitive, ergonomic and physically less painful than the default keybinds used in pretty much all other editors. I find that I can be much more productive in Vim. I can type for longer, with less pain. And my hands rarely need to leave the home row. So Vim really suits me. I've been using it every day,for many years and have invested a LOT of time in learning how to use it more effectively.

However, there is one default Vim keybind that I find extremely annoying..... I despise constantly having to leave the home row to press <esc>, in order to switch back to command mode. I have no problem whatsoever with constantly switching modes, I've grown to love Vim's modal features. I just don't like having to constantly reach for the escape key every time. It completely disrupts my rhythm/flow!

Vim does have another default, built-in, alternative key-bind mapped to escape, which is ctrl + [, or in Vim-speak <c-[>. But, I'm not a huge fan of that one either, as it still involves leaving the home row AND performing a bit of a stretch with both hands. It's less annoying than escape, but it can be a little painful.

Some Vim users also recommend swapping the caps-lock and escape keys around, but that's actually more of a system-wide key-mapping, rather than a purely localised Vim only mapping. Which I personally think would be disruptive. Plus, if you use caps lock a lot - which, as a C/C++ programmer, I do - then you've potentially swapped one problem for another. Instead of leaving home row to hit escape, you now have to leave home-row every time you want to toggle caps lock. Is there a better key combo that could be used to switch back to 'normal' mode? I believe there is!

Which leads into my personal favourite, most useful .vimrc modification ever, which is this:
1. Mapping jj to escape.
It sounds weird, but bear with me. I believe I have some compelling reasons for doing this. I'll explain them later.
In this modification, we'll be mapping the key combo jj to escape when in 'insert' mode (when actually typing/editing text). And mapping jj to ctrl + c in 'command' mode (when typing/editing a command in 'command' mode). Allowing us to quickly return to 'normal' mode without having to move from the home row.

Here's the code to add to your .vimrc, I'll explain what it does afterwards.
Open up your existing .vimrc, find an appropriate spot, press o to put vim into 'insert' mode on a new-line in your .vimrc and add the following lines:
Code:
inoremap jj <esc>
inoremap JJ <esc>

cnoremap jj <C-c>
cnoremap JJ <C-c>

Now hit the <esc> key and save using :w.

The two inoremap commands define keyboard mappings for 'insert' mode.
e.g.
When you are typing text in 'insert' mode.

In this case, we're mapping 'jj' to generate an escape key-stroke. So with this modification in your .vimrc - whenever you're typing text in 'insert' mode and you want to switch back to 'normal' mode, you can simply type in jj, which will generate an escape key hit and Vim will switch back to 'normal' mode.
The second inoremap is mapping 'JJ' (uppercase jj) to escape. (JIC I'm typing with caps-lock on and I want to go back to 'normal' mode !)

The two cnoremap commands define 'command' mode key-mappings.
e.g.
When you are writing a command using Vim's command (:) operator, like :e /path/to/somefile.ext, you're in Command mode.
cnoremap maps jj to generate a <C-c> key hit (Ctrl + c).
With this modification in place, if you get part way through writing a command and you change your mind, you can type jj to cancel the command, instead of having to press Ctrl + c to cancel.
And the second cnoremap maps JJ to Ctrl + c, to allow you to cancel a command if you have caps-lock on.

Why is mapping jj to escape such a great idea?
OK, explanation time... There are a few reasons why I think 'jj' is an extremely good candidate for an edit-mode keybind for switching to 'normal' mode:
1) On a standard, English QWERTY keyboard - the J key is conveniently placed on the home-row, anchored directly underneath your right index/pointer finger. So it's immediately accessible, requiring no effort whatsoever to double tap it.
2) The sequence 'jj' doesn't occur in any common English words (that I am aware of). So it's pretty safe to use as a shortcut from a writers point of view (at least for English).
3) Using jj as a name for counter variables in loops is a common practice in C, C++ and several other programming languages. But it's a very bad habit. It's much better to use more meaningful names for variables. So mapping jj to escape will effectively prevent that happening. Seriously, stop using ii and jj for counter variables in your loops people! Ha ha!

So in my opinion - mapping jj to escape is an absolute no-brainer. Try it - you might just love it! And if you don't - simply remove those modifications from your .vimrc.

NOTE:
Once you have this shortcut in place - if you ever actually need to type 'jj' in your document, or in a command, without it generating and escape and taking you back to nomal mode - you have to type the first j, then pause for a second or so, before typing the second j. When you type the first j, the cursor will hover over the j for a second or so. This is because Vim knows that there is an insert mode shortcut that starts with j. You just have to wait until the cursor moves to the right of the j before typing the second j. So it's potentially disruptive if you ever need to type jj. But I mean, seriously - how often are you likely to use jj in a file/document?

If you're typing a normal word that contains a j - like Jason, or Project - then the cursor will hover briefly above the j as you type, but you can continue to type your word, without needing to pause. Again, you only need to pause if you are trying to insert 'jj' into a word in your document/file, or into a command. But again.... Seriously, how often are you going to need to do that?! Not unless you're the biographer for legendary Jazz-man JJ Johnson (who tragically committed suicide in 2001), or JJ Abrahms, or something?!

Additional notes on key-mappings:
In a .vimrc file, or a vim script - the syntax for keyboard mappings is:
[type of mapping] [trigger key/sequence] [action to perform]

Where [type of mapping] is exactly that - you specify whether it's a global, insert mode, command mode, normal mode or visual mode keyboard mapping.
The [trigger key/sequence] is the keyboard shortcut, or key-sequence/pattern/combo that you want to use to trigger an action.
And [action to perform] is the action to perform when the shortcut, or sequence has been entered by the user.

Recursive and non-recursive keyboard mappings:
inoremap stands for insert-mode no recursive map. There are also non-recursive equivalents for the other Vim modes cnoremap (for command mode), nnoremap (for normal mode), vnoremap (for visual mode) etc. These commands all create non-recursive mappings.

In order to understand non-recursive mappings, I first aught to explain what recursive mappings are.
The Vim commands map, cmap, imap, nmap and vmap create recursive keyboard mappings for Vims various modes.
By a recursive mapping, I mean that anything in the defined action will be expanded if there's a key-bind mapping for that too.

Personally, I avoid recursive mappings where possible, because if you aren't careful - your shortcut might end up doing completely unintentional things due to unwanted expansions.
For example, you could end up creating a mapping which self-references itself and goes into an infinite recursive loop during the expansion.
Or it might expand unexpected parts of your action, causing it to do something you didn't intend, or expect.

As a purely contrived example of recursive keybinds going wrong, consider this: (NOTE: DON'T add this to your .vimrc. It is NOT going to do anything interesting, or useful!)
Code:
map j F
map G j
noremap O j
The two map commands are recursive.
The first one maps j to F. OK, that's fine.
The second one maps G to j, but because map is recursive and j was already mapped to F previously, then G actually ends up being mapped to F.
But the noremap in the code-block above is non-recursive. So O is mapped directly to j. No expansion of j occurs.

So to avoid unwanted expansions, I recommend using the non-recursive key-mapping commands. inoremap, cnoremap, nnoreamap - etc. Where possible.

The recursive key-mappings can allow you to set up some really complex, clever mechanisms when used properly. But generally speaking, I tend to use the non-recursive key map commands as they're safer and easier to use. You have to be extremely careful when using the recursive mapping functions.


Moving swiftly along. Here is another extremely useful modification:
2. Reloading your .vimrc whilst still in Vim (and 2.a. Setting the leader key).

In the previous modification, we set up a few keybinds to allow us to quickly get back to 'normal' mode, from 'insert' mode, or 'command' mode by typing jj, or JJ.
But we can't test it out until we have re-started vim, or reloaded our .vimrc..... Wouldn't it be nice if we could just reload our .vimrc and test our changes whilst vim is still running?
Well, there is a command that will allow you to do this.
Simply enter the command:
Code:
:source $MYVIMRC
Where $MYVIMRC is a special variable in Vim, which stores the path to the .vimrc file that was loaded when Vim started up.

Go ahead and enter that command now, reload your .vimrc so you can use jj or JJ to quickly return to 'normal' mode, without having to leave the home row.
Seriously give it a go.... Go into edit mode using i, or o, type some gibberish then quickly type jj... And suddenly you should find yourself back in 'normal' mode. How neat is that? Don't forget to undo, or delete the gibberish - you don't want that getting saved to your .vimrc! Ha ha!

Hint: Undo in vim is accessed via the 'normal' mode key u.

So far, we have added a quick way of getting back to normal mode from the edit/command modes AND we know a command to reload our .vimrc on the fly..... But we don't want to have to type that command every single time we make a change to our .vimrc do we? So let's add a custom keybind for that as well!

So this is what we'll add to our .vimrc: (And once again, drop into edit mode using o and add the following line:
Code:
map <leader>r :source $MYVIMRC<CR>

In the code-block above, we have mapped <leader>r to run the :source command, to reload our .vimrc via vim's special internal variable $MYVIMRC.
The <CR> at the end of the command tells Vim to press the enter key, in order to run the command.
Basically, all of the actions that the keybinds are mapped to, are essentially macros. You define a key combo, or a text pattern to act as a trigger. Whenever that key/pattern is pressed, or that trigger pattern is detected in typed text - the corresponding action is triggered as a sequence of simulated keybinds. So our jj mapping, maps jj to simulate an <esc> key-press.
<leader>r will simulate the key-presses we would need in order to run the :source command to reload our .vimrc.
And I know what many of you are thinking right now.... You're thinking "But what the hell is the leader key? Where is it? and what does it do?"
I assure you, I was coming to that.

In Vim, the default leader key is backslash (\). The leader key can be used to prefix keybinds. So alongside ordinary, global, or modal keybinds, the leader key allows you to define another entire bank of keybinds that are prefixed with whatever key the leader key currently is.
By default, our keybind <leader>r, would equate to \r, assuming that the leader key is still set to its default.

In order to reload your .vimrc whilst still in Vim. From normal mode, you would simply type \r. And your .vimrc will be reloaded and you can immediately try out the changes. However, because we've only just added that keybind to the .vimrc, it's not yet available to us in vim. So we need to manually run the :source $MYVIMRC command one last time, in order to re-load our config and pick up the new <leader>r keybind.
If you do that now - the next time you make a change to your .vimrc, you can quickly reload your .vimrc by pressing \r in 'normal' mode.

Notes On Redefining The Leader Key:
Some people prefer to change their leader key to comma ,. Personally, the default backslash \ leader key setting suits me just fine.
But if you want to redefine your leader key to comma, add the following line to your .vimrc.
Code:
let mapleader = ","
That line is purely optional. Put it somewhere BEFORE the definition of your first keybind that uses the <leader> key.
You don't have to use comma, you could specify any other key in there. But you should bear in mind that most of the other symbolic keys have already been mapped to other things. So comma and backslash are probably the only two candidates available to use for your leader key. If you decided to map the leader key to comma, the keybind for reloading the .vimrc will become ,r.

If you opted to map your leader key to comma - as per the code-block above - I'd also recommend reloading your config using the original, default leader key. Because we're still in vim and the new configuration hasn't been re-loaded yet. So you'll have to use \r. After doing that, you'll then be able to use ,r to reload your config.

So now we've got a nice alternative to escape. we know what the leader key is and how to change it. And we know how to create keybinds that use the leader key as a prefix.


Lets try one more for fun and then I'll call it a day because this post got large rather quickly:
3. DUDE! Where's my cursor?!
I don't know about you, but sometimes, when I've got a huge wall of text open in front of me in Vim, I completely lose track of the cursor. Perhaps I've ran some commands in another terminal or looked away from the screen for a while. And then I've looked back and wondered where the hell the cursor was. Perhaps I was watching a cat video in my other monitor whilst Vim was still focused and I've absent-mindedly pressed some normal mode navigation keys. And now I can't immediately see where the cursor is.

This next modification sets up a neat highlight effect, that will give you a massive cross-hair that will immediately show you exactly where you are in your file.
And we'll set up a leader keybind to toggle it on and off.

Here's the code to add to your .vimrc:
Code:
highlight CursorLine ctermbg=darkgrey ctermfg=black
highlight CursorColumn ctermbg=darkgrey ctermfg=black
map <leader>h :set cursorline! cursorcolumn!<CR>

Once you've added those lines to your .vimrc and returned to normal mode via <escape> (or your nifty, new jj shortcut - you're welcome, BTW). Save your changes using :w and then press <leader>r (\r, or ,r) to reload your .vimrc and apply those changes.

This time we've defined a highlighting scheme for CursorLine and CursorColumn.
CursorLine is the line that the cursor is currently on. And CursorColumn is the column that the cursor is currently on.
ctermbg and ctermfg set up colours for the background and foreground (text colour), respectively.
So effectively, the first two lines tell Vim to highlight the CursorLine and the CursorColumn with a dark-grey background and black text.
Depending on your colour scheme - you may want to experiment with different colours for this.
In Vim, you can use the command :help cterm-colors to see a list of the available colours.

The final line maps the key combo <leader>h to enter the following Vim command :set cursorline! cursorcolumn!<CR>, which toggles the cursorline and cursorcolumn on and off.
The exclamation marks ! flip the state of the cursorline and cursorcolumn variables.
So if cursorline and cursorcolumn are off, then using :set cursorline! cursorcolumn! sets them to the opposite of their current state. Therefore,turning them on.
And when they are turned on, the highlighting is applied to them. When they are turned off, the highlighting is removed.
So in effect, what you get is a huge crosshair on your screen that you can toggle on and off. And if you mess with the colours, you can make it as pretty, or gaudy as you like.
But one thing's for sure, you aren't going to lose your cursor for very long!

So for me to toggle it, I'd use \h. If your leader key was redefined to the comma, then you'd use ,h.

And I think that's about it for the first set of tips in this series. We've covered quite a lot of information considering we've only added a handful of simple keybinds. I could have just posted a bunch of esoteric snippets of code with little or no description. But I figured I aught to fully explain what we're doing and why.

Hopefully now you at least understand a little more about defining custom keyboard mappings for vim.
As the series goes on, I'll share more useful keybinds and commands. And a lot more tips on using vim effectively.
Hopefully that wasn't too much information to take in. If you have any questions, or comments - fire away in the comments below.

Vim is an insanely powerful editor with capabilities that will blow your mind when you actually get to grips with its unique way of doing things. There is a bit of a learning curve involved and it does take a lot of time and practice to get used to. But if you stick with it - it can really pay dividends. You'll be far more productive than in any other editing environment. At least that's been my experience.

The next article will cover some really handy keybinds for managing buffers and tabs in Vim. In the meantime, I'm out of here!
 
Last edited:


This should be posted with Jarret's stuff in the "front page" of this site. Or somehow combine the two threads about this subject and make the result as persistent thread. <3
 
This should be posted with Jarret's stuff in the "front page" of this site. Or somehow combine the two threads about this subject and make the result as persistent thread. <3
I want to keep these threads as a series of standalones. That way, I can present a few tips/modifications at a time and people can ask questions about them, or discuss them, or perhaps even suggest alternative solutions that might be better than mine. I’m not going to claim that my way of doing things in Vim is perfect. There are plenty of vim users out there who are better at vim-golf than I am, ha ha!

But once I have a few more parts up, I could create and maintain an index thread, with links to each part of the series and then that could be stickied, and/or posted on the "front-page", if the admins fancy it!
 
and/or posted on the "front-page", if the admins fancy it!

More specifically, those are "Tutorials" classified posts. I'd have no objection to moving these there as nothing prevents people from commenting in those threads. I'm not sure I'd make that decision in a vacuum, however. So, I'll simply state that I have no objections. I'm quite certain that you know what you're doing, even if I am not fluent in Vim.
 

Staff online


Top