Vim exit Insert mode with some key press - vim

I have reassigned ; to : in Vim. I am constantly saving my code using :w. When I am in the insert mode, after making some changes, due to my muscle memory, I type ;w to save the document, but it adds ;w text in the code. Is it possible to assign ;w in insert mode to exit and save the document. If there is a better method, please let me know.

:inoremap ;w <esc>:w<cr>i save buffer and return to insert mode
:inoremap ;w <esc>:wq<cr> save and close buffer (exit vim if buffer only one).

You can remap : and ; at the OS level, and just get used to it. I started that some months ago and the adjustment was fairly smooth. Now I love it. Not sure what OS you’re on, but I’m sure there’s a solution for any. In X, you’d use xmodmap. In my ~/.xinitrc I have (among many remappings):
# Swap ; and :
xmodmap -e "keycode 47 = colon semicolon"
Use xev to see what exactly your keycodes are.

Related

Vim's "hit-enter" mode. Using ; of `:map ; :` without clearing displayed contents.

Do any maps work from hit-enter mode? Reading :help hit-enter, it seems the only way to continue writing commands without redrawing clearing the screen, is to start a command with :.
But there we read:
-> Press ':' or any other Normal mode command character to start that command.
Why doesn't nnoremap ; : apply? (What are "other Normal mode command character[s]"?) I'd like to quickly start a new command without losing the displayed contents from the previous command. I'd also like to be able to use the leader key without losing the displayed contents.
For instance, try ;ls<Ret>, then ; or your <leader> key.
It's not that bad, I can use : after, just wondering if I could get more control in hit-enter-mode.
nnoremap gb :ls<CR>:b<Space>
Is the "canonical" way to do what you want.

How can I map these five keyboard actions to a single key in Vim?

I want to map a key so that it will do the following actions in Vim. Suppose I am editing a file; I want it set up so that if I press F2, I will accomplish the same thing I would if I did the following:
press ESC
type colon (:)
type w
press Enter
press ESC again
type i to go back to insert mode
Is this possible?
Yes it's possible, but it doesn't do what you want if the cursor is at the end of line.
To get file saved on F2 in insert mode, use the following mapping:
:imap <F2> <C-O>:w<CR>
Literal answer: Yes. You can use this:
:inoremap <F2> <Esc>:w<CR>I
but it won’t do exactly what you want (the cursor will be at the wrong place).
Anton beat me to the less literal (but correct) answer.
The best answer, though, is this: Don't use Vim incorrectly. You should never spend so much time in insert mode that you need a shortcut to get out of it, save the file, and then get back in. With all other editors, you’re in “insert mode” all the time, and only temporarily pop into a menu or dialog or whatever; in Vim, you should learn to reverse this. Only pop into insert mode to edit or add something; never use arrow keys to move the cursor while in insert mode; spend the majority of your time in command (normal) mode, and after a bit of adjustment to the new paradigm, you will find that your editing speed has increased.
Writing the mapping is almost easier than your description.
First, you need to determine from which mode the mapping will be used, because that determines what :map variant you will use. You’ll probably want to use this in insert mode, so you’ll use :inoremap.
The format of the mapping is:
:..noremap {keys} {rhs}
You want <F2> (see :help key-notation) for keys. For {rhs}, just concatenate the keys listed in your description.
To persist the mapping, add it to ~/.vimrc. (See :help vimrc.)
P.S. The alternative given by Anton Kovalenko is probably better for what you’re trying to do, but here I’ve given you the general recipe for future key mappings.

Insert a word in normal mode as compared to executing a command in insert mode

