Processing vim buffers through an external program on save, is a technique that
is probably in use, and that I have not found documented anywhere, so here we
go. Skip to the details for the entertaining example.
I wanted to integrate
egt with
TaskWarrior so that every time I am editing an egt
project file in vim, if I write a line in a certain way then a new taskwarrior
task is created. Also, I have never written a vim plugin, and I don't want to
dive into another rabbit hole just yet.
Lynoure brought to my attention that
taskwiki processes things when the file
is saved, so I thought that I can probably get a long way by piping the file
from vim into egt and reading it back before saving.
I created a new
egt annotate command that reads a project file, tweaks it,
and then prints it out; I opened a project file in vim; I typed
:%!egt annotate %:p --stdin and saw that it could be done.
I find the result quite fun: I type
15 March: 18:00-21:00 in a log in egt,
save the file, and it becomes
15 March: 18:00-21:00 3h. I do something in
TaskWarrior, save the file in egt, and the lines that are TaskWarrior tasks
update with the new task states.
Details
Here's a step by step example of how to hook into vim in this way.
First thing, create a filter script that processes text files in some way.
Let's call this
/usr/local/bin/pyvimshell:
#!/usr/bin/python3
import sys
import subprocess
for line in sys.stdin:
print(line.rstrip(), file=sys.stdout)
line = line.strip()
if line == "$":
pass
elif line.startswith("$"):
out = subprocess.check_output(["sh", "-c", line[1:].strip()], universal_newlines=True)
sys.stdout.write(out)
if not out.endswith("\n"):
sys.stdout.write("\n")
print("$ ", file=sys.stdout)
Then let's create a new filetype in
~/.vim/filetype.vim for our special magic
text files:
if exists("did_load_filetypes")
finish
endif
augroup filetypedetect
au! BufNewFile,BufRead *.term setf SillyShell
augroup END
If you create a file
example.term, open it in vim and type
:set ft it
should say
SillyShell.
Finally, the hook in
~/.vim/after/ftplugin/SillyShell.vim:
function! SillyShellRun()
:%!/home/enrico/dev/egt/pyvimshell
:$
endfunction
autocmd BufWritePre,FileWritePre <buffer> :silent call SillyShellRun()
Now you can create a file
example.term, open it in vim, type
$ ls, save it,
and suddenly you have a terminal with infinite scrollback.
For egt, I actually want to preserve my cursor position across saves, and egt
also needs to know the path to the project file, so here is the egt version of
the hook:
function! EgtAnnotate()
let l:cur_pos = getpos(".")
:%!egt annotate --stdin %:p
call setpos(".", l:cur_pos)
endfunction
autocmd BufWritePre,FileWritePre <buffer> :silent call EgtAnnotate()
I find this adorably dangerous. Have fun.