There is no builtin solution. And I fail to find a one liner. If I put eatchar()
directly in a mapping, it'll see what follows in the mapping instead of what the user will type.
The following isn't very ergonomic, but it'll work:
function! s:repl1() abort
let c = nr2char(getchar())
exe "normal! ciw".c."\<esc>"
endfunction
" use anything you wish instead of "µ" to trigger the mapping
nnoremap <silent> µ :call <sid>repl1()<cr>
EDIT: See Daniel Kaplan's answer for a oneliner
BTW, it's also possible to define our own operator (:h g@
), so instead of µ
, we could type µiw
(for the current word), µw
(from the cursor position to the end of the current word), and so on.
function! s:opfunc(type) abort
let motion = a:type == 'line' ? "'[v']" : '`[v`]'
silent exe "normal! ".motion."c".nr2char(getchar())."\<esc>"
endfunction
nnoremap <silent> µ :set opfunc=<sid>opfunc<cr>g@
Note that, I've still haven't found how to force a redraw where we see we're in REPLACE-mode. The best I can come up with is the following, inspired by Daniel Kaplan's solution.
silent exe "normal! ".motion."c¤\<esc>"
redraw
silent exe "normal! r".nr2char(getchar())
,x
(if I mapped the script to,
andx
is the replacement letter) and would definitely help -- Just to mention, you may also want to doinoremap jk <esc>
so it won't feel too much a burden to exit from insert mode.