2

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

2 Answers 2

1

You can use let @x=substitute(strtrans(@a),'.*\zs^@',' ',''). The .* tries to match as many characters as possible, so that only the last "^@" is matched. \zs only replaces that '^@' and not the characters before it. As you only replace one match, you won't need the 'g' option. If you need to replace the last two, then you could run this function twice.

Sign up to request clarification or add additional context in comments.

Comments

0

Your approach of translating newlines via strtrans() is creative, but you can substitute them directly (matching them via the \n atom). You don't show the contents of s:NodeJSTranslate(), but I guess it's using system() to obtain the output, and having trailing newline(s) is a common problem. (My ingo-library plugin has a corresponding function ingo#system#Chomped() for this, too.)

let @x = substitute(@x, '\n\+$', '', '')

Additional critique

  • Use :normal! (with a !) to make the commands immune against remappings. This is especially important if you plan to publish your plugin for others; you'll never know what users have mapped.
  • You can combine the deletion and paste in a single command: :normal! gv"xp. By using the expression register, you can even avoid clobbering another register (@x):
:let outp = substitute(outp, '\n\+$', '', '')
:execute "normal! gv\"=outp\<CR>p"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.