I'd count the number of space characters before the cursor at the moment
<cr> is hit and produce as many
<BS>. It can be done with
:inoremap <expr> <cr> substitute(matchstr(getline('.')[: col('.')-2], '\S\zs\s*$'), '.', "<bs>", 'g')."<cr>"
:inoremap <expr> <cr> repeat("<bs>", len(matchstr(getline('.')[: col('.')-2], '\S\zs\s*$')))."<cr>"
- As there is no movement/break (with
<esc>) in the flow of this solution, anything that is typed can be undone, redone , etc. However, if you start a new insert sequence to cut after a series of spaces, redoing the same insertion sequence with
. elsewhere is likely to remove too many characters.
\S\zs is a workaround when we're on en empty line and when each
&sw characters. In that case I should check
getline() result and do something smarter.
A version that behaves a little bit better regarding indented empty lines is the following:
let line = getline('.')
" TODO: set and reset &bs
if line =~ '^\s*$'
let nb = (virtcol('.') + 2*&sw-2) / &sw - 1
" echomsg "remove "virtcol('.').'/'.&sw.' -> '.nb
let nb = len(matchstr(line[: col('.')-2], '\s*$'))
let line = ''
return repeat("\<bs>", nb)."\<cr>".line
inoremap <expr> <cr> <sid>trim_ws_on_the_fly()
<CR>in insert mode? I’m having a hard time imagining that happening in a case where you wouldn’t delete the trailing spaces before pressing enter.