I came up with the following. It basically is a pair of typing-saving canned s/// command which replaces all consecutive horizontal whitespace with a given number of linebreaks throughout the buffer, in a range or in the current visual selection, in the second version restricted to horizontal whitespace after sentence-final punctuation.
" Command :Wl [{N}] (*W*ord *l*ine)
" Replace consecutive horizontal whitespace in buffer/range/selection
" with N line breaks (Default: the number in variable g:Wl_line_breaks)
let g:Wl_line_breaks=1
:com! -range=% -nargs=? Wl exe printf('<line1>,<line2>s/\s\+/%s/g',repeat('\r', (<q-args> ? <q-args> : g:Wl_line_breaks)))
" Explanation:
" -range=%
" The command operates over the whole buffer or over a given range, which
" may be visual.
" -nargs=?
" The command takes an optional argument.
" exe printf(...)
" Constructs a string containing the actual command, then executes this
" string as a command.
" (<q-args> ? <q-args> : g:Wl_line_breaks)
" Compute N: use the argument if there was one (and it was non-zero)
" or else use the number which is the value of the global variable
" g:Wl_line_breaks, which must be defined.
" It is up to you to make sure that the argument and the variable value
" are positive integers!
" repeat('\r', N)
" Construct a string which will be interpolated as N linebreaks.
" The string doesn't actually contain linebreaks, but they will "become"
" line breaks when the command is executed.
" s/\s\+/%s/g
" Here %s will be replaced with N linebreaks,
" so if N is 1 it's s/\s+/\r/g
" and if N is 4 it's s/\s+/\r\r\r\r/g
" so basically replace all consecutive horizontal whitespace
" with the desired number of linebreaks.
" Command :Sl [{N}] (*S*entence *l*ine)
" Replace consecutive horizontal whitespace *after a ./?/!*
" in buffer/range/selection with N line breaks (Default: the number in variable g:Sl_line_breaks)
let g:Sl_line_breaks=1
:com! -range=% -nargs=? Sl exe printf('<line1>,<line2>s/[.?!]\zs\s\+/%s/g',repeat('\r', (<q-args> ? <q-args> : g:Sl_line_breaks)))
" Explanation:
" This is basically the same as above, but requires that the horizontal
" whitespace is preceded with a "." or "?" or "!", and it has its own
" variable for the default value of N.
" Mappings to execute :Wl/:Sl (without argument) over buffer/selection
nor Wl :Wl<cr>
nor Sl :Sl<cr>