diff options
| -rwxr-xr-x | extras/sysroot/home/rahm/.local/bin/vim | 83 | ||||
| -rw-r--r-- | src/Internal/Keys.hs | 18 |
2 files changed, 101 insertions, 0 deletions
diff --git a/extras/sysroot/home/rahm/.local/bin/vim b/extras/sysroot/home/rahm/.local/bin/vim new file mode 100755 index 0000000..d0aafa5 --- /dev/null +++ b/extras/sysroot/home/rahm/.local/bin/vim @@ -0,0 +1,83 @@ +#!/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 + +# 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_LISTEN_ADDRESS"] +except KeyError: + # If we aren't running inside a `:terminal`, just exec nvim. + os.execvp(u'nvim', sys.argv) + +nvim = neovim.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) diff --git a/src/Internal/Keys.hs b/src/Internal/Keys.hs index ee74e14..89b4e0f 100644 --- a/src/Internal/Keys.hs +++ b/src/Internal/Keys.hs @@ -1,5 +1,6 @@ module Internal.Keys where +import Debug.Trace import Control.Applicative import Prelude hiding ((!!)) import Control.Monad @@ -64,6 +65,22 @@ newKeys = shiftToWorkspace ch = do windows $ W.shift $ return ch + swapWs f t (W.Workspace t' l s) | t' == f = W.Workspace t l s + swapWs f t (W.Workspace t' l s) | t' == t = W.Workspace f l s + swapWs _ _ ws = ws + + swapSc f t (W.Screen ws a b) = W.Screen (swapWs f t ws) a b + + swapWorkspace :: Char -> X () + swapWorkspace toChar = do + windows $ \ss -> do + let from = W.tag $ W.workspace $ W.current ss + to = [toChar] in + (W.StackSet (swapSc from to $ W.current ss) + (map (swapSc from to) $ W.visible ss) + (map (swapWs from to) $ W.hidden ss) + (W.floating ss)) + fuzzyCompletion s1 s0 = let ws = filter (not . all isSpace) $ words (map toLower s1) l0 = map toLower s0 in @@ -128,6 +145,7 @@ newKeys = (mapAlpha modm (jumpToMark markContext)))) , ((modm, xK_g), (submap $ mapNumbersAndAlpha 0 gotoWorkspace)) , ((modm .|. shiftMask, xK_g), (submap $ mapNumbersAndAlpha 0 shiftToWorkspace)) + , ((modm .|. shiftMask .|. mod1Mask, xK_g), (submap $ mapNumbersAndAlpha 0 swapWorkspace)) , ((modm .|. shiftMask, xK_bracketleft), sendMessage (IncMasterN (-1))) , ((modm .|. shiftMask, xK_bracketright), sendMessage (IncMasterN 1)) |