1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#!/usr/bin/python3
import neovim, 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))
# Many terminals now support undercurl, but Neovim still looks for xterm-kitty
# to enable it.
if os.environ["TERM"] in ["alactritty", "xterm-256color"]:
os.environ["TERM"] = "xterm-kitty"
# 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 = [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(u'nvim', list(filter(lambda a: a != "--float", sys.argv)))
nvim = neovim.attach('socket', path=nvim_socket)
existing_buffers = get_listed_buffers(nvim)
if '--float' in sys.argv:
float_title = filenames[0] if len(filenames) > 0 else ""
nvim.command('call nvim_open_win(0, 1, {' + "'relative': 'editor'," +
"'width': 90," + "'height': 40," +
"'col': (nvim_list_uis()[0].width / 2) - (90 / 2)," +
"'row': (nvim_list_uis()[0].height / 2) - (40 / 2)," +
"'anchor': 'NW'," + "'style': 'minimal'," +
"'border': 'single'," + "'title': [['" + float_title +
"', 'Statement']]" + "})")
nvim.command("set winhighlight=Normal:Normal")
else:
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,QuitPre <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,QuitPre <buffer=%d>' %
buffer)
nvim.command('bdelete! %d' % buffer)
|