Reputation: 393
I have a mapping nnoremap <leader>l i<space><esc>
that inserts a space while staying in a normal mode, and the mapping is dot-repeatable. However, the cursor stays where it was and the space "expands" to the right of the cursor.
I want to have a mapping that does the same but moves the cursor along, e.g.
nnoremap <leader>h i<space><esc>l
I love breaking sequences of characters with a space from normal mode and I want to decide at will if the cursor should stay or move (using either h
to move the cursor along or l
to move the text to the left while leaving the cursor where it is).
None of the tricks with i
or a
or <C-o>
seems to work and this is an expected behavior.
Is there any clever hack to accomplish dot-repeatability using nnoremap
only? It should also work if I am at the end of the line.
I can probably re-phrase it like this: I want to have functionality similar to X
and x
that deletes a single character before or at the cursor, but instead of deleting a character I want to insert a <space>
before or at the cursor (not after the cursor as with a
). And it should be dot-repeatable and take counts. Preferably a mapping that does not use more than a single line in the .vimrc
and does not require any plugins. And I don't want to change the behaviour of <esc>
(or i
, whichever is responsible for moving the cursor when one leaves the insert mode) that moves a cursor one character to the left.
Edit 1:
Dot-repeatable nnoremap <leader>l i<space><esc>
does this:
<leader>l...
AAAAAAAAAA[B]BBBBBBBB
AAAAAAAAAA[ ]BBBBBBBBB
AAAAAAAAAA[ ] BBBBBBBBB
AAAAAAAAAA[ ] BBBBBBBBBB
And I want a dot-repeatable <leader>h
that would do this:
<leader>h...
AAAAAAAAAA[B]BBBBBBBB
AAAAAAAAAA [B]BBBBBBBB
AAAAAAAAAA [B]BBBBBBBB
AAAAAAAAAA [B]BBBBBBBBB
Edit 2:
The workaround mentioned in reply by @romainl does the trick:
function! s:insspace(...)
if a:0
" perform operation
execute 'normal' v:count1.'i '."\<esc>".'l'
else
" set up
let &operatorfunc = matchstr(expand('<sfile>'), '[^. ]*$')
return "g@\<space>"
endif
endfunction
nnoremap <silent><expr> <leader>h <sid>insspace()
Can someone explain how it works? I am a beginner in vim...
Upvotes: 2
Views: 235
Reputation: 12950
Maybe I did not understand your question well enough, but for me this does the trick:
:nnoremap <leader>h i<space><esc>w
Rationale: Insert space, after <ESC>
go one left, so the cursor stays on the space, use w
to get to the next word boundary.
Is that what you want? I can now do 5\h
and it stays at the current position while inserting spaces to the left.
Upvotes: 0
Reputation: 196751
Given the string below and assuming the cursor is on the -
:
lorem-ipsum
^
There are various easy and repeatable ways to insert a space after the -
and leave the cursor on the space:
a <Esc>
s<C-r>" <Esc>
lorem- ipsum
^
The two macros above…
But this is precisely the latter behaviour that prevents us from doing the same in the other direction without a motion either before or after the insertion.
Without motion, the operation is "dot-repeatable" but the cursor is left on the -
:
i <Esc>
a <Esc>
s <C-r>"<Esc>
lorem -ipsum
^
With motion, the cursor is left on the space but the operation is not "dot-repeatable":
i <Esc><Left>
<Left>a <Esc>
s <C-r>"<Esc><Left>
lorem -ipsum
^
The workaround is a bit contrived but nifty.
Upvotes: 2