I have discovered that it is possible in insert mode to execute a single command and return to insert mode by using Ctrl-O.
What about the possibility to insert a single word while in normal mode ?
I could, of course, switch to insert mode, write the word, escape and go back to normal mode.
But I wondered if it was possible to map a sequence (e.g. Ctrl-K) allowing without leaving normal mode to quickly add a single word at the cursor position ?
I tried mapping a function with a prompt (cf. question 11567596 - Ingo Karkat's answer - and Wikia tip 1616) but failed : the word was appended at the end of the line...
My best advice is to embrace insert mode; it's the vi way TM.
Seriously, I also had the idea of creating mappings that allow me to enter a word / sentence / whatever, and then automatically return to normal mode. But...
Whether you use the input() from romainl's answer, or a more elaborate approach (e.g. with a CursorMovedI hook), you have to press Enter or another key to indicate that you're done. That's no better than pressing Esc to leave insert mode the normal way!
You just make things more complex: you spend valuable (short) key sequences for it, you have to spend brain cycles to decide between both approaches, your muscle memory must learn to ways to enter text, and these specials aren't available in other vi-modes (e.g. in Bash).
So, I think it's just not worth it.
This simple function works, here:
function! InsertWord()
let l:user_word = input("Type something then hit ENTER: ")
execute "normal i".l:user_word
endfunction
command! InsertWord call InsertWord()
nnoremap <C-k> :InsertWord<CR>
The whole thing could probably be shortened to a one-liner, though, but I like it like that.

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.

Pasting from the clipboard and automatically toggling ":set paste"

When I paste things from the clipboard, they're normally (always) multilined, and in those cases (and those cases only), I'd like :set paste to be triggered, since otherwise the tabbing will increase with each line (you've all seen it!).
Though the problem with :set paste is that it doesn't behave well with set smartindent, causing the cursor to jump to the beginning of a new line instead of at the correct indent. So I'd like to enable it for this instance only.
I'm using Mac, sshing to a Debian machine with Vim, and thus pasting in Insert mode using cmd + v.
I don't use a mac, but I believe I have the prefix right here: <D-v> should mean cmd-v. For insert mode:
:imap <D-v> ^O:set paste<Enter>^R+^O:set nopaste<Enter>
or really, just do this:
:imap <D-V> ^O"+p
The ^O and ^R are literal control-O and control-R, which you can type with ^V^O (control-v control-o) and ^V^R (control-v control-r). Control-O in insert mode allows you to execute one command then return to insert mode; here you can use it to put from the clipboard register.
This worked for me when I tested them mapped to a different key, so you should be all set.
There's no need to map anything when not in insert mode; you can just use "+p.
I have the following in my .vimrc:
inoremap <S-Insert> <ESC>:setl paste<CR>gi<C-R>+<ESC>:setl nopaste<CR>gi
gi is to start insert mode in the same position as where insert mode was stopped last time in the current buffer.
Update:
Jefromi posted a better solution. I have tinkered it a bit
inoremap <S-Insert> <ESC>"+p`]a
It inserts clipboard text and places the cursor right after it.
You're right in that you should only enable 'paste' when you need it. It does more than just affect indenting. You can read everything that it affects in its documentation. A related option that is very useful to ease the use of 'paste' is 'pastetoggle'.
If you were using X-forwarding and a terminal that can properly communicate mouse actions, you could also take advantage of the 'mouse' option. With :set mouse=a, Vim is made aware of what the mouse is doing and therefore won't perform automatic indentation when it receives a multi-line paste via a middle-button mouse click.
Even without the mouse capability, X-forwarding could help because Vim will do the same thing when manually pasting from the clipboard or selection registers ("+ and "* respectively).
This ought to be solvable with a Vim script. (I hate Vim scripting, so it would have to be a much more serious infliction to cause me to solve it myself.) Even with iTerm2's "paste slowly" mode, the default is to break the data to be pasted into 16 byte chunks and send one every 0.125 seconds. Therefore, you should be able to programmatically detect a 16 byte chunk of "keystrokes" and do something about it.
In pseudocode that would look like:
if too_fast_too_be_human():
set('pastemode', True)
else
set('pastemode', False)
# where either
def too_fast_too_be_human
char_threshold = 16
return len(input_buffer) > char_threshold
# or
def too_fast_too_be_human
static byte_times = []
char_threshold = 16
time_threshold = 0.125
byte_times.append(now())
while(len(byte_times) > char_threshold):
byte_times.unshift()
return (byte_times[-1] - byte_times[0]) < time_threshold
There are weaknesses to that, but it would work for most cases.
We can paste (insert mode) without messing up indentation using
Ctrl-r Ctrl-o Register
Ctrl-r Ctrl-o +
Ctrl-r Ctrl-o *
Ctrl-r Ctrl-o 0
CTRL-R CTRL-O {0-9a-z"%#*+/:.-=} *i_CTRL-R_CTRL-O*
Insert the contents of a register literally and don't
auto-indent. Does the same as pasting with the mouse
"MiddleMouse". When the register is linewise this will
insert the text above the current line, like with `P`.
Does not replace characters!
The '.' register (last inserted text) is still inserted as
typed.

Resources