Besides their position and hand movement required, is there any difference between using hjkl and the arrow keys? Can I use either one interchangeably and expect the same behavior? The only difference I can think of is that the arrow keys work in insert mode so you save strokes if you need to move 1-2 chars.
Note: I use an alternate keyboard layout and the hjkl keys are mixed up. I have a programmable layer on my keyboard and wondering whether it should have hjkl or the arrow keys. I'd prefer to use the arrow keys since they can be used in all programs.
Arrow keys vs. h,j,k,l
You are correct in your assessment. They are equivalent, except that the arrow keys also work in insert mode.
(The same is true in a couple of other places, for instance you can use left/right arrows to move around within a command or search/replace you are typing, but you cannot use hjkl for movement in those cases.)
There is one other difference, I suppose - since they are separate keys, they can be mapped to separate things. So if you remap h for instance, it would not affect the function of <Left>, and vice-versa.
Other keys
You asked about some other keys in the comments.
X - Bkspc, x - Delete, 0 - Home, $ - End, R - Insert
Some are equivalent, but not all of these.
x, X, backspace, delete
x and <Del> are equivalent, and even share the exact same node in the help text. Both of them delete characters under and after the cursor.
X and <BS> both delete characters to the left of the cursor. But in different modes: X does so in normal mode, and <BS> does so in insert mode. If you are in normal mode, <BS> just goes backward by one character without changing the text (so it behaves like h).
0, $, Home, End
These are interchangeable.
R, Insert
These do not do the same thing. <Insert> works like i, and inserts. R enters insert mode, but in a special way where it overwrites characters rather than inserting before them.
Related
While using Vim under Linux Mint 20.2 (with NumLock off), when I hit the NumPad center key (5), a line is inserted above the current line, a capital E appears, and I am left in Insert mode. I often mistakenly hit the 5 key when trying to navigate using the NumPad cursor keys, and I would love to redefine the NumPad 5 to do nothing. I've tried remapping the key in .vimrc (using noremap <Esc>[E <Esc>, for example), but it has no effect. Note, the ANSI sequence produced when I press the NumPad5 is \033[E
FYI, I have TERM=xterm-256color.
Note: this answer generally talks about the numpad in a no-numlock context. All numbers on the numpad can be mapped when numlock is on by using <k0>...<k9>. References to the mapability of keys is therefore in a no-numlock context
Note, the ANSI sequence produced when I press the NumPad5 is \033[E
Vim doesn't see it that way.
On my system (Mint 20.2 with Cinnamon under X11), no-numlock 5 produces ^[OE. That O is very important to the observed behavior. o means "go to a new line under and enter insert mode", and O means the exact same thing, but to a new line above. The next E is then interpreted as an insert mode character, because Vim.
Moreover, esc is represented as ^[, so for mapping purposes, you only need <esc>. This point is easier to demonstrate in Vim:
^[ is additionally treated as a single character. If you want to play around with this, pop into insert mode and press <C-v>. The next key(bind) you press will be printed literally to the screen
This means what you actually want is:
nnoremap <Esc>OE <nop>
Note that I'm not sure how terminal input processing applies here; this may only hold for certain terminals, or even only apply to X11.
Another trick in general here, and a way to make sure the keycode is correct for your terminal, is that you can type :nnoremap , and then press Ctrl+v+Numpad 5. This will give you the exact keycode as Vim sees it, which you then can map to whatever you have planned.
If you do this in gVim, however, you'll find that numpad 5 without numlock doesn't actually produce a keycode detectable by gVim. This presumably means it can't be mapped (unless there's some way I just don't know about - if there is, please prove me wrong). But because it doesn't spew out a terminal code, there's the added benefit of not needing to remap it for this particular purpose, because it doesn't have the problem you're trying to avoid here in the first place.
romainl mentioned :help key-notation in the comments, but there's something to keep in mind here:
gVim not producing a keycode usually means there isn't one. <C-v> followed by numpad 9 in gVim produces <kPageUp>, but followed by numpad 5, it doesn't produce anything. Secondly, if you read :h key-notation, you'll see that it only defines home, end, up, and down, as well as the various operators, enter, and the decimal point. 2, 4, 6, and 8 are all registered as normal arrow keys, meaning <Down>, <Left>, <Right>, and <Up>. There's no way to detect these on the numpad specifically, but that's not really important.
If you've been keeping track, you'll find that numpad 5 is excluded. Note: When numlock is on, <C-v> + numpad 5 doesn't output anything in Vim or gVim, because the definition is:
Insert the next non-digit literally.
See :h i_CTRL-V.
TL;DR:
<C-v> is your friend.
Use:
nnoremap <Esc>OE <nop>
Or use <C-v> to insert the keycode, that may or may not be terminal dependent.
The mapping isn't necessary in gVim, and may not be possible.
The reason why you see this behavior is that Vim uses only the termcap interface of the terminal database. If it used terminfo, it would see a wider range of information.
Typing the key on the keyboard is misleading, because Vim (like almost all terminal applications) puts the keypad into application mode, which causes the terminal to send Escape and O rather than Escape and [ as a prefix. In terminal notation, that is \EO. In XTerm Control Sequences, that is referred to as SS3 (technically a misnomer since that applies to output, while keyboard input is input — but since no standards apply to keyboard input, that's good enough).
The terminal description for xterm at one point assigned \EOE to the kbeg capability (i.e., terminfo, which termcap names #1). That was a while back, around 1996.
Terminfo names are generally 3-5 characters, while termcap names are always 2.
Standard terminfo has a limited number of special keys (such as those for the numeric keypad which you are familiar with). All of the standard termcap names correspond to these terminfo names. In the standard arrangement, there are only five keys associated with a keypad: ka1, ka3, kb2, kc1, and kc3, which correspond to termcap's K1, K2, K3, K4, and K5. (Why there are no standard k2, kb1, kb3, or kc2 is long forgotten).
Looking for ways to improve the terminal descriptions in ncurses, a few different layouts of the standard keys have been proposed. But the best solution lies in adding new keys, using extended capabilities (a feature of ncurses since 1999). Those extensions all have names, and are chosen to conform to terminfo naming conventions. So... in May 2019, the terminfo building blocks xterm+keypad and vt220+keypad were introduced. In the former (used in xterm-new and xterm-256color, that key is named kp5.
There's no kp5 in the standard names listed in the terminfo(5) manpage. It is an extended (user-definable) key. In the older scheme some other key was unavailable for applications.
An ncurses application would automatically be able to use all of the keys, because ncurses uses terminfo (and adds all of the keys in a terminal description to its special cases for timing).
Vim will not see that key's definition because it views only a fraction (about a third) of the terminal description. Since it does not see the definition, it does not add that to the special cases where it will wait (a short time) for the completion of the character-sequence sent on that key. As noted in the other answer, in that case, Vim will see the commands Escape and O to insert the third character in the sequence, "E".
I am trying to find replacement for multi cursors plugin and found out cgn command pretty useful. However, there is undesirable behavior using arrow keys during insert mode. Sometimes there is no need to change the whole search entry (e.g. fix typo) so the arrow keys are necessary in that case. To reproduce the "bug" you can type tabe and then 3ifoobar<Enter><Esc>/foo<Enter>cgn<End>bar<Esc>.
No matter what movement you will use: arrow keys or key like <End> - powerful dot command stops working. I mean it just inserts text written after movement at the same position instead of changing the next search entry.
The only way to support redo, consists in using <C-G>U before <right> and <left>. This requires has('patch-7.4.849')
If you need to move to the end of the line, you'll need to count. If you need to move to the next line, you'll loose redo.
I want to map 'space+u' as 'Ctrl+u', I have this at my config:
nnoremap <space>u <C-u>
But it isn't work as Ctrl+u. When I press 'space+u', firstly it works fine, but when I press 'u' second time - it works an 'undo' (I'm holding 'space' since first time). I want to make it works as , when I press 'Ctrl', hold it and can hit 'u' any times I want.
What can I do?
The mapping you made means "space first, then u in succession". Not simultaneous action there, which explains the behavior for subsequent calls.
Vim listens to key press events; the system reports it that this-and-that key was typed, with that-and-that modifier (ctrl, super). Few applications would understand to check arbitrary combinations of keys being held (outside of games).
For this sort of hacks there is an established project for Linux systems called https://github.com/alols/xcape. In combination of xcape and xmodmap you can basically map <space> as a modifier key like less used Hyper key (this is the part for xmodmap). Then you would use xcape to make sure that pressing space in isolation would result in a space character. People have used xcape to map return as a right Ctrl key (while Caps Lock would act as the left Ctrl).
The d{motion} command seems to work inconsistently:
d1j " deletes 2 lines to the bottom
d1l " deletes 1 character to the right
Is it expected behaviour?
When you start a motion and you are in operator pending mode, your motion will be either inclusive or exclusive, and either characterwise or linewise (linewise motions are always inclusive).
j is a linewise inclusive motion. Probably you want to try dvj or dgj (the latter one works with screen lines).
See :help operator. You can force motions to be linewise, characterwise or blockwise with V, v or CTRL-V respectively.
It is not actually inconsistent. I guess you were looking for
delete one line: dd (which is a command)
delete one line down: d1j (or short dj). This is an operator with a motion)
The remaining surprising bits are due to vim's notion of linewise, blockwise and characterwise motions, which are really just abstractions to allow Vim to Do The Right Thing or Do What You Expect when operating on selections.
Like #Benoit said, d is operator that takes a motion.
2j being linewise, it will move two lines down, covering 3 lines.
Note how, if you would like some visual clues with that, you can set the rn option
:se relativenumber
This will cause relative linenumbering to be shown in the left 'gutter' of the editor. These numbers can be used as 'addresses' and do what you expect when you do 'd12j' or 'd12k'
I recommend getting acquainted with the text object motions before getting used to this, by the way. Many times, text objects are much more precise (and often work in character mode, only degrading to linewise selections in appropriate conditions)
I use MacVim (and gvim) a lot. I'm familiar with and use a lot of the basic movement commands (b, w, $, 0, G). However, for a lot of things—such as selecting particular lines on the screen or jumping to a particular column in a different line—I use the mouse (sometimes in concert with my left hand on the keyboard). It also helps that my mouse has a scroll wheel and buttons for changing tabs.
I also need to admit... I use the arrow keys on my keyboard rather than hjkl.
I think that my speed (and posture at the computer) will be improved by not having to escape from insert mode, and from keeping both hands on the main part of the keyboard.
What convinced you to abandon the mouse? What are the most helpful shortcuts for moving quickly between lines and columns, scrolling, etc.?
This question is inspired by this recent post
I think that my speed (and posture at
the computer) will be improved by not
having to escape from insert mode
No, you must escape from insert mode right after you typed what you want. It quickly becomes a reflex, so you don't really lose time (I sometimes even press escape after completing a web form...). Normal mode isn't just for moving around, it's used to perform most operations (save from typing): for instance deleting or moving sections of text. You also benefit from entering insert mode with the appropriate key: o to start a line, S to replace a line (while keeping indentation), A to move to the end of the line, c+motion to replace a few words or until a given character... All of these save keystrokes.
The mouse seems fast, but in reality it isn't precise, so you lose time (in addition to the constant back and forth with the keyboard). ViM has a long list of moving commands (see :help usr_03) which, when mastered, are faster than the mouse in most situations.
Use search the most you can (/, ?, *, #, f, t...). I personally use Ctrl+(d,u,f,b) a lot. Also, Ctrl+(o, i) and `` are really useful to go back where you were before a search or something else.
h, j, k, l are there to place your right hand near to useful commands (i, u, o...): I always have my fingers on them. The arrows force you to move your hand a lot.
Try to look at a few commands in :help, then use them a lot, and you'll get habits about what you should use to move according to the situation. Nobody uses ViM the same way.
The more I used the keyboard movement in vim, the less I wanted to use the mouse. It doesn't help that extended periods of time where I'm constantly moving from keyboard to mouse can take a toll on my wrist.
If you want to force doing things the vim way, unplug your mouse for a while! The more you use the keyboard, the more you will love it. This worked for me.
For moving between lines, I usually just use jk but I often skip to lines using :line_num. Getting to a specific column in a line, I typically use wbe^0$ and put modifiers in front of w, b, or e if I'm skipping through several words. And there is also the shifted versions, WBE which also come in handy often.
I have to admit that I often use the arrow keys for specific movement in vim.
I rarely use hjkl. However, I find that most of my navigation is done with other commands such as w (skip a word forward), b (skip a word backwards). Combine this with modifiers such as 3w (3 words forward). : skip to a specific line.
I've never really had to abandon the mouse since I never really started with it. All I can say is that attempting to use editors without all the keyboard shortcuts that vim has can feel quite painful.
I'd run vimtutor from the command line (Terminal.app in OS X). It runs vim with a tutorial document. That document was what really made me realize the power of some of the commands. You'll pick up some that are most useful to you and gain more over time. Eventually you'll find yourself using the mouse less and less.
One command that will really improve your movement speeds is f. f plus a character will jump to the first occurrence of that character on the current line. Pressing ; will jump to the next occurrence. Of course this can be used in combination with other commands. So, for example, removing all characters up to and including the first closing parenthesis is achieved by pressing d+f+).
You can seriously revolve your life around jk in hjkl.
nnoremap <c-k> ddkP "move current line up one
nnoremap <c-j> ddp "move current line down one
vnoremap <c-j> dp'[V'] "move visual block down one
vnoremap <c-k> dkP'[V'] "move visual block up one
"These may be a bit more esoteric to me"
inoremap jj <esc>o "Insert mode can move to next line (works mid line)
inoremap kk <esc>O "Insert mode new line on previous line
also for the desktop gui (ion3 and gnome)
winj - next window
wink - prev window
(This beats alttab if your editing in vim all day)
also read :he motion.txt in its entirety using j and k to scroll up and down as you do.
I learned vi so for me the mouse has never been something to use with a text editor.
I don't use hjkl except when the machine/network/keyboard/whatever-in-between is not comfortably configured.
Use the mouse where it makes sense. It often does (copy/paste to and from other gui applications).
To answer your question, though: Once you start using vim as a tool for transforming text bits with macros, the movements will all start to fall into place ;)
I think you're wondering if there's a quick way to move around while in insert mode (without using the mouse or arrow keys) but unfortunately there isn't; you have to escape out of insert mode. However I know that jumping all the way to your Esc key can be really annoying, which is why I've gotten into the habit of escaping with Ctrl+c, it's much faster.
I almost never use hjkl because it's too tedious. I usually try to jump right to where I want to go. There's a great cheat sheet out there (a Dvorak version is a available also (although it's in PDF)) that you can stare at and imagine the possibilities.
Mostly I use f, F, t, and T, and sometimes they're enhanced by typing a number up front like d2t) will delete up to the second close paren. Sometimes I use search. A lot of the time I use w, W, b, B, e, and E. They're all fantastic.
When I see vim users arrowing all over the place in visual mode just to delete text it makes me shudder, because there are so much easier ways (and hjkl only make you move your arm less, they don't change the number of button presses).
Something I did that I don't know if it's common or not is remapped my arrow keys to be <Esc><Up> and so on. For whatever reason I started out always arrowing around and assuming I'd be back in normal mode, so I just made it do that...
The biggest bummer about Vim is that now when I edit anything anywhere else I hit escape all of the time and type :w after every change...