Making inserting a single character in Vim an atomic operation - vim

I've long used this very useful shortcut in vim:
nmap <space> i <esc>r
this means that if I press spacef, for example, it will insert a single character f at the given position.
unfortunately, however, this is not atomic, ie, if I press spacef and then navigate somewhere else, then press ., I get the equivalent of rf, not spacef.
all this makes sense, but here's the question: is there a way of making this atomic, so that . will repeat the 'insert character' operation, and so that undo etc all treat it as one operation, too?

Awesome! Michael's answer pointed me to the plugin I needed to finish my plugin, which can now do what you want - I had been trying to figure out how to do this for ages!
1) Install Tim Pope's plugin
2) Install my plugin
3) Add a mapping to your .vimrc:
nnoremap <space> :<C-U>call InsertChar#insert(v:count1)<CR>

Does this work for you?
noremap <silent> <space> :exe "normal i".nr2char(getchar())<CR>

You might want to have a look at this plugin script. It may be possible to configure your map so it can be supported. Read the supporting docs
http://www.vim.org/scripts/script.php?script_id=2136

Sorry I can't provide a specific answer to your problem but I will note that I tend to use the . key when I have to reproduce quite a lot of commands (e.g. I want to insert f 5 or more times).
If that is the case here, I don't think the saving of using your macro is worth it. You save one keystroke by using your macro rather than ifesc and that operation is atomic so you could then . to your heart's content.
I would just use the non-macro version if I know I want to repeat it a lot.
P.S. You know I'm starting to like the <kbd> tag quite a bit :-)

Related

Is it possible to easily insert a single word in vim

I often want to insert a single word with vim. Is there a way to insert as many Chars as you want until you type a <Space> which then acts as an <esc>?
I know that a normal i with an <esc> doesn't take too long, but I would like to have such a command and the <esc> is quiet hard to reach.
You should consider the following
remap caps lock to esc or;
remap caps lock to control, and then use
the alias for esc which is control-[.
Otherwise, though this isn't quite what you're looking for, see this post for a possible approach, but also read Ingo Karkat's answer there for why it may not be such a great idea to make such mappings.
Please mention the most underrated <C-c>

repurpose default key in vim

I heard that there is no internal function to call when typing a key combo in vim, unlike emacs. So I want to repurpose Ctrl-A to ^ (like, nnoremap < C-A> ^); however, the original function of Ctrl-A is also attractive, so I want to map it to some other keys, say Ctrl-S. How can I do this the vim way?
This question might have been asked but I searched around and did not find anything close. Thanks in advance.
PS: the stupid vim-emacs war is spamming everywhere and nowhere can i find a real solution that makes a desired feature to work in another environment.
The following should do:
nnoremap <C-A> ^
nnoremap <C-A>A <C-A>
This works because the noremap tells vim to do not apply any other mapping, thus the rhs of the second mapping above is the default <Ctrl-A>.
You will notice that the first mapping will take a delay to execute, because vim waits a while to allow you to type the second mapping. Vim-FAQ 20.16 may help if this bothers you.
But I'd advice against changing the default mapping because, as explained here, vim has many default mappings that may seems silly when you start using it. When you understand it better you will have a hard time finding another key to map it or to get used to the old/default mappings.

Insert character without entering insert mode?

Sometimes I want to insert a # to comment out a line and test it quickly. Currently I do:
i#ESC:w
Is there something shorter I can do?
Although I agree with others that there are better ways to comment and uncomment code, it seems that people have gotten distracted and forgotten to actually answer the question.
This is my approach to inserting a single character:
:noremap <key> i <Esc>r
I tend to find that I need to replace, remove, or add single characters very often if I'm correcting typos, so (resp.) r, x, and whatever is chosen for <key> in the above become very handy.
Note that . is also particularly handy for this sort of task. It repeats the previous action.
Personally though, I only map this function to a valuable key when I'm doing a task where I use it frequently enough to justify occupying a prime spot on the keyboard (such as correcting typos), because really, it only saves one keystroke per use and that's only when <key> is not a combination, which of course limits availability.
I map a couple of things to my <leader> key (\ by default):
" # comment the current line
nnoremap <leader>d I#<ESC>
" block comment in visual mode
vnoremap <leader>c <ESC>'<O/*<ESC>'>o*/<ESC>V'<k
If you want to add a # to the start of a group of lines, then do this:
<ctl-v>
j (as many times as necessary
I#
<esc>
You could use a recording. From normal mode, type:
qlml0i#<press escape>`lq
Then to comment out a line, just press #l
Mapping in vim is so easy that I might do something like
:nmap CC I#<Esc>:w<CR>
on the fly. If I get used to it, then I will add it to my vimrc file.
:help key-mapping
:help usr_40.txt
Actually there is a plugin you might wanna take a look at:
http://www.vim.org/scripts/script.php?script_id=1218
It is specifically designed for that purpose.
I'm particularly fond of the tComment plugin. gcc to comment a line, repeat to uncomment, multiple lines, motions, etc.

Swap two characters atomically, so that it can be repeated with "."

The idiom for swapping two characters in Vim is xp.
See the help at :h 04.5, final paragraph, and Vim: how do I swap two characters?.
But very occasionally I need to do two or more swap operations in a row. I'm often surprised that what feels like a single operation to me, xp, is actually two operations to Vim. This makes it impossible to repeat xp with .. (Or atomic undo with u.)
Is there a way to swap two characters in a single operation that I can quickly repeat with .?
This isn't ideal, but if you store xp as a macro, it will be repeatable after you've executed the macro. So instead of xp, you're using, say #s (for swap). Then ## will repeat it. Not as nice as ., but it does work.
Edit: You know, I'm sure there's a way to accomplish this with some vimscript and tpope's repeat.vim. Sadly, my vimscript is not up to snuff. I got this far - maybe someone can correct where I'm going wrong?
fun! DoSwap()
:normal xp
silent! call repeat#set("\<Plug>Swap",1)
endfun
nnoremap <silent> <Plug>Swap :call DoSwap()<CR>
nmap <Leader>s <Plug>Swap
The problem with this is that once you enter \s, it does indeed swap the characters you're on, and it DOES repeat when you hit ., but it jumps to the beginning of the line first, which is not what you want. But I do think this can be done, I'm just not all the way there.
Here's an idea. Suppose the cursor is on the "y" of the word "oyxgen".
In normal mode, type
2sxy<Esc>
Now the word reads "oxygen". Find the next instance of the typo (fy) and repeat the change (.).
Too bad this works only for the specific swap "yx" to "xy", so this isn't the definitive solution.
Vimcasts.org has published an episode that addresses this very problem.
As #Jeremy guessed the solution is to use the repeat.vim plugin. Then simply add the following <Plug> mapping and key mapping to your vimrc.
nnoremap <silent> <Plug>Transpose xp:call repeat#set("\<Plug>Transpose")<CR>
nmap cp <Plug>Transpose
The mapping shown here uses cp. cp is the new xp, repeatable with . but otherwise exactly the same.
Now all that remains is getting used to it.

mapping # in vim

In my .vimrc I have mapped the #-key to a macro for commenting out/in lines of code.
Unfortunately # in vim already has a function - it searches backwards for the word beneath the cursor.
What I would now like to have is a way to map this functionality to another key-sequence (ideally I would like to have Control-* for that as * alone searches forward).
Does anyone know how to achieve this?
Many thanks!
Unfortunately, Ctrl + * cannot be used; I would propose \*; it's longer to type, but backwards searches are probably not that common.
:nnoremap <Leader>* #
Like Ingo Karkat said, mapping Ctrl+certain keys is impossible in vim. However, you can map Alt+8 instead:
noremap <A-8> #
I suggest Alt+8 instead of Alt+* because if you wanted to bend your hand in unnatural ways to press more than one modifier keys to perform a command, you would probably be using Emacs instead of Vim.
I use \+c for commenting and \+d for removing comments. The mappings are following :
:map \c <ESC>:s,^\(\s*\)[^/ \t]\#=,\1// <ESC>,e<CR>j$a
:map \d <ESC>:s,^\(\s*\)// \s\#!,\1<ESC>,e<CR>j$a
Above mappings are used in command mode. Taken from one answer on SO, which I am currently unable to find.

Resources