I am trying to create a simple vim plugin that translates the word or phrase that is selected in visual mode. I have the plugin working for the most part, with one annoying exception, the translated string is always pasted on the next line from where the selection was made. I've come to understand that is is because the string was not created in a "word-wise" fashion.
My question is how do I create a string in vimscript that contains word-wise data, or alternately, how do I paste a regular string in the middle of a line?
I think I solved the first part of the question. Vim encodes new lines as NULL characters when the lines are yanked. The strtrans() function can be used to convert the NULL characters into ^@ codes in the register. Then the substitute() function can be invoked to search for and replace the null characters with spaces. Once the trailing NULL character is removed, the register can be pasted inline with p, just as if it was yanked with yw.
So now my question becomes how do I substitute only the last ^@ in the string?
My function currently looks like:
function! s:BingTranslate(...)
let s:query = a:000
let outp = ""
"call sub translator
let outp = s:NodeJSTranslate(s:query)
"replace with translation
let @x = outp
"remove null characters
let @x=substitute(strtrans(@x),'.*\zs^@',' ','g')
"re-select area and delete
normal gvd
"paste new string value back in
normal "xp
return outp
endfunction
答案 0 :(得分:0)
您通过strtrans()
翻译换行符的方法很有创意,但是您可以直接替换它们(通过\n
原子进行匹配)。您没有显示s:NodeJSTranslate()
的内容,但是我想它是使用system()
来获取输出的,而尾随换行符是一个常见的问题。 (我的ingo-library plugin对此也具有相应的功能ingo#system#Chomped()。)
let @x = substitute(@x, '\n\+$', '', '')
:normal!
(带有!
)使命令免于重新映射。如果您打算为他人发布您的插件,这尤其重要。您将永远不会知道用户已经映射了什么。:normal! gv"xp
。通过使用表达式寄存器,您甚至可以避免破坏另一个寄存器(@x
)::let outp = substitute(outp, '\n\+$', '', '')
:execute "normal! gv\"=outp\<CR>p"