I am writing a function to reformat a visual selection:
function! FormatText() range
" Calling this function has ended visual mode, so it must be started
" again before the selection can be yanked into the unnamed register.
normal! gvy
let selection = @"
echomsg 'Z'.selection.'Z'
let cmd = 'sort'
let output = system(cmd, selection)
echomsg 'X'.output.'X'
silent exe "'<,'>s/.*/" . output . "/"
endfunction
The examination of @" value reveals that spaces and new lines are randomly replaced by ^@.
Any idea why this is happening and how to handle this? Is there a better approach to get the context of the visual selection?
UPDATE: After the feedback I know now that ^@ is a new line replacement. I also provided the actual function. I have to withdraw the statement about spaces, only new lines are replaced by ^@. The spaces were replaced by external program because it could not handle 0 bytes. To eliminate the external program effect I am using the sort to illustrate what's happening.
Debugging steps:
open a file with the following content: z line a line
visually select both line and trigger the function by the following mapping: vnoremap f :call FormatText()
echomsg output (works as expected) Zzline^@a line^@Z Xaline^@z line^@X
The selection in file changed to: aline^@z line^@ aline^@z line^@
I have more questions now.
a) Why is the selection contents doubled? Is this approach wrong:
silent exe "'<,'>s/.*/" . output . "/"
I tried \%V
silent exe "'<,'>s/\\%V.*\\%V/" . output . "/"
but the result is the same.
b) Is there a way to get the visual selection as it is, without transformation?
c) How does built-in gq with 'formatexpr' works? Does it convert ^@ to new lines first? Would it be awkward to do it for all type of file formats?
:echo
command.silent exe "'<,'>s/\\%V.*\\%V./" . output . "/"
but it does solve the new line problem. Thegvp
is probably a better solution.systemlist
instead ofsystem
. It should do the right thing. (Also, please avoid posting multiple questions in a single Question.)