18

I've disabled my arrow keys, and am finally getting used to hjkl (for the longest time I'd always hit j and k the wrong way around - just seemed more natural for some reason).

In normal mode I'm fine with it, but not being able to move the cursor in insert mode is killing me.

Frequently I want to make lots of short changes to a few lines near each other. Previously this was a doddle with a couple of taps of arrow keys, but having to leave insert mode, move then re-enter insert mode is incredibly tedious - it means I end up reaching for the mouse instead, which isn't what we're aiming for with vim!

What's your solution?

12
  • 7
    This is a serious question (it's not my intention to be rude): given that using them makes things easier for you, why have you decided to disable your arrow keys in insert mode?
    – Rich
    Commented Jun 12, 2020 at 10:45
  • 2
    @Rich because if the internet is to be believed, in the long run once you've got over the steep learning curve, it's better NOT to use the arrow keys. Or so a lot of people state, anyway.
    – Codemonkey
    Commented Jun 12, 2020 at 11:11
  • 7
    As for your response to my other question, you shouldn't believe everything you read on the internet ;). You can also find many (very experienced) Vim advocates on the internet saying that you should do whatever works for you. If your current workflow with arrow keys is already "a doddle" where's the improvement to come from? A dogmatic refusal to use the arrow keys in that scenario seems just to be slowing yourself down for no reason.
    – Rich
    Commented Jun 12, 2020 at 15:07
  • 8
    Re: because if the internet is to be believed, in the long run once you've got over the steep learning curve, it's better NOT to use the arrow keys. Or so a lot of people state, anyway: this is nonsense propagated by Vim purists who hold the misguided view there is a One True Way™ to use Vim (namely, the way they prefer). If you like arrow keys: use them. If you don't: then don't. Simple as that. Commented Jun 12, 2020 at 16:46
  • 5
    I'm confident that when iron tools started to replace bronze there were "bronze purists" who claimed that iron tools were bad, rusted if you left them out in the rain, caused stones to crack and split where the softer bronze tool wouldn't have done that, etc, etc. (I've heard that the gods favor the users of bronze tools, for they are righteous and gnarly, and that the blasphemers who foul themselves with iron shall suffer eternal schmutz and etc, but I don't know. But lots of people are saying that... :-) Commented Jun 12, 2020 at 20:05

8 Answers 8

35
+250

I believe that the art of Vim has nothing to do with disallowing any tools available for you, but rather finding the best (i.e., most efficient) path to altering text. The truth is that sometimes the arrow keys really are the most efficient. This is particularly true in cases where several small insert-mode changes need to be made that are interspersed with several small navigations.

Here is a small test to illustrate this:

Fast: Using Arrow Keys (Insert Mode)

Adding single unique characters to each line (fast!)

Slow: Using HJKL Navigation (Normal Mode)

Adding single unique characters to each line (slow!)

Using arrow keys here is clearly faster. Not only does exiting and re-entering insert mode cost extra keystrokes, but it also requires the user to reset their left hand position. A different set of characters to add (maybe more right-hand focused) could change the results, but I believe the effect would be similar.

Here is a similar example where HJKL navigation will typically prove better:

Slow: Using Arrow Keys (Insert Mode)

Replacing the first character of each line (slow!)

Fast: Using HJKL Navigation (Normal Mode)

Replacing the first character of each line (fast!)

When it comes down to it, all we can do is to approximate the fastest path. Oftentimes this is best without arrow keys, and this is where Vim shines -- we could all share countless tricks and tools for normal mode manipulation. But, sometimes, there's just nothing better than arrow keys.

5
  • 5
    Welcome to Vi and Vim! Thanks for taking the time to write a very thoughtful answer!
    – filbranden
    Commented Jun 12, 2020 at 22:00
  • 4
    This is terrific.
    – Rich
    Commented Jun 12, 2020 at 23:54
  • This is a good answer, but I disagree about hand position: Using arrow keys also requires resetting a hand, hence why it is recommended to avoid them. A solution that avoids all hand movement from the home row is to bind an unlikely pair to esc in insert mode (e.g. kj or jj). In your first example arrow keys still win by one key stroke per edit though.
    – kitsu.eb
    Commented Jun 15, 2020 at 14:38
  • In first example one can switch to normal mode for one move: <CTRL+O> and then to first character in next line with <CR> and be back in insert mode in desired position to enter letter. Commented Jun 18, 2020 at 6:43
  • Regarding the first example, if you have the characters to be entered memorized, sure. If there's any thinking time involved or you're copying from some source then it's not going to be that much faster than the alternatives. BTW, I think I'd handle that example in a way that turns it into your second example. Ie. use <c-v>}0Ix or something to insert a dummy character then rXj repeatedly from there (X is whatever character goes with current line). That may sound insane but when the first part is instinctual it works. :)
    – B Layer
    Commented Jun 23, 2020 at 20:42
