3

I want to automate certain text manipulation (essentially writing a plugin), but for easiness, I wish to minimize the use of Vim script whenever possible. This is because, indeed it is much harder to look for a documentation for writing something in Vim script, than in a well-established script language in any sort, Python, Lua, and so on.

Thus I am not sure what the best method is, to call an external binary or script that modifies the current buffer. For concreteness, let me say that I want to remove all newlines in the current buffer. Surely this can be done by a simple replacement, but for sake of illustration let me implement it in Python.

remove_newline.py:

#!/usr/bin/env python

import os # to get path name
import sys # to get CLI arguments

srcPath = os.path.realpath(__file__)
dirPath = os.path.dirname(srcPath)
dataPath = dirPath + "/" + sys.argv[1]

myFile=open(dataPath,'r')
content = myFile.read()
myFile.close()

content = content.replace("\n", "")

myFile=open(dataPath,'w')
myFile.write(content)
myFile.close()

And when editing, say, test.txt, run this line in Vim: (of course I can choose a shorter name)

:cabbrev remove_newline :! ./replace.py %

Now I can simply run

:remove_newline

I see several problems in this approach:

  1. The buffer has to be saved in advance, otherwise there is a warning

    W12: Warning: File "test.txt" has changed and the buffer was changed in Vim as well
    See ":help W12" for more info.
    [O]K, (L)oad File, Load (A)ll, (I)gnore All: "test.txt" "test.txt" [noeol] 1L, 5C
    

    Such warning is understandable, but it is cumbersome to save file every time before I hit my shortcut. Calling an external script this way is not seamlessly integrated with the i/o action of buffer, but considered an alien action.

  2. I want to open a new tab that temporary holds error message, but don't know how to connect the std i/o into a new Vim buffer.

  3. I want to select text and, upon hitting my shortcut, only replace selected text. But I don't know how to specify location selected in Vim, into called script.

Or maybe my intention is not suitable to implement in Vim? I know very little about plugins. It seems Youcompleteme is written in Python, but it remains overwhelming of me to find where Vim "communicates" with Python in the Repo (which is all I have to know for present purpose).

1 Answer 1

4

You can filter (part of) a buffer through an external command by using :{range}!{command}. The range of the buffer written to the external command is replaced by the output of the command.

If you rewrote your Python script to read from stdin and write to stdout, then you would just run :%!./replace.py or visually select a few lines and use :'<,'>!./replace.py.


As far as your specific example, you can do this using standard tools.

:%!tr -d '\n' will delete all newlines.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.