diff --git a/docs/changelog.rst b/docs/changelog.rst index 0f00782fc..27b539111 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -15,6 +15,11 @@ Changelog be bound to key presses in :file:`kitty.conf`. See `https://sw.kovidgoyal.net/kitty/kittens/custom.html`_. (:iss:`870`) +- Add a new ``nth_window`` action that can be used to go to the nth window and + also previously active windows, using negative numbers. Similarly, + ``goto_tab`` now accepts negative numbers to go to previous windows + (:iss:`1040`) + - Fix the ``*_with_cwd`` actions using the cwd of the overlay window rather than the underlying window's cwd (:iss:`1045`) diff --git a/docs/index.rst b/docs/index.rst index b8817f3ba..4b6dbb8a8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -160,6 +160,13 @@ windows and move windows around (similar to window movement in vim):: map shift+down move_window up ... +You can also define a shortcut to switch to the previously active window:: + + map ctrl+p nth_window -1 + +``nth_window`` will focus the nth window for positive numbers and the +previously active windows for negative numbers. + Other keyboard shortcuts ---------------------------------- diff --git a/kitty/config.py b/kitty/config.py index ddcb9d4b5..663e16bad 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -173,6 +173,16 @@ def pipe(func, rest): return func, rest +@func_with_args('nth_window') +def nth_window(func, rest): + try: + num = int(rest) + except Exception: + log_error('Invalid nth_window number: {}'.format(rest)) + num = 1 + return func, [num] + + def parse_key_action(action): parts = action.split(' ', 1) func = parts[0] diff --git a/kitty/config_data.py b/kitty/config_data.py index 39559eff8..882e32fb4 100644 --- a/kitty/config_data.py +++ b/kitty/config_data.py @@ -140,7 +140,8 @@ For example:: 'shortcuts.tab': [ _('Tab management'), '', _('''\ -You can also create shortcuts to go to specific tabs, with 1 being the first tab:: +You can also create shortcuts to go to specific tabs, with 1 being the first +tab, 2 the second tab and -1 being the previously active tab:: map ctrl+alt+1 goto_tab 1 map ctrl+alt+2 goto_tab 2 diff --git a/kitty/tabs.py b/kitty/tabs.py index 7f98fbe59..46b80d73a 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -34,6 +34,7 @@ class Tab: # {{{ self.tab_manager_ref = weakref.ref(tab_manager) self.os_window_id = tab_manager.os_window_id self.id = add_tab(self.os_window_id) + self.active_window_history = deque() if not self.id: raise Exception('No OS window with id {} found, or tab counter has wrapped'.format(self.os_window_id)) self.opts, self.args = tab_manager.opts, tab_manager.args @@ -82,6 +83,9 @@ class Tab: # {{{ def active_window_idx(self, val): try: old_active_window = self.windows[self._active_window_idx] + self.active_window_history.append(old_active_window.id) + if len(self.active_window_history) > 64: + self.active_window_history.popleft() except Exception: old_active_window = None self._active_window_idx = max(0, min(val, len(self.windows) - 1)) @@ -255,7 +259,19 @@ class Tab: # {{{ def nth_window(self, num=0): if self.windows: - self.active_window_idx = self.current_layout.nth_window(self.windows, num) + if num < 0: + try: + old_window_id = self.active_window_history[num] + except IndexError: + return + for idx, w in enumerate(self.windows): + if w.id == old_window_id: + self.active_window_idx = self.current_layout.set_active_window(self.windows, idx) + break + else: + return + else: + self.active_window_idx = self.current_layout.nth_window(self.windows, num) self.relayout_borders() glfw_post_empty_event() @@ -330,6 +346,7 @@ class TabManager: # {{{ def __init__(self, os_window_id, opts, args, startup_session): self.os_window_id = os_window_id + self.last_active_tab_id = None self.opts, self.args = opts, args self.tabs = [] self.active_tab_history = deque() @@ -426,6 +443,15 @@ class TabManager: # {{{ def goto_tab(self, tab_num): if tab_num < len(self.tabs) and 0 <= tab_num: self.set_active_tab_idx(tab_num) + elif tab_num < 0: + try: + old_active_tab_id = self.active_tab_history[tab_num] + except IndexError: + return + for idx, tab in enumerate(self.tabs): + if tab.id == old_active_tab_id: + self.set_active_tab_idx(idx) + break def __iter__(self): return iter(self.tabs)