4

I am quite newbie in vim. What I want to achieve is that vim will return the output of a python function in my text file. The idea is that I select a part of text and press F5 and get the output. The complication is that this function is part of a library and I have to import it. I tried this

command MyPythonFunction execute "!python from Bio.Seq import reverse_complement; reverse_complement(%)"
map <F5> :MyPythonFunction<CR>

and I get "no range allowed"

2 Answers 2

2

Selected lines are passed to stdin of the command. So read it using sys.stdin.read()

fun! ReverseComplement()
    exec ":'<,'>! python -c \"import sys, Bio.Seq; print Bio.Seq.reverse_complement(sys.stdin.read().rstrip())\""
endfun

vnoremap <F5> :call ReverseComplement()<CR>

EDIT

pass a part of a line:

vnoremap <F5> d:let @a=system('python -c "import sys, Bio.Seq; sys.stdout.write(Bio.Seq.reverse_complement(\"' . @" . '\"))"')<CR>"aP
  • d -> delete selected part. side effect: content of register " changed.
  • @": content of register " (cut contents)
  • .: binary operator that concatenate strings.
  • let @a = system(..): Execute external command, and save its output to a register.
  • "aP: Paste content of a register before current cursor position.
Sign up to request clarification or add additional context in comments.

5 Comments

Tx!!! But I still have the same problem as in the solution above. stdin gets the full line and not just the selection and stdout writes to the full line not the selection
@Gioelelm, I tested above vim script. It only replaced the selected line. I used V command to select lines.
yes I see that it replace only the selected line but that is not what I want... what I want is to reverse complement only a part of a line not the full line. Is it possible?
Thank you a lot!!!! Super good! Could you explain the code a bit? Can I change this structure for any vim function? Something like: vnoremap <F5> d:let @a=ReverseComplement(a)<CR>"aP
@Gioelelm, I added explanation.
1

First of all, you are going to need** write your python parts in such a manner that the data is read from stdin and then output to stdout. You can then apply your code in following style:

fun! DoMyPythonThing() range
    exec ":'<,'>! python ./path/to/your/script.py"
endfun

vnoremap <F3> :call DoMyPythonThing()<CR>

The idea behind ex's command :! is that you give it an executable program, and vim pipes the visualized text to it and replaces the region with the ouput of the program.

Note the range there in the function definition. Note about the mapping that we restrict ourselves in visual mode mappings only. If you like to wave the mouse as well, consider mapping in selection mode as well.

**) Well, it's possible to write in-vim python to perform this, but that's harder to test and you went with the external-program route by calling ! anyway.

2 Comments

Than you a lot it worked perfectly!!! Still for some reason stdin gett the full line and not just my selection. How do I fix it?
@Gioelelm: that is, I believe, a limitation in the system. Only complete lines in ranges I'm afraid.

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.