When using vim's terminal mode (access by :term) if I put in two double quotes and then press the left button (such as if you were to type in git commit -m "" and then go back one character to start the message), the following happens:
The terminal is closed.
A new line is added above the cursor in the buffer.
Insert mode is entered.
The character D is inserted.
The exact typed sequence is :term<cr>git commit -m ""<left>
Why is it that this series of events happens, and how can I prevent it in the future?
It turns out that in some terminals the arrow keys are represented with escape key sequences, such as the left arrow represented by Esc O D. In my vimrc I had the mapping tnoremap <esc> <c-w>:q!<cr> which was meant to close the terminal when I pressed the escape key. But due to how vim interpreted my arrow key sequences, it would close out the terminal when I pressed any of the arrows. I solved this by changing the mapping to tnoremap <esc><esc> <c-w>:q!<cr>.
More background can be found on this error here: https://github.com/vim/vim/issues/2216#issuecomment-337566816
Related
Any keystroke (except for Esc) puts vim into insert mode and inserts the character. Example: I sit in Normal mode, press k to go up, vim goes into insert mode and types k under the cursor. Same for : and other keys. Esc or Ctrl-[ returns to Normal mode, but the behavior persists.
This doesn't happen on entering vim, but on occasion (quite often) it gets into this mode and stays until I kill the terminal window. It's not global (so if I have another vim instance in another terminal, the state does not propagate) so it's probably not about the input modes / keyboard layouts.
Running a Mac M1 with macOS 12.
What could it be?
Update:
It happens after I hit Delete key in Insert mode (consistently).
I have a binding that exits Insert mode on a key sequence (inoremap saj <esc>l), and typing that exits Insert mode for good after it gets stuck. However, exiting through Esc or Ctrl-[ doesn't work as mentioned above.
In vim, I've always been curious why pressing the esc key causes the cursor to go back by one character (usually). For example if I've typed:
This is |
With the cursor being the |, after I have finished typing and press esc, the line will look like:
This is|
And to re-type from where I left off I would have to press a instead of i. Why is this the expected behavior in vim?
I found the following answer in this question on the Unix & Linux Stack Exchange:
In insert mode, the cursor is between characters, or before the first
or after the last character. In normal mode, the cursor is over a
character (newlines are not characters for this purpose). This is
somewhat unusual: most editors always put the cursor between
characters, and have most commands act on the character after (not,
strictly speaking, under) the cursor. This is perhaps partly due to
the fact that before GUIs, text terminals always showed the cursor
on a character (underline or block, perhaps blinking). This
abstraction fails in insert mode because that requires one more
position (posts vs fences).
Switching between modes has to move the cursor by a half-character, so
to speak. The i command moves left, to put the cursor before the
character it was over. The a command moves right. Going out of
insert mode (by pressing Esc) moves the cursor left if
possible (if it's at the beginning of the line, it's moved right
instead).
I suppose the Esc behavior sort of makes sense. Often,
you're typing at the end of the line, and there Esc can
only go left. So the general behavior is the most common behavior.
Think of the character under the cursor as the last interesting
character, and of the insert command as a. You can repeat
a Esc without moving the cursor, except that
you'll be bumped one position right if you start at the beginning of a
non-empty line.
Credits to the original author.
If you would like to edit this behavior, you could follow the advice from #ib. in this answer:
Although I would not recommend changing the default cursor mechanics,
one way of achieving the behavior in question is to use the following
Insert-mode mapping.
:inoremap `^
Here the Esc key is overloaded in Insert mode to
additionally run the `^ command which moves the cursor to the
position where it had been the last time Insert mode was left. Since
in this mapping it is executed immediately after leaving Insert mode
with Esc, the cursor is left one character to the right as
compared to its position with default behavior.
Unlike some other workarounds, this one does not require Vim to be
compiled with the +ex_extra feature.
I have discovered Vim a year ago and I am getting more and more addicted to it.
I remapped every key of my french dvorak-like bépo layout to stick to the qwerty layout for the normal mode, as described in "Reconfiguration totale des touches" on this page: https://bepo.fr/wiki/Vim, essentially because I learnt with Vim Adventures game.
It works very well:
For instance, yr remaps as cl : the command cuts the character to the right and enter insertion mode.
However, the vim status line displays y for one second before displaying c:
I changed my mapping from:
noremap y c
to this :
map <nowait> y c
without success.
Anyone knows if it is possible to display a remapped operator-pending key immediately, i.e. "c" in my case ?
This has nothing to do with vim-airline or any other plugin.
The pending operator is shown due to showcmd standard option. AFAIK, there's no way to change this, except to disable it completely (set noshowcmd), or to patch Vim's source code.
Instead of remapping every key combination, a simpler solution is to use langmap. This provides the additionnal benefit to show the remapped command key.
From :h langmap
This option allows switching your keyboard into a special language
mode. When you are typing text in Insert mode the characters are
inserted directly. When in Normal mode the 'langmap' option takes
care of translating these special characters to the original meaning
of the key. This means you don't have to change the keyboard mode to
be able to execute Normal mode commands.
To test it:
:set langmap=éw remaps é to w in normal mode.
:set showcmd displays w instead of é in the status line.
Now, my config is: http://vim.wikia.com/wiki/Example_vimrc
with additional two lines in it:
source $VIMRUNTIME/mswin.vim
behave mswin
my sample text is:
foo.bar
how can i select foo, then .bar using Ctrl+Shift+Right
and bar, then foo. using Ctrl+Shift+Left ?
Ctrl+Lelf and Ctrl+Right stop on dot char, like traditional editor, but when i use Ctrl+Shift+Arrows - it stops only on whitespaces.
vim version: 7.4
os: ubuntu 14.04
The Select-mode (which will be enabled by :behave mswin) only "simulates" some behaviors of MS-Windows like editors. Just these movements cursor keys, <End>, <Home>, <PageUp> and <PageDown> with the shift key are expanding/collapsing current selection.
From :help Select-mode:
Commands in Select mode:
- Printable characters, <NL> and <CR> cause the selection to be deleted, and
Vim enters Insert mode. The typed character is inserted.
- Non-printable movement commands, with the Shift key pressed, extend the
selection. 'keymodel' must include "startsel".
- Non-printable movement commands, with the Shift key NOT pressed, stop Select
mode. 'keymodel' must include "stopsel".
- ESC stops Select mode.
- CTRL-O switches to Visual mode for the duration of one command. *v_CTRL-O*
- CTRL-G switches to Visual mode.
From :help keymodel:
... Using a shifted special key starts selection ...
... Special keys in this context are the cursor keys, <End>, <Home>,
<PageUp> and <PageDown>. ...
Try to read about it: :help behave, :help Select-mode and :help keymodel.
But, I strongly recommend you to learn about the "real" vim movements and commands and disable :behave mswin. It is actually way more powerful.
In your case you could simply press veE to select first foo then foo.bar. Or if your intention is to select the whole foo.bar at once even simpler, press vW.
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.