aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xextras/sysroot/home/rahm/.local/bin/vim83
-rw-r--r--src/Internal/Keys.hs18
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))