remap or ignore spacebar in vi - vim

Vim/vi shortcuts are awesome, but there is one behavior that I would be very happy if it could be configured. My machine uses Brazilian Portuguese(abnt2) keyboard map,and some accents(like caret) needs an extra spacebar to be print, obviously because they wait/expect another character, mostly vowels. Example of the "cut until you find an empty line":
d/^$
Keystrokes actually needed on br-abnt2:
d / <shift + ~ , spacebar>(to result ^) $ <enter>
I could use { d } as it is explained on this awesome thread, but i would benefit much more on other accents(backslash) where the extra backspace trick is needed, and most important, without change my keyboard mapping to "US" for example.
Edit: I also know that this is a keymap limitation, since our language expect something after the accent, and this is why i'm asking if there is a way to circunvent this limitation inside vim.
Any ideas?

The problem does not come from the editor, but your keymap. In fact, the caret is set to be a "dead key". Meaning that it should wait for other input before being printed.
What you probably need is a new keymap that has the caret as a non dead-key. As for example, uk-gb map has caret on the key as well as another dead-key ( if I remember correctly).
If you don't want/can't remap your keyboard, you can use vim mapping function do act so.
Just choose an unused key and map it like this:
imap g ^
This will insert ^ while typing g on insert mode (other mapping for other- mode exists, nmap, ...).
For example, to use the vim mapping in the vim command-line, you shall use :
cmap g ^
Then your example will be working.

Related

In Vim, the 5-key on the numeric keypad inserts a line above the current line with "E"

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".

Insert mode default keys in vim

The following items are useful to me in editing text, and I was wondering if vim had something for this built out of the box (though I didn't see it on the https://vimhelp.org/index.txt.html#index.txt page), or I had to create mappings for it:
Forward-delete a character. This is X in normal mode.
Forward-delete all text to the right of the cursor on the line. This is the inverse of ctrl-u.
Are either of these mappings available? And if not, are there 'standard' mappings for this that are common (for example, how it might be done in another unix program).
Note that this is the keyboard I have -- there is only one delete key (which acts like a normal backspace key) and there is no backspace key:
Note: for forward-delete, I am currently mapping ctrl-d as:
"Ctrl-d to forward-delete when in insert or command mode
noremap! <C-d> <Delete>
However, this interferes with the tab in insert mode (which I don't use) and the help-options in command mode (which I do use!) so I may have to modify this later, or hopefully someone suggests a better solution.
though I didn't see it on the https://vimhelp.org/index.txt.html#index.txt page
If you can't find it in the documentation, then it doesn't exist.
You can use fn+delete for "Forward-delete a character".
"Forward-delete all text to the right of the cursor on the line" is ctrl+k in MacOS, but Vim has its own use for that combo, :help i_ctrl-k so it is up to you to create a mapping for it.
Something like:
inoremap <key> <C-o>ld$

Return to normal mode without leaving the home row

I've been trying out vim, and the emphasis on speed and accessibility makes sense for the veteran programmer. I've previously used emacs, and currently use a combination of nano, and stuff like gedit or geany.
I'm confused by the need to constantly switch modes, and that returning from insert mode to normal mode requires leaving the home row to press Esc. I've read that previously, this key was Tab on some systems where vim was first used, which makes a lot more sense, but not on current systems where tab is expected to participate in smart indenting when coding.
Returning to normal mode is an operation that you need to perform all the time. Is there some alternative key mapping that makes this quicker, or mappings that I simply don't know about that do this?
Ctrl+C also return you to normal mode
You can also use ^[. If you've mapped your caps lock key to control (highly recommended), this becomes a rather easy keystroke.
I personally use the Capslock key as the second Esc key, so it is very comfortable. You can do it by adding the following lines to your .xmodmap file:
remove Lock = Caps_Lock
keysym Caps_Lock = Escape
You can map whatever you like to escape:
imap kj <Esc>
I haven't yet run across a situation where I need to type kj next to each other, besides when I talk about this mapping. I've seen other people use jk or jj, but kj works best for me.
I personally use ii to get out of insert mode while staying on the home row, but it is only a matter of personal preference:
inoremap ii <Esc>
i to go in insert and ii to go out. This is easy for your finger to remember. (I tend to still use <Esc> though)
I personally use Left Control as escape and Caps Lock as Left Control. It is not vim mapping, but some xmodmap+setxkbmap magic:
! ~/.Xmodmap
! Control_R
keycode 37 = Escape
and ctrl:nocaps in X keyboard options. You may have different keycode though.
Use Alt/Meta In a Terminal
If you use Vim in a terminal, simply press alt/meta+normal_mode_key. Most terminals send an escape character followed by the normal_mode_key that you pressed, removing the need to press escape yourself.
The terminals konsole and gnome terminal send the escape by default when you press alt/meta+normal_mode_key. For Xterm you can ctrl+click and select the option "Meta sends escape" or "Alt sends escape".
Thus in insert mode pressing alt+h alt+j alt+k alt+l all take you to normal mode and move in the expected direction. You can hold down alt when moving even while in normal mode since the additional ESC that is sent does no harm.
The advantage of using this scheme is that you can use the alt/meta+key combination with any normal mode key, e.g.
Alt+o opens a new line below the one you are currently editing,
Alt+A appends to the end of the current line,
Alt+p pastes at the current insert location.
Alt+k moves up
Thus using vim via a terminal gives you these short cut powers on any stock standard system without the need to edit each systems vim mappings.

Case-sensitive keyboard shortcuts

I'd like some map/remap/nmap/etc. commands to be case sensitive, e.g. "<C-I>" vs. "<C-i>".
I checked Google and :help map, but was unable to find this.
It appears you currently can't combine control with case-sensitivity in vim or gvim (I'm using 7.2). I might expect this to be a limitation of terminals for the former, but not the latter.
I tested it by typing this in a buffer:
map <c-i> :echo "c-i"<cr>
map <c-s-i> :echo "c-s-i"<cr>
Yank those lines, then :#" (when executes register " as commands). Verifying the maps with :map <c-i> and <c-s-i> shows the problem: <c-i> is <tab>, and only the last one takes effect, with the shift being ignored.
For alt, <a-i> and <a-s-i> do work as expected in gvim
In terminal vim, those two get mapped to é and É (at least here, check with ":map <a-i>" as above), and typing é/É directly (I use dead keys) does invoke the mapping. Actually doing a-i or a-s-i just enters insert mode.
Of course, non-control and non-alt maps work case-sensitively.
Add S for Shift
<C-S-i>
If you use your Caps Lock, (1) what on earth for?, and (2) you'll have problems. See here if this is your situation.
My bad.
Cannot be done, by design, with printable characters. The approach above does work with F1 et al, such as <C-S-F8>. See this thread for more.
My workaround would be to map it to something entirely different and obscure, and use AutoHotkey or similar to substitute the combination only for the uppercase variant.
Docs say that "CTRL-A and CTRL-a are equivalent".
Relevant part from :help notation
CTRL-{char} {char} typed as a control character; that is, typing {char}
while holding the CTRL key down. The case of {char} does not
matter; thus CTRL-A and CTRL-a are equivalent. But on some
terminals, using the SHIFT key will produce another code,
don't use it then.
(not intended as an answer, but as relevant info for anybody comming from search engine regarding case sensitivity)

VIM: Mappable (unused) shortcut letters?

I'm trying to create two mappings which are efficient for myself:
map X ddp
Which I'd use to delete and paste in one go.
map X "_dw
Which would delete a word without yanking into a register.
However I don't want to break any existing, useful shortcuts so I'm wondering what keys I could use - any suggestions? Am I being too uptidy?
vim help has a section :he map-which-keys
1.7 WHAT KEYS TO MAP *map-which-keys*
If you are going to map something, you will need to choose which key(s) to use
for the {lhs}. You will have to avoid keys that are used for Vim commands,
otherwise you would not be able to use those commands anymore. Here are a few
suggestions:
- Function keys <F2>, <F3>, etc.. Also the shifted function keys <S-F1>,
<S-F2>, etc. Note that <F1> is already used for the help command.
- Meta-keys (with the ALT key pressed). |:map-alt-keys|
- Use the '_' or ',' character and then any other character. The "_" and ","
commands do exist in Vim (see |_| and |,|), but you probably never use them.
- Use a key that is a synonym for another command. For example: CTRL-P and
CTRL-N. Use an extra character to allow more mappings.
See the file "index" for keys that are not used and thus can be mapped without
losing any builtin function. You can also use ":help {key}^D" to find out if
a key is used for some command. ({key} is the specific key you want to find
out about, ^D is CTRL-D).
Many Vim plugins use an initial <Leader> to start their key sequences; this is an (otherwise normally) unused key that is configurable by the user.
*<Leader>* *mapleader*
To define a mapping which uses the "mapleader" variable, the special string
"<Leader>" can be used. It is replaced with the string value of "mapleader".
If "mapleader" is not set or empty, a backslash is used instead. Example:
:map <Leader>A oanother line<Esc>
Works like:
:map \A oanother line<Esc>
But after:
:let mapleader = ","
It works like:
:map ,A oanother line<Esc>
Note that the value of "mapleader" is used at the moment the mapping is
defined. Changing "mapleader" after that has no effect for already defined
mappings.
Every single ASCII character, upper and lower case, is used for something in Vim. So you're going to wind up overwriting something--just pick something that you don't use. It may help to use a common idiom for your own extensions. I use a leading comma, for example:
map ,w :w!<CR>
map ,e :e #<CR>
imap ,, <ESC>
(The last is particularly useful for me, since I pretty much never need to write two consecutive commas in insert mode, and it's nice not to have to go all the way to the Esc key.)
Typically I use control + [letter] or alt + [letter] for most mappings and it's safe, but watch out for 'w' since that's needed for window commands. You might also be interested in arpeggio.vim which lets you create mappings to simultaneously pressed groups of keys - it will massively expand the possibilities for your mappings with no danger of over-mapping something. For example, you could map "dp" (pressed simultaneously) to execute "ddp" to delete and paste in one command.
Uhmm, no, don't. When creating your mappings try not to overwrite anything ... not so much because you don't use the command you're overmapping, but because some plugin which you have/or will have maybe using it.
And then you overmap it, and then you have to worry.
Personally, for commands such as you gave as an example, I like Ctrl+some key combinations. There are a lot of free ones in vim, and the letters on the left side near Ctrl make a nice pair then.
Btw, what are you trying to do with those mappings ... I understand the second one (delete word by word), but the first doesn't make sense to me. What is it supposed to do ? Transpose lines ?

Resources