Запуск фоновых задач из vim

При разработке проекта удобно всегда иметь актуальную документацию по методам. После добавления нового метода и сохранения файла приходится вручную запускать скрипт обновления документации.

У vim есть возможность выполнять команды по собственным событиям, но нельзя просто выполнять команды фоном без блокировки работы.

Вспомогательная прога

В Linux есть средство для организации взаимодействия между разными программами — D-Bus. Vim может с помощью dbus-send передавать сигналы во вспомогательную программу, которая в свою очередь и будет выполнять скрипт обновления документации.

Есть готовый пример на python-е для выполнения функций при получении сигнала, адаптируем его для выполнения внешних команд:

import gobject

import dbus
import dbus.service
import dbus.mainloop.glib

import os

class Runner(dbus.service.Object):

	@dbus.service.method("info.gnedov.Runner",
	                     in_signature='s', out_signature='')
	def Execute(self, cmd):
		os.system(cmd)

	@dbus.service.method("info.gnedov.Runner",
	                     in_signature='', out_signature='')
	def Exit(self):
		mainloop.quit()

if __name__ == '__main__':
	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

	session_bus = dbus.SessionBus()
	name = dbus.service.BusName("info.gnedov.Runner", session_bus)
	object = Runner(session_bus, '/Runner')

	mainloop = gobject.MainLoop()
	print "Running"
	#print usage
	mainloop.run()

# vim: set ts=4 sw=4 noet

Запуск:

python runner.py

Эту команду можно разместить в автозапуске вашей среды рабочего стола

Теперь чтобы передать команду на выполнение воспользуемся программой dbus-send:

dbus-send --print-reply --dest=info.gnedov.Runner \
/Runner info.gnedov.Runner.Execute string:"xterm &"

Настройка vim

Есть событие “BufWritePost”, которое срабатывает при сохранении. Им и настрою обновление документации с помощью vim-скрипта специфичного для проекта:

autocmd BufWritePost *.js  execute("silent !dbus-send --print-reply --dest=info.gnedov.Runner /Runner info.gnedov.Runner.Execute string:\"/path/to/project/update-client.sh &\"")
autocmd BufWritePost *.php execute("silent !dbus-send --print-reply --dest=info.gnedov.Runner /Runner info.gnedov.Runner.Execute string:\"/path/to/project/update-server.sh &\"")