9

My solution is to use everything vim offers me: HJKL, /, FftT, {n}w/b/e, ^, $, %, [], ][, [{, and also arrow keys, control arrow keys, home, end, Pg Up and Down, the mouse...

Arrow keys and hjkl are both as inefficient when moving around. If the need is only to move of a couples of characters or lines, they are perfect. For more, Vim has better solutions. They come with time.

Try to think about what you want to do: move to the next Word, the beginning of the current function... instead of moving to the position you see with your eyes.

4
  • I have no problem with navigating in normal mode - I'm not a god but I'm certainly using more than hjkl. It's the fact that without arrow keys it becomes impossible to navigate without quitting insert mode first. That's the bit I struggle with. I've remapped jk (and kj) to esc, and am used to that now, but to move one line down and three characters to the right I have to hit jkjlllli, rather than just <down><right><right><right>. It feels inefficient. 8 keystrokes vs 4.
    – Codemonkey
    Commented Jun 12, 2020 at 11:18
  • 6
    In all honesty, I've never understood this "arrow you shall not use" commandment. On the contrary, I've been using vi then vim for than more 25 years, and yet I seldom use hjkl. I don't feel less efficient than what I could be. In the use case you describe here, I'd use (in normal mode) down + F{key I see} Commented Jun 12, 2020 at 11:34
  • 1
    @Codemonkey. Number of keystrokes is not the only side of fast editing. IMHO the more important is time. Let's be honest, in your example you have 4 keys and 2 hand motions (from base to arrows and back), which for me are far slower then pressing 8 nearest keys. I use inoremap <C-L> to move 1 key forward not leaving insert mode and some more tricks, which help sometimes. And yes, I still use arrows in some cases, like up-arrow in Cmdline mode to search command started with string I typed, and mouse to resize windows. Each tools is best at some tasks, don't limit yourself =)
    – Dmitry
    Commented Jun 12, 2020 at 21:25
  • The addition of ctrl-etc key remaps to move while in insert mode is a good idea, I feel I should have thought of that! Given everyone else's comments and answers here though... I might just go back to the arrow keys.
    – Codemonkey
    Commented Jun 14, 2020 at 13:16
6

In general I try to stay out of insert mode as much as is humanly possible. (A fact I alluded to in the comments.) Most of the time, for lots of small edits I make to nearby lines, I will endeavour to enter insert mode only once.

For your given example of changing getVal to get_val on two consecutive lines with the cursor starting far from the first edit point, what I'd most likely do in practice is:

  1. /getVal<CR> Jump to first location.
  2. ciwget_val Make the edit. fVsv_ is fewer keystrokes, but wouldn't, for me, actually be any quicker to type, and also it would prevent me from performing the edit on the next line simply with...
  3. n. Jump to the second location and make the change again.

If the cursor starts after the edit points, instead of before, I'd substitute ? for / in step 1.

If the cursor starts near to the edit points, I'd instead use whatever other motions are quickest (which hopefully doesn't include hjkl) to get there, and then press * to set up my search register (without moving the cursor, because I have * mapped to *<C-O>), and then continue with steps 2 and 3.

2
  • 2
    cgn is even nicer in this case, as you only have to press .
    – D. Ben Knoble
    Commented Jun 12, 2020 at 16:32
  • @D.BenKnoble Yeah. For some reason, cgn has never clicked with me. ¯\_(ツ)_/¯
    – Rich
    Commented Jun 14, 2020 at 10:01
2

This answer might not be able to cover all cases where you see yourself doing many small edits on different locations of the same line, but I find that a good approach here is to try and turn them from many separate small insertions into a Normal mode action.

That often means adopting plug-ins implementing more complex actions, or also advanced text objects that can help select the right bits of text to act upon.

In the comments, you mentioned refactoring to replace getVal with get_val. Plug-in vim-abolish has a "coerce" operation under cr to do case coercion, using crs will perform case coercion to snake case on the current word, which is the transformation you're after. (cr_ also works.)

Another type of refactoring that typically involves small edits interspersed with movements is adding braces or parentheses around text. Plug-in vim-surround can help with that. You can surround text with ys, for example ys"iw to put double quotes around the current word. Or replace types of braces, cs]) to replace square brackets with parentheses. You can also use visual mode to select which text to surround.

For advanced text objects, I recommend targets.vim, which introduces some useful text objects for arguments of functions that can also be very helpful when refactoring code. It also introduces modifiers for the "next" (n) and "last" (l, more like "previous") text object, so you can act further away on the line you're in. For example, you can use dana to delete the "next" argument if you're on top of a function call or an argument of a function call. Plug-in targets.vim includes many other helpful text objects and it also extends some built-in text objects in Vim to make them smarter.

Make sure you also have vim-repeat, which will allow you to use . to repeat actions from plug-ins such as vim-abolish and vim-surround (among many others), which is important if you're using these actions repeatedly on many separate lines or matches.

In short: Try to reframe your small edits into an "action", which you'd execute in Normal mode, and consider embracing plug-ins which implement such actions for you.

1
  • 1
    And macros, and /search<CR>cgn, and all the goodies :) this is what id write if i had the time
    – D. Ben Knoble
    Commented Jun 12, 2020 at 16:29
2

People always think the advice for disabling the arrow keys is so you will use hjkl instead, but it's really so you will get used to using normal mode in general. Normal mode is where you get all your efficiency gains.

As others have pointed out, yes, there are situations where an arrow key is faster than using normal mode to move one square, but most of the time, you aren't moving just one square. Forcing you into normal mode hopefully encourages you to learn and use those shortcuts that work by lines and words and marks and patterns.

At a certain point, you don't even think about switching back into normal mode. You just always seem to be in it, and occasionally you realize after the fact that just hitting an arrow key would have been faster. That's when I recommend re-enabling your arrow keys.

That being said, ultimately the way you learn and use the tool is up to you. Just be aware that the fastest vimmers are normally in normal mode.

1

having to leave insert mode, move then re-enter insert mode is incredibly tedious

I imagine most of the tedious part is leaving insert mode, which implies reaching for the Esc key. Personally, I have my CapsLock mapped to Esc (with setxkbmap -option caps:escape), but there are multiple alternatives, like mapping jj to leaving insert mode, etc.

I actually switch more than necessary, and don't see it as a hassle. It's because I'm thinking of a series of actions and my fingers just translate. Let me give you an example. Let's say that I want to

  1. call foo
  2. pass it an object
  3. make it a multiline object
  4. pass it field bar with value "baz"

I don't foo({EnterTabbar: "baz"EnterBackspace}).

Instead I do:

  1. foo()Caps (call foo)
  2. i{}Caps (pass it an object)
  3. iEnterCaps (make it a multiline object *)
  4. koTabbar: ""Caps (add field bar) **
  5. ibazCaps (with value "baz")

I think I don't see it as a hassle because:

  1. I've made it easier to exit insert mode, by using Caps
  2. Typing like that allows me to take advantage that opening and closing braces of all types are right next to each other on a QWERTY keyboard. This also allows me to hit " twice in succession when typing strings. It limits how many times I need to move from typing words to "weird" keys.
  3. This is the big one for me: It better maps editing actions I have in mind to key sequences I need to type. It's like it makes typing more composable. I think this allows me to use muscle memory better when editing text.

* When I know from the get-go that I want a multiline object, I'll just {Enter} directly. Since it's just a common thing to do and the keys are so close to one another, it's already in my muscle memory. I would do it like I listed above if I wasn't sure at first, though, or if the keys were different.

** I use ko because O immediately after Esc corresponds to some terminal escape sequence, so weird stuff happens.

0

I have a non standard solution for the need to press esc too often: Map ` to be insert mode enter & leave. If I need to insert `, I mapped ctrl-] for that (rare). For ` in normal mode, I mapped ! (not needed that often so shift-1 is ok) And ctrl-` for ctrl-o for fasted movement .

I have another solution of leaving insert mode on timeout but found it not useful.

0

I use the arrow keys a lot, but rebound them to automatically exit insert mode, as shown below. In my experience, it quickly becomes second nature to navigate with hjkl when you know what mode you're in and with the arrow keys when you're in insert mode or aren't sure.

inoremap <left>  <esc>
inoremap <up>    <esc><up>
inoremap <down>  <esc><down>
inoremap <right> <esc>l

Overall, it is very convenient and works well with one's intuition. It does make using visual block mode more annoying though, since your navigation options when creating a small bit of text to Insert or Append are more limited.

You might also consider just rebinding the up and down keys.

inoremap <up>    <esc><up>
inoremap <down>  <esc><down>

That way, moving around within a line doesn't change the mode you're in, but leaving the line does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.