From e39635ea1682e30b3d43e5005991c6d52ff1b506 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 8 Sep 2018 08:59:11 +0530 Subject: [PATCH] Add a new ``neighboring_window`` function to switch to neighboring windows in the current layout, similar to window movement in vim Fixes #916 --- docs/changelog.rst | 3 +++ docs/index.rst | 7 +++++++ kitty/config.py | 10 ++++++++++ kitty/layout.py | 9 ++++++--- kitty/tabs.py | 8 ++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 10aaeb763..42c9d9b25 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,6 +9,9 @@ Changelog - Add a new ``last_used_layout`` function that can be mapped to a shortcut to switch to the previously used window layout (:iss:`870`) +- Add a new ``neighboring_window`` function to switch to neighboring + windows in the current layout, similar to window movement in vim (:iss:`916`) + 0.12.1 [2018-09-08] ------------------------------ diff --git a/docs/index.rst b/docs/index.rst index e3e463c0a..e9654cc65 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -151,6 +151,13 @@ Focus specific window :sc:`first_window`, :sc:`second_window` ... :sc:`ten (clockwise from the top-left) ======================== ======================= +Additionally, you can define shortcuts in :file:`kitty.conf` to go to neighboring +windows (similar to window movement in vim):: + + map ctrl+left neighboring_window left + map ctrl+down neighboring_window bottom + ... + Other keyboard shortcuts ---------------------------------- diff --git a/kitty/config.py b/kitty/config.py index 942ba9be3..07ff29b9d 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -140,6 +140,16 @@ def clear_terminal(func, rest): return func, args +@func_with_args('neighboring_window') +def neighboring_window(func, rest): + rest = rest.lower() + rest = {'up': 'top', 'down': 'bottom'}.get(rest, rest) + if rest not in ('left', 'right', 'top', 'bottom'): + log_error('Invalid neighbor specification: {}'.format(rest)) + rest = 'right' + return func, [rest] + + def parse_key_action(action): parts = action.split(' ', 1) func = parts[0] diff --git a/kitty/layout.py b/kitty/layout.py index e8a531040..d5d95f6b1 100644 --- a/kitty/layout.py +++ b/kitty/layout.py @@ -231,7 +231,10 @@ class Layout: # {{{ def neighbors(self, all_windows, active_window_idx): w = all_windows[active_window_idx] windows = process_overlaid_windows(all_windows)[1] - self.neighbors_for_window(w, windows) + ans = self.neighbors_for_window(w, windows) + for values in ans.values(): + values[:] = [idx_for_id(w.id, windows) for w in values] + return ans def move_window(self, all_windows, active_window_idx, delta=1): w = all_windows[active_window_idx] @@ -481,7 +484,7 @@ class Tall(Layout): # {{{ if window is windows[0]: return {'left': [], 'right': windows[1:], 'top': [], 'bottom': []} idx = windows.index(window) - return {'left': windows[0], 'right': [], 'top': [] if idx <= 1 else [windows[idx-1]], + return {'left': [windows[0]], 'right': [], 'top': [] if idx <= 1 else [windows[idx-1]], 'bottom': [] if window is windows[-1] else [windows[idx+1]]} def minimal_borders(self, windows, active_window, needs_borders_map): @@ -540,7 +543,7 @@ class Fat(Tall): # {{{ if window is windows[0]: return {'left': [], 'bottom': windows[1:], 'top': [], 'right': []} idx = windows.index(window) - return {'top': windows[0], 'bottom': [], 'left': [] if idx <= 1 else [windows[idx-1]], + return {'top': [windows[0]], 'bottom': [], 'left': [] if idx <= 1 else [windows[idx-1]], 'right': [] if window is windows[-1] else [windows[idx+1]]} # }}} diff --git a/kitty/tabs.py b/kitty/tabs.py index 42ec98799..1dd3a810e 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -271,6 +271,14 @@ class Tab: # {{{ def previous_window(self): self._next_window(-1) + def neighboring_window(self, which): + neighbors = self.current_layout.neighbors(self.windows, self.active_window_idx) + candidates = neighbors.get(which) + if candidates: + self.active_window_idx = self.current_layout.set_active_window(self.windows, candidates[0]) + self.relayout_borders() + glfw_post_empty_event() + def move_window(self, delta=1): self.active_window_idx = self.current_layout.move_window(self.windows, self.active_window_idx, delta) self.relayout()