We all know about no-op’ing arrow keys in Vim to get us to break the habit of relying on them for inefficient movement. But, as this post points out, it is not the location of the arrow keys that makes them inefficient, but the modality of the movement: single steps in insert mode is a horrible way to move around when normal mode provides so much better functionality.
But here is the thing: while normal mode provides for much better and
more efficient ways to move around than insert mode, it also provides
for ways to move that are just as inefficient as arrow keys. In fact,
there is nothing that makes, e.g. “
j” significantly better than
<DOWN>”, and so if we replace
jjjj, we are just slapping on some fresh paint on a rusty bike and
calling it “faster”. We have not even replaced one bad habit with
another, we are indulging in the same bad habit, albeit with a
different “it”. A bad habit that is not only inefficient, but, perhaps
a much worse sin in the Vim-world, inelegant.
will help break you of that habit by forcing you to enter a count for
each of the basic moves (”
gk”). This itself will make you more efficient for any move of
three repeats or more: “
3j” is more efficient than the uncounted
jjj” equivalent. But, in addition, it will also have the
side-effect of making you come up with more efficient moves yourself: as
your eyes focus on the point where you want to go, instead of counting
off the lines (or reading off the line count if you have
:set relativenumber”), you might find it more natural to, e.g.
In fact, you might find that in many cases, you do not even need to
actually move as such. For example, instead of moving to a line 8 lines
down and deleting it, “
8jdd”, you could just “
:+8d”. Or instead
of moving to a line four lines up, yanking it, moving back to where you
were and pasting it, “
4kyy4jp”, you can just “
:-4y” and “
Once you get good enough at it, it will seem like magic the way you can
manipulate lines far from your current position without moving! And what
you will find is that, beyond the increased efficiency in number of
keystrokes, there is an increase in mental efficiency: the microseconds
of visually re-orienting yourself after each move is no longer a cost
that you have to pay over and over and over again.
Naturally, you are going to find things less efficient and less elegant at first. But that is just the pain that of stressing out mental muscles that have not been exercised enough, like that first leg day after the holidays (or maybe even the first leg day ever after signing up at the gym 4 years ago).
Eventually, your efficiency will increase.
But more than efficiency, the elegance of your moves will eventually increase as well. Dramatically. As far as editing text goes, at any rate.
So, stick the
into your “
~/.vimrc”, and be prepared for some pain and frustration
and swearing and clumsiness as you retrain your muscle memory and your
mind, before gaining a new level of enlightened
[NOTE]: One of the greatest impediments to me naturally working with counted-movements was the fact that counting the number of lines to go in each direction is disruptive: it completely breaks my “flow”, jarringly derailing my train of thought. See below for the solution to this, the implementation of which I consider a mandatory pre-requisite to working this way.
" Notes: " (1) To enhance the ergonomics of this sufficiently to make it practical, at " least, until your brain grows a new lobe dedicated to counting line offsets " in the background while you work, you should either make sure you have " something like the following in your `~/.vimrc`: " " set number " if has('autocmd') " augroup vimrc_linenumbering " autocmd! " autocmd WinLeave * " \ if &number | " \ set norelativenumber | " \ endif " autocmd BufWinEnter * " \ if &number | " \ set relativenumber | " \ endif " autocmd VimEnter * " \ if &number | " \ set relativenumber | " \ endif " augroup END " endif " " or you have installed a plugin like " (vim-numbers)[https://github.com/myusuf3/numbers.vim]. " " (2) You might want to relax the constraint for horizontal motions, or " add other motions. You can customize the list of motions by " specifying the keys in the " `g:keys_to_disable_if_not_preceded_by_count` variable. For example, " the following only enforces count-prefixed motions for "j" and "k": " " let g:keys_to_disable_if_not_preceded_by_count = ["j", "k"] function! DisableIfNonCounted(move) range if v:count return a:move else " You can make this do something annoying like: " echoerr "Count required!" " sleep 2 return "" endif endfunction function! SetDisablingOfBasicMotionsIfNonCounted(on) let keys_to_disable = get(g:, "keys_to_disable_if_not_preceded_by_count", ["j", "k", "l", "h"]) if a:on for key in keys_to_disable execute "noremap <expr> <silent> " . key . " DisableIfNonCounted('" . key . "')" endfor let g:keys_to_disable_if_not_preceded_by_count = keys_to_disable let g:is_non_counted_basic_motions_disabled = 1 else for key in keys_to_disable try execute "unmap " . key catch /E31:/ endtry endfor let g:is_non_counted_basic_motions_disabled = 0 endif endfunction function! ToggleDisablingOfBasicMotionsIfNonCounted() let is_disabled = get(g:, "is_non_counted_basic_motions_disabled", 0) if is_disabled call SetDisablingOfBasicMotionsIfNonCounted(0) else call SetDisablingOfBasicMotionsIfNonCounted(1) endif endfunction command! ToggleDisablingOfNonCountedBasicMotions :call ToggleDisablingOfBasicMotionsIfNonCounted() command! DisableNonCountedBasicMotions :call SetDisablingOfBasicMotionsIfNonCounted(1) command! EnableNonCountedBasicMotions :call SetDisablingOfBasicMotionsIfNonCounted(0) DisableNonCountedBasicMotions
Displaying Relative Numbers vs. Absolute Numbers
I find the need to count line offsets before every move or operation as
conducive to my “flow” as having an air horn stuffed down my throat
while frozen mayonnaise is blasted into my ears. This was why I resisted
count-based ergonomics in Vim for so long. Vim has a feature, “`:set
relativenumber`” that shows relative numbers, and this makes things
tremendously better, in that you can simply read of the line offset to
your navigation target .… except that you must choose to show
either relative numbers or absolute numbers. The fact is, the only
time relative numbers are useful is for motions/operations in the
current window or split, but when you have other splits open, relative
numbers are worse than useless, as you need to have absolute numbers to
make sense of what part of the buffer you are seeing in the non-focal
splits. Showing both absolute and relative numbers at the same time
would be ideal, but Vim does not support that natively (there is a
plugin to help with
that, but it exploits the
which can be a problem if you use signs to display something else, like
marks, as I do). So
the dilemma is that in most cases you want absolute numbers, but
count-based motions/operations in the current window are annoying and
mentally-disruptive if you do not have relative numbers showing to avoid
you breaking your train of thought to count the lines to the target.
Luckily, a Vim plugin provides the answer:
vim-numbers. This plugin
automatically sets relative numbers on for the split/window in focus,
and restores the previous numbering (absolute in my case) when focus
moves to another split or window. It was this that made my move to
strict count-required based motion possible.
EDIT: It was pointed out by
/u/VanLaser that the following in
~/.vimrc” is sufficient to achieve the
without the need for a plugin:
set number if has('autocmd') augroup vimrc_linenumbering autocmd! autocmd WinLeave * \ if &number | \ set norelativenumber | \ endif autocmd BufWinEnter * \ if &number | \ set relativenumber | \ endif autocmd VimEnter * \ if &number | \ set relativenumber | \ endif augroup END endif