Remote control: Allow matching by neighbor of active window

This commit is contained in:
Kovid Goyal
2023-08-25 13:48:53 +05:30
parent 1cb4cdbaea
commit f50660bb30
5 changed files with 28 additions and 2 deletions

View File

@@ -59,6 +59,8 @@ Detailed list of changes
- X11: Print an error to :file:`STDERR` instead of refusing to start when the user sets a custom window icon larger than 128x128 (:iss:`6507`)
- Remote control: Allow matching by neighbor of active window. Useful for navigation plugins like vim-kitty-navigator
0.29.2 [2023-07-27]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -489,7 +489,7 @@ class Boss:
return {wid for wid in candidates if self.window_id_map[wid].matches_query(location, query, tab, self_window)}
for wid in search(match, (
'id', 'title', 'pid', 'cwd', 'cmdline', 'num', 'env', 'var', 'recent', 'state'
'id', 'title', 'pid', 'cwd', 'cmdline', 'num', 'env', 'var', 'recent', 'state', 'neighbor',
), set(self.window_id_map), get_matches):
yield self.window_id_map[wid]

View File

@@ -83,7 +83,7 @@ MATCH_WINDOW_OPTION = '''\
--match -m
The window to match. Match specifications are of the form: :italic:`field:query`.
Where :italic:`field` can be one of: :code:`id`, :code:`title`, :code:`pid`, :code:`cwd`, :code:`cmdline`, :code:`num`,
:code:`env`, :code:`var`, :code:`state`, and :code:`recent`.
:code:`env`, :code:`var`, :code:`state`, :code:`neighbor`, and :code:`recent`.
:italic:`query` is the expression to match. Expressions can be either a number or a regular expression, and can be
:ref:`combined using Boolean operators <search_syntax>`.
@@ -101,6 +101,9 @@ The window id of the current window is available as the :envvar:`KITTY_WINDOW_ID
The field :code:`recent` refers to recently active windows in the currently active tab, with zero being the currently
active window, one being the previously active window and so on.
The field :code:`neighbor` refers to a neighbor of the active window in the specified direction, which can be:
:code:`left`, :code:`right`, :code:`top` or :code:`bottom`.
When using the :code:`env` field to match on environment variables, you can specify only the environment variable name
or a name and value, for example, :code:`env:MY_ENV_VAR=2`.

View File

@@ -755,6 +755,21 @@ class Window:
if query == 'overlay_parent':
return self_window is not None and self is self_window.overlay_parent
return False
if field == 'neighbor':
t = get_boss().active_tab
if t is None:
return False
gid: Optional[int] = None
if query == 'left':
gid = t.neighboring_group_id("left")
elif query == 'right':
gid = t.neighboring_group_id("right")
elif query == 'top':
gid = t.neighboring_group_id("top")
elif query == 'bottom':
gid = t.neighboring_group_id("bottom")
return gid is not None and t.windows.active_window_in_group_id(gid) is self
pat = compile_match_query(query, field not in ('env', 'var'))
return self.matches(field, pat)

View File

@@ -395,6 +395,12 @@ class WindowList:
return self.id_map.get(self.groups[n].active_window_id)
return None
def active_window_in_group_id(self, group_id: int) -> Optional[WindowType]:
for g in self.groups:
if g.id == group_id:
return self.id_map.get(g.active_window_id)
return None
def activate_next_window_group(self, delta: int) -> None:
self.set_active_group_idx(wrap_increment(self.active_group_idx, self.num_groups, delta))