Skip to content

Instantly share code, notes, and snippets.

@rf-
Last active December 9, 2024 06:07
Show Gist options
  • Save rf-/33fc88d3071f4254b80e to your computer and use it in GitHub Desktop.
Save rf-/33fc88d3071f4254b80e to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import pynvim, os, re, sys, time
# Get a list of buffers that haven't been deleted. `nvim.buffers` includes
# buffers that have had `:bdelete` called on them and aren't in the buffer
# list, so we have to filter those out.
def get_listed_buffers(nvim):
return set(buf.number for buf in nvim.buffers \
if nvim.eval('buflisted(%d)' % buf.number))
# For now, treat all arguments that don't start with - or + as filenames. This
# is good enough to recognize '-f' and `+11`, which is all this script really
# needs right now.
filenames = [
re.sub(' ', '\\ ', os.path.abspath(arg))
for arg in sys.argv[1:] if not arg[0] in ['-', '+']
]
try:
nvim_socket = os.environ["NVIM"]
except KeyError:
# If we aren't running inside a `:terminal`, just exec nvim.
os.execvp('nvim', sys.argv)
nvim = pynvim.attach('socket', path=nvim_socket)
existing_buffers = get_listed_buffers(nvim)
nvim.command('split')
nvim.command('args %s' % ' '.join(filenames))
new_buffers = get_listed_buffers(nvim).difference(existing_buffers)
for arg in sys.argv:
if arg[0] == '+':
nvim.command(arg[1:])
# The '-f' flag is a signal that we're in a situation like a `git commit`
# invocation where we need to block until the user is done with the file(s).
if '-f' in sys.argv and len(new_buffers) > 0:
# The rule here is that the user is 'done' with the opened files when none
# of them are visible onscreen. This allows for use cases like hitting `:q`
# on a `git commit` tempfile. However, we can't just poll to see if they're
# visible, because using `nvim.windows`, `nvim.eval()`, or `nvim.call()`
# will interrupt any multi-key mappings the user may be inputting. The
# solution is to set a buffer-local autocmd on each opened buffer so that
# we only check for visibility immediately after the user either closes or
# hides one of the buffers.
channel_id = nvim.channel_id
for buffer in new_buffers:
nvim.command((
'autocmd BufDelete,BufHidden <buffer=%d> ' +
'call rpcnotify(%d, "check_buffers")'
) % (buffer, channel_id))
stay_open = True
while stay_open:
nvim.next_message() # block until `rpcnotify` is called
open_buffers = [window.buffer.number for window in nvim.windows]
stay_open = any([buffer in open_buffers for buffer in new_buffers])
# Now that none of the opened files are visible anymore, we do a few
# cleanup steps before ending the script:
# * Clear the arg list, since otherwise `:next` would reopen the tempfile
# or whatever.
# * Clear the autocmds we added, since `bdelete` just hides the buffer and
# the autocmds will still be active if the user reopens the file(s).
# * Delete each of the buffers we created.
nvim.command('argdel *')
for buffer in new_buffers:
nvim.command('autocmd! BufDelete,BufHidden <buffer=%d>' % buffer)
nvim.command('bdelete! %d' % buffer)
@rf-
Copy link
Author

rf- commented Sep 12, 2015

From outside Neovim, the script just delegates to the real nvim command:


Opening files from inside a Neovim terminal:


Setting EDITOR='nvim-client -f' allows usage with git and pry:

@nathanaelkane
Copy link

This is exactly what I was looking for, thank you 👍

@cliffxuan
Copy link

ver 0.1.6 of neovim python client has some breaking changes. this script doesn't work anymore with the -f option.
https://github.com/neovim/python-client/releases/tag/0.1.6

@rf-
Copy link
Author

rf- commented May 23, 2016

@cliffxuan Fixed, thanks!

@TSFoster
Copy link

This look fantastic, just what I was looking for, but I'm finding -f doesn't work (still/again). I'm running python 3.5 with neovim python client v0.1.11, neovim v0.1.6.

I see that something (perhaps) similar happened with neovim python client v0.1.6, has something happened to it since then that would break this script again? Is there anything I can provide to help you debug it?

@rf-
Copy link
Author

rf- commented Nov 27, 2016

@TSFoster It seems to be working for me with Neovim v0.1.6 (although it's compiled from master, so it could be older or newer than your v0.1.6). Do you see an error message or anything? What happens when you try to use -f?

@jacobstanley
Copy link

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment