vimrc mapping key doens't work as expected [duplicate] - vim

Is it possible for the terminal to detect ⇧ Shift+Enter↵ or Ctrl+Enter↵ keypresses?
I am trying to configure vim to do key mappings that use these sequences, and while they work fine in gvim, they don't seem to work in any terminal console.
The curious thing is that although Ctrl+Enter↵ is not detected in vim, mapping Enter↵ to Esc maps properly, but then pressing Ctrl+Enter↵ behaves like Enter↵!

Some terminals send <NL> when <C-Enter> is pressed. This is equivalent to sending <C-J>.
To find out what your terminal does with <Shift-Enter>, <Ctrl-Enter> and <Enter>, go to your terminal, type <Ctrl-V> (similar to sykora's suggestion for vim), and type in the sequence you're interested in.
Using gnome-terminal, I get the following:
<Enter> : ^M
<S-Enter> : ^M
<C-Enter> : <NL>
Looking at man ascii indicates that ^M gives the <CR> sequence.
The answer is that it depends on the terminal, and there's an easy way to check.

Gvim runs its own manager for keystroke handling and so can pick up all the various key combinations. Vim is reliant on the specific terminal for passing on the particular keypress, so keyhandling is only as good or varied as the terminal is.
One way you can find out whether you can do what you want to do is to use the key to find out what is inserted. eg Type:
:<C-V><C-Enter>
ie actually type in the combination you want to press after having typed the combination Control-V. After that do the same thing for enter, ie
:<C-V><Enter>
If they yield the same code, then the terminal interprets both key combinations as the same keycode, and you can't bind them without messing with the terminal.
In my terminal (urxvt), Control-Enter, Shift-Enter and Enter (by itself) all produce the ^M character, meaning I can't map one without mapping the other. The same goes for Control-Tab and Control-I, and Control-Space and Control-#
EDIT: Use C-Q instead of C-V for Windows.

Related

Error in my Vim mapping

I would like to map Control + F3 with map <c-f3> :w <CR> :make <CR><CR><CR>. When I leave out the Control this works fine. With control from normal command mode insert mode is entered and 1;5R is inserted into the buffer.
When I use a simpler command e.g. map <c-f3> dd this works as expected.
With Shift instead of control I get a similar behavior (1;2R inserted into buffer). What can I do get my mapping right?
Edit: I want the command to be executed from normal command mode. However, vim enters insert mode, which is not desired.
The combination of function keys and modifiers is problematic in terminal Vim; whether this works depends on the terminal.
Check your $TERM value; a wrong one can cause these problems. Also, your termcap database must be correct and complete.
Try out another terminal (gnome-terminal vs. konsole vs. xterm); it may work there.
Alternatively, use GVIM; it doesn't have these problems (but still can't map some other combinations).
If you use varying terminals, it's best to avoid these key combinations, and just use plain <F1..12>, and <Leader>... for the rest.
map defines keystrokes for normal, visual and operation modes. For insert mode you should use imap.
Something like this I believe: imap <c-f3> <esc>:w :make <cr><cr><cr>. <ESC> puts the Vim to normal mode.
:he :key-mapping for explaining.

Vim commands containing `r` cause me to replace

I'm using vim and the python-mode extension, but I'm having a hard time using commands that contain r. It's causing vim to replace characters instead of executing my desired command.
Here is what the vim docs for python-mode say -
let g:pymode_rope_organize_imports_bind = '<C-c>ro'
So I'm doing CTRL-cro, but like I said, it's replacing which ever character I'm under with the letter o.
What am I missing?
It seems that your mapping is not being interpreted by Vim, so it only sees the Ctrl-c, which by default aborts the current action, then the replace command r (see :help r) followed by its "argument".
You could check if the mapping is defined with :map <c-c>.
If it is correctly defined it may be that your terminal is handling the Ctrl-c directly and not passing it to Vim, as stated in Vim FAQ 20.5 - Why does mapping the key not work?. In this case you could follow the instructions on Vim FAQ 20.4 - I am not able to create a mapping for the key. What is wrong?, in special:
1) First make sure, the key is passed correctly to Vim. To determine if
this is the case, put Vim in Insert mode and then hit Ctrl-V (or
Ctrl-Q if your Ctrl-V is remapped to the paste operation (e.g. on
Windows if you are using the mswin.vim script file) followed by your
key.
If nothing appears in the buffer (and assuming that you have
'showcmd' on, ^V remains displayed near the bottom right of the Vim
screen), then Vim doesn't get your key correctly and there is nothing
to be done, other than selecting a different key for your mapping or
using GVim, which should recognise the key correctly.

Mapping Alt-j and Alt-k in vim [duplicate]

I'm running Vim on a gnome terminal. But the alt key mappings are not working. For example:
:imap <A-i> <Esc>
It works fine in GVim. But when I run the same command with Vim in the gnome terminal it does nothing.
I'm using Windows 7, The problem is with the terminal, right?
The problem
There are two ways for a terminal emulator to send an Alt key (usually called a Meta key as actual terminals didn't have Alt). It can either send 8 bit characters and set the high bit when Alt is used, or it can use escape sequences, sending Alt-a as <Esc>a. Vim expects to see the 8 bit encoding rather than the escape sequence.
Some terminal emulators such as xterm can be set to use either mode, but Gnome terminal doesn't offer any such setting. To be honest in these days of Unicode editing, the 8-bit encoding is not such a good idea anyway. But escape sequences are not problem free either; they offer no way of distinguishing between <Esc>j meaning Alt-j vs pressing Esc followed by j.
In earlier terminal use, typing Escj was another way to send a Meta on a keyboard without a Meta key, but this doesn't fit well with vi's use of Esc to leave insert mode.
The solution
It is possible to work around this by configuring vim to map the escape sequences to their Alt combinations.
Add this to your .vimrc:
let c='a'
while c <= 'z'
exec "set <A-".c.">=\e".c
exec "imap \e".c." <A-".c.">"
let c = nr2char(1+char2nr(c))
endw
set timeout ttimeoutlen=50
Alt-letter will now be recognised by vi in a terminal as well as by gvim. The timeout settings are used to work around the ambiguity with escape sequences. Esc and j sent within 50ms will be mapped to <A-j>, greater than 50ms will count as separate keys. That should be enough time to distinguish between Meta encoding and hitting two keys.
If you don't like having timout set, which times out for other mapped key sequences (after a second by default), then you can use ttimeout instead. ttimeout applies only to key codes and not other mappings.
set ttimeout ttimeoutlen=50
For Gnome-terminal, use the following instead:
imap ^[i <Esc>
^[i should be typed by pressing Ctrl-v Alt-i
Attention: You need to yank and put in Vim when you want to copy it elsewhere. If you just copy the mapping in an editor like gedit, the mapping will probably be broken.
EDIT here is an example which makes Alt-k add an empty line above the cursor, and Alt-j add an empty line after the current line.
" Alt-j/k to add a blank line
if has('gui_running')
" the following two lines do not work in vim, but work in Gvim
nnoremap <silent><A-j> :set paste<CR>m`o<Esc>``:set nopaste<CR>
nnoremap <silent><A-k> :set paste<CR>m`O<Esc>``:set nopaste<CR>
else
" these two work in vim
" shrtcut with alt key: press Ctrl-v then Alt-k
" ATTENTION: the following two lines should not be
" edited under other editors like gedit. ^[k and ^[j will be broken!
nnoremap ^[k :set paste<CR>m`O<Esc>``:set nopaste<CR>
nnoremap ^[j :set paste<CR>m`o<Esc>``:set nopaste<CR>
endif
Try
<m-i>
Or, if typing alti inserts a character (like in my case, it inserts a carret: ˆ) just map to that character:
:inoremap ˆ <esc>
Be careful, because this one wouldn't work (at least in my system, MacOS 10.6). The caret waits for a letter, because it's not exactly a caret, it is a circumflex.
It may be that the shortcuts are actually from the Gnome Desktop. Try looking at the Gnome Keyboard Shortcuts tool (System menu, Preferences, Keyboard Shortcuts), which lets you view and modify the shortcuts defined on Gnome Desktop. If the key combination is assigned to a function on Gnome Desktop, then remove it and then that key combo should filter down to Vim properly.
Or you may be right that it is a problem of the terminal. Not all terminals support all key combos. Your problem may be the one described in the Vim help docs at :h map-alt-keys. The docs provide a workaround, but not a very good one.
The same thing happens to me. I searched on Google with "gnome terminal alt key", and found that someone asked almost the same question: "How to disable the alt-hotkey behavior on gnome terminal?" in the first link found. (The second link is just this question)
So, maybe you can try that:
Edit > Keyboard Shortcuts, and uncheck "Enable menu access keys"
Take a look at section 1.10 of http://vimdoc.sourceforge.net/htmldoc/map.html. It seems to indicate that gnome-terminal automatically escapes the Alt modifier, so that it doesn't switch the byte sent in the way that Vim is expecting. The document seems to indicate that there isn't really a way around this except for using a different terminal (such as xterm).
This is certainly frustrating because so far as I can tell Linux machines are also incapable of using the D (Mac's Command or Linux's Super) bindings, so at least as far as the terminal goes, we are limited to Shift and Ctrl modifiers, which is frustrating if we want to ensure that we can use all the commands we use in Gvim on terminal Vim (at least without switching terminals, towards which I'm perhaps overly stubborn - gnome-terminal is just so much prettier). I've been looking for a way around this but have been unable to find anything.

Alt key shortcuts not working on gnome terminal with Vim

I'm running Vim on a gnome terminal. But the alt key mappings are not working. For example:
:imap <A-i> <Esc>
It works fine in GVim. But when I run the same command with Vim in the gnome terminal it does nothing.
I'm using Windows 7, The problem is with the terminal, right?
The problem
There are two ways for a terminal emulator to send an Alt key (usually called a Meta key as actual terminals didn't have Alt). It can either send 8 bit characters and set the high bit when Alt is used, or it can use escape sequences, sending Alt-a as <Esc>a. Vim expects to see the 8 bit encoding rather than the escape sequence.
Some terminal emulators such as xterm can be set to use either mode, but Gnome terminal doesn't offer any such setting. To be honest in these days of Unicode editing, the 8-bit encoding is not such a good idea anyway. But escape sequences are not problem free either; they offer no way of distinguishing between <Esc>j meaning Alt-j vs pressing Esc followed by j.
In earlier terminal use, typing Escj was another way to send a Meta on a keyboard without a Meta key, but this doesn't fit well with vi's use of Esc to leave insert mode.
The solution
It is possible to work around this by configuring vim to map the escape sequences to their Alt combinations.
Add this to your .vimrc:
let c='a'
while c <= 'z'
exec "set <A-".c.">=\e".c
exec "imap \e".c." <A-".c.">"
let c = nr2char(1+char2nr(c))
endw
set timeout ttimeoutlen=50
Alt-letter will now be recognised by vi in a terminal as well as by gvim. The timeout settings are used to work around the ambiguity with escape sequences. Esc and j sent within 50ms will be mapped to <A-j>, greater than 50ms will count as separate keys. That should be enough time to distinguish between Meta encoding and hitting two keys.
If you don't like having timout set, which times out for other mapped key sequences (after a second by default), then you can use ttimeout instead. ttimeout applies only to key codes and not other mappings.
set ttimeout ttimeoutlen=50
For Gnome-terminal, use the following instead:
imap ^[i <Esc>
^[i should be typed by pressing Ctrl-v Alt-i
Attention: You need to yank and put in Vim when you want to copy it elsewhere. If you just copy the mapping in an editor like gedit, the mapping will probably be broken.
EDIT here is an example which makes Alt-k add an empty line above the cursor, and Alt-j add an empty line after the current line.
" Alt-j/k to add a blank line
if has('gui_running')
" the following two lines do not work in vim, but work in Gvim
nnoremap <silent><A-j> :set paste<CR>m`o<Esc>``:set nopaste<CR>
nnoremap <silent><A-k> :set paste<CR>m`O<Esc>``:set nopaste<CR>
else
" these two work in vim
" shrtcut with alt key: press Ctrl-v then Alt-k
" ATTENTION: the following two lines should not be
" edited under other editors like gedit. ^[k and ^[j will be broken!
nnoremap ^[k :set paste<CR>m`O<Esc>``:set nopaste<CR>
nnoremap ^[j :set paste<CR>m`o<Esc>``:set nopaste<CR>
endif
Try
<m-i>
Or, if typing alti inserts a character (like in my case, it inserts a carret: ˆ) just map to that character:
:inoremap ˆ <esc>
Be careful, because this one wouldn't work (at least in my system, MacOS 10.6). The caret waits for a letter, because it's not exactly a caret, it is a circumflex.
It may be that the shortcuts are actually from the Gnome Desktop. Try looking at the Gnome Keyboard Shortcuts tool (System menu, Preferences, Keyboard Shortcuts), which lets you view and modify the shortcuts defined on Gnome Desktop. If the key combination is assigned to a function on Gnome Desktop, then remove it and then that key combo should filter down to Vim properly.
Or you may be right that it is a problem of the terminal. Not all terminals support all key combos. Your problem may be the one described in the Vim help docs at :h map-alt-keys. The docs provide a workaround, but not a very good one.
The same thing happens to me. I searched on Google with "gnome terminal alt key", and found that someone asked almost the same question: "How to disable the alt-hotkey behavior on gnome terminal?" in the first link found. (The second link is just this question)
So, maybe you can try that:
Edit > Keyboard Shortcuts, and uncheck "Enable menu access keys"
Take a look at section 1.10 of http://vimdoc.sourceforge.net/htmldoc/map.html. It seems to indicate that gnome-terminal automatically escapes the Alt modifier, so that it doesn't switch the byte sent in the way that Vim is expecting. The document seems to indicate that there isn't really a way around this except for using a different terminal (such as xterm).
This is certainly frustrating because so far as I can tell Linux machines are also incapable of using the D (Mac's Command or Linux's Super) bindings, so at least as far as the terminal goes, we are limited to Shift and Ctrl modifiers, which is frustrating if we want to ensure that we can use all the commands we use in Gvim on terminal Vim (at least without switching terminals, towards which I'm perhaps overly stubborn - gnome-terminal is just so much prettier). I've been looking for a way around this but have been unable to find anything.

Can terminals detect <Shift-Enter> or <Control-Enter>?

Is it possible for the terminal to detect ⇧ Shift+Enter↵ or Ctrl+Enter↵ keypresses?
I am trying to configure vim to do key mappings that use these sequences, and while they work fine in gvim, they don't seem to work in any terminal console.
The curious thing is that although Ctrl+Enter↵ is not detected in vim, mapping Enter↵ to Esc maps properly, but then pressing Ctrl+Enter↵ behaves like Enter↵!
Some terminals send <NL> when <C-Enter> is pressed. This is equivalent to sending <C-J>.
To find out what your terminal does with <Shift-Enter>, <Ctrl-Enter> and <Enter>, go to your terminal, type <Ctrl-V> (similar to sykora's suggestion for vim), and type in the sequence you're interested in.
Using gnome-terminal, I get the following:
<Enter> : ^M
<S-Enter> : ^M
<C-Enter> : <NL>
Looking at man ascii indicates that ^M gives the <CR> sequence.
The answer is that it depends on the terminal, and there's an easy way to check.
Gvim runs its own manager for keystroke handling and so can pick up all the various key combinations. Vim is reliant on the specific terminal for passing on the particular keypress, so keyhandling is only as good or varied as the terminal is.
One way you can find out whether you can do what you want to do is to use the key to find out what is inserted. eg Type:
:<C-V><C-Enter>
ie actually type in the combination you want to press after having typed the combination Control-V. After that do the same thing for enter, ie
:<C-V><Enter>
If they yield the same code, then the terminal interprets both key combinations as the same keycode, and you can't bind them without messing with the terminal.
In my terminal (urxvt), Control-Enter, Shift-Enter and Enter (by itself) all produce the ^M character, meaning I can't map one without mapping the other. The same goes for Control-Tab and Control-I, and Control-Space and Control-#
EDIT: Use C-Q instead of C-V for Windows.

Resources