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>"
" 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>"
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>"
silent exe "normal! r".nr2char(getchar())