4

I have a working prototype for some kind of linux-based neovim-app. Sole functionality is "vsplit if 'k' is pressed". It is based on tarruda's nvim-terminal-edit-py.

It is started through start_nvim.sh:

#!/bin/bash
NVIM_LISTEN_ADDRESS='/tmp/nvim' /usr/bin/nvim &
./myapp.py

myapp.py is

#!/usr/bin/env python
import os, sys, time, subprocess
from neovim import attach

tf = '/tmp/nvim'

env = dict(os.environ)
env['NVIM_LISTEN_ADDRESS'] = tf

#os.execvpe("nvim", ["nvim"], env)
#subprocess.Popen(["/usr/bin/nvim"], env=env)
#subprocess.call(['/usr/bin/nvim', '&'], env=env)

nvim = attach("socket", path=tf)

def key_subscribe(key, to):
    cid = nvim.channel_id                                                                                                               
    nvim.command( ('nnoremap <silent> <buffer> %s ' + ':call rpcnotify(%d, "keypress", "%s")<cr>') % (key, cid, to))


def _request_cb(*args):
    pass


def _notification_cb(*args):
    nvim.command('vsplit')


def _setup_cb():
    key_subscribe('k', 'up')


nvim.run_loop(_request_cb, _notification_cb, _setup_cb)

How to start /usr/bin/nvim from within myapp.py, so that start_nvim.sh is not necessary?

I did try various things.

Uncommenting the respective line in myapp.py and directly executing ./myapp.py:

execvpe does start nvim, but if I press k no vsplit is triggered.

Popen and call yield

Traceback (most recent call last):
  File "./myapp.py", line 18, in <module>
    nvim = attach("socket", path=tf)
...
FileNotFoundError: [Errno 2] No such file or directory

Obviously, Popen/call didn't pass /tmp/nvim to nvim.

2
  • Did you tried a mapping like :nmap k :sp<CR>?
    – SibiCoder
    Jun 24, 2016 at 3:08
  • I actually did something very similar here. I ran into lots of problems that took me a while to figure out, including this exact one. Feel free to look through that for inspiration, how to get around some common problems.
    – DJMcMayhem
    Jun 24, 2016 at 4:50

1 Answer 1

3

Your problem is that you're starting a Neovim subprocess and it's blocking before processing the rest of your script. When you quit Neovim, the rest of the script executes well after the file socket has outlived its use to Neovim.

You will need to start it from a thread so that the rest of the script can execute.

#!/usr/bin/env python
import os
import time
import threading
import subprocess

from neovim import attach

tf = '/tmp/nvim'


def start_neovim():
    env = dict(os.environ)
    env['NVIM_LISTEN_ADDRESS'] = tf
    subprocess.call(['/usr/bin/nvim'], env=env)


t = threading.Thread(target=start_neovim)
t.daemon = True
t.start()

# Give Neovim time to start
time.sleep(1)

nvim = attach("socket", path=tf)


def key_subscribe(key, to):
    cid = nvim.channel_id
    nvim.command(('nnoremap <silent> <buffer> %s ' + ':call rpcnotify(%d, "keypress", "%s")<cr>') % (key, cid, to))


def _request_cb(*args):
    pass


def _notification_cb(*args):
    nvim.command('vsplit')


def _setup_cb():
    key_subscribe('k', 'up')


nvim.run_loop(_request_cb, _notification_cb, _setup_cb)

I hope you're just doing this as an exercise. Configuring key bindings using the RPC interface is a little silly considering you still have to use Vim's language to do it.

The more common approach is to use .vim scripts to setup the keybindings and API, then use Python for things that aren't practical to do in Vim such as networking or long running asynchronous work.

2
  • I need to open several files at the same time, e.g. <F1> opens all the text files concerning class 5, <F2> opens all those belonging to class 6... I need to map and unmap keys several times. The appriopriate modell would be a finite state machine which would be kind of hard in .vim-file, I suppose. Thanks for your help.
    – Markus
    Jun 24, 2016 at 8:43
  • 1
    @Markus Glad I could help. But, why not post a question regarding what you just explained?
    – Tommy A
    Jun 24, 2016 at 14:04

Your Answer

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

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