Your original substitution is this (I replaced the delimiters / with # for reading):
%s
And here is my suggested reverse replacement (take a deep breath ...):
%s
Suppose the matched string ( submatch(0) ) contains n whitespace characters. What I'm doing is calculating half that number ( n/2 = string(float2nr(len(submatch(0))/2)) ) and then extracting a lot of characters from the match (essentially matchstr(n/2) ). This ensures that we get exactly half the space we started with (which can be a mixture of spaces and tabs).
If you know that a space will contain ONLY spaces or ONLY tabs, this can be somewhat simplified, for example:
%s#^\s*#\=repeat(" ",indent(".")/2)#
In another note, I would recommend reformulating your maps to make them more readable and therefore easier to modify and maintain. My approach would be to define two functions:
function! DoubleWS() let pos = getpos('.') let reg = getreg('@') exe '%s/^\s*/&&/e' call setreg('@',reg) call setpos('.',pos) endfunction function! HalfWS() let pos = getpos('.') let reg = getreg('@') exe '%s#^\s*#\=matchstr(submatch(0),"^.\\{".string(float2nr(len(submatch(0))/2))."\}")#e' call setreg('@',reg) call setpos('.',pos) endfunction
Note that the get/set pos/reg functions are a much more reliable way to maintain cursor position and registration. Then you can map these functions as you like:
nnoremap <silent> <leader>iw :call DoubleWS()<CR> nnoremap <silent> <leader>rw :call HalfWS()<CR>
Hope this helps!
source share