diff options
-rwxr-xr-x | run_vim.py | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/run_vim.py b/run_vim.py new file mode 100755 index 0000000..93f15e5 --- /dev/null +++ b/run_vim.py @@ -0,0 +1,104 @@ +#!/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)) + + +def resolve_google3(fname): + if fname.startswith('//depot/google3'): + cwd = os.getcwd() + if "/google3" in cwd: + depot_dir = cwd[:cwd.find('/google3')] + realfname = fname.replace('//depot', depot_dir) + return realfname + return fname + +# 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 = [ + re.sub(' ', '\ ', os.path.abspath(resolve_google3(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: + 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': [['" + filenames[0] + "', '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) |