summaryrefslogtreecommitdiff
path: root/run_vim.py
blob: 894b5e7c0022b238a3b69d7f06c7512d5dfe4593 (plain) (blame)
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)