mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-08-03 22:25:57 +00:00
kitten @ ls: Also output the neighbors for every window
This commit is contained in:
parent
e0118e4553
commit
e49d940621
11 changed files with 63 additions and 40 deletions
|
|
@ -163,6 +163,8 @@ Detailed list of changes
|
|||
|
||||
- Have reloading config also reload the custom tab bar python modules (:disc:`9221`)
|
||||
|
||||
- kitten @ ls: Also output the neighbors for every window (:disc:`9225`)
|
||||
|
||||
|
||||
0.44.0 [2025-11-03]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ from typing import Any, Callable, NamedTuple
|
|||
from kitty.borders import BorderColor
|
||||
from kitty.fast_data_types import Region, get_options, set_active_window, viewport_for_window
|
||||
from kitty.options.types import Options
|
||||
from kitty.types import Edges, WindowGeometry, WindowMapper
|
||||
from kitty.typing_compat import TypedDict, WindowType
|
||||
from kitty.types import Edges, NeighborsMap, WindowGeometry, WindowMapper
|
||||
from kitty.typing_compat import WindowType
|
||||
from kitty.window_list import WindowGroup, WindowList
|
||||
|
||||
|
||||
|
|
@ -41,13 +41,6 @@ LayoutDimension = Generator[LayoutData, None, None]
|
|||
ListOfWindows = list[WindowType]
|
||||
|
||||
|
||||
class NeighborsMap(TypedDict):
|
||||
left: list[int]
|
||||
top: list[int]
|
||||
right: list[int]
|
||||
bottom: list[int]
|
||||
|
||||
|
||||
class LayoutGlobalData:
|
||||
draw_minimal_borders: bool = True
|
||||
draw_active_borders: bool = True
|
||||
|
|
@ -437,7 +430,7 @@ class Layout:
|
|||
raise NotImplementedError()
|
||||
|
||||
def neighbors_for_window(self, window: WindowType, windows: WindowList) -> NeighborsMap:
|
||||
return {'left': [], 'right': [], 'top': [], 'bottom': []}
|
||||
return {}
|
||||
|
||||
def compute_needs_borders_map(self, all_windows: WindowList) -> dict[int, bool]:
|
||||
return all_windows.compute_needs_borders_map(lgd.draw_active_borders)
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ from math import ceil, floor
|
|||
from typing import Any
|
||||
|
||||
from kitty.borders import BorderColor
|
||||
from kitty.types import Edges, WindowMapper
|
||||
from kitty.types import Edges, NeighborsMap, WindowMapper
|
||||
from kitty.typing_compat import WindowType
|
||||
from kitty.window_list import WindowGroup, WindowList
|
||||
|
||||
from .base import BorderLine, Layout, LayoutData, LayoutDimension, ListOfWindows, NeighborsMap, layout_dimension, lgd
|
||||
from .base import BorderLine, Layout, LayoutData, LayoutDimension, ListOfWindows, layout_dimension, lgd
|
||||
from .tall import neighbors_for_tall_window
|
||||
|
||||
|
||||
|
|
@ -302,12 +302,16 @@ class Grid(Layout):
|
|||
xs.extend(neighbors(neighbor_row, neighbor_col))
|
||||
return xs
|
||||
|
||||
return {
|
||||
'top': neighbors(row-1, col) if row else [],
|
||||
'bottom': neighbors(row + 1, col),
|
||||
'left': side(row, col, -1) if col else [],
|
||||
'right': side(row, col, 1) if col < ncols - 1 else [],
|
||||
}
|
||||
ans: NeighborsMap = {}
|
||||
if row:
|
||||
ans['top'] = neighbors(row-1, col)
|
||||
if bottom := neighbors(row + 1, col):
|
||||
ans['bottom'] = bottom
|
||||
if col and (left := side(row, col, -1)):
|
||||
ans['left'] = left
|
||||
if col < ncols - 1:
|
||||
ans['right'] = side(row, col, 1)
|
||||
return ans
|
||||
|
||||
def layout_state(self) -> dict[str, Any]:
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ from collections.abc import Collection, Generator, Sequence
|
|||
from typing import Any, NamedTuple, Optional, TypedDict, Union
|
||||
|
||||
from kitty.borders import BorderColor
|
||||
from kitty.types import Edges, WindowGeometry, WindowMapper
|
||||
from kitty.types import Edges, NeighborsMap, WindowGeometry, WindowMapper
|
||||
from kitty.typing_compat import EdgeLiteral, WindowType
|
||||
from kitty.window_list import WindowGroup, WindowList
|
||||
|
||||
from .base import BorderLine, Layout, LayoutOpts, NeighborsMap, blank_rects_for_window, lgd, window_geometry_from_layouts
|
||||
from .base import BorderLine, Layout, LayoutOpts, blank_rects_for_window, lgd, window_geometry_from_layouts
|
||||
|
||||
|
||||
class Extent(NamedTuple):
|
||||
|
|
@ -405,14 +405,14 @@ class Pair:
|
|||
geometries = {group.id: group.geometry for group in all_windows.groups if group.geometry}
|
||||
|
||||
def extend(other: Union[int, 'Pair', None], edge: EdgeLiteral, which: EdgeLiteral) -> None:
|
||||
if not ans[which] and other:
|
||||
if not ans.get(which) and other:
|
||||
if isinstance(other, Pair):
|
||||
neighbors = (
|
||||
w for w in other.edge_windows(edge)
|
||||
if is_neighbouring_geometry(geometries[w], geometries[window_id], which))
|
||||
ans[which].extend(neighbors)
|
||||
ans.setdefault(which, []).extend(neighbors)
|
||||
else:
|
||||
ans[which].append(other)
|
||||
ans.setdefault(which, []).append(other)
|
||||
|
||||
def is_neighbouring_geometry(a: WindowGeometry, b: WindowGeometry, direction: str) -> bool:
|
||||
def edges(g: WindowGeometry) -> tuple[int, int]:
|
||||
|
|
@ -610,7 +610,7 @@ class Splits(Layout):
|
|||
wg = all_windows.group_for_window(window)
|
||||
assert wg is not None
|
||||
pair = self.pairs_root.pair_for_window(wg.id)
|
||||
ans: NeighborsMap = {'left': [], 'right': [], 'top': [], 'bottom': []}
|
||||
ans: NeighborsMap = {}
|
||||
if pair is not None:
|
||||
pair.neighbors_for_window(wg.id, ans, self, all_windows)
|
||||
return ans
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from kitty.types import NeighborsMap
|
||||
from kitty.typing_compat import WindowType
|
||||
from kitty.window_list import WindowList
|
||||
|
||||
from .base import Layout, NeighborsMap
|
||||
from .base import Layout
|
||||
|
||||
|
||||
class Stack(Layout):
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from typing import Any
|
|||
|
||||
from kitty.borders import BorderColor
|
||||
from kitty.conf.utils import to_bool
|
||||
from kitty.types import Edges, WindowMapper
|
||||
from kitty.types import Edges, NeighborsMap, WindowMapper
|
||||
from kitty.typing_compat import EdgeLiteral, WindowType
|
||||
from kitty.window_list import WindowGroup, WindowList
|
||||
|
||||
|
|
@ -17,7 +17,6 @@ from .base import (
|
|||
LayoutData,
|
||||
LayoutDimension,
|
||||
LayoutOpts,
|
||||
NeighborsMap,
|
||||
lgd,
|
||||
normalize_biases,
|
||||
safe_increment_bias,
|
||||
|
|
@ -38,7 +37,7 @@ def neighbors_for_tall_window(
|
|||
idx = groups.index(wg)
|
||||
prev = None if idx == 0 else groups[idx-1]
|
||||
nxt = None if idx == len(groups) - 1 else groups[idx+1]
|
||||
ans: NeighborsMap = {'left': [], 'right': [], 'top': [], 'bottom': []}
|
||||
ans: NeighborsMap = {}
|
||||
main_before: EdgeLiteral = 'left' if main_is_horizontal else 'top'
|
||||
main_after: EdgeLiteral = 'right' if main_is_horizontal else 'bottom'
|
||||
cross_before: EdgeLiteral = 'top' if main_is_horizontal else 'left'
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ from collections.abc import Generator, Iterable
|
|||
from typing import Any
|
||||
|
||||
from kitty.borders import BorderColor
|
||||
from kitty.types import Edges, WindowMapper
|
||||
from kitty.typing_compat import WindowType
|
||||
from kitty.types import Edges, NeighborsMap, WindowMapper
|
||||
from kitty.typing_compat import EdgeLiteral, WindowType
|
||||
from kitty.window_list import WindowGroup, WindowList
|
||||
|
||||
from .base import BorderLine, Layout, LayoutData, LayoutDimension, NeighborsMap, lgd
|
||||
from .base import BorderLine, Layout, LayoutData, LayoutDimension, lgd
|
||||
|
||||
|
||||
def borders(
|
||||
|
|
@ -133,9 +133,16 @@ class Vertical(Layout):
|
|||
after = [groups[(idx + 1) % lg].id]
|
||||
else:
|
||||
before, after = [], []
|
||||
ans: NeighborsMap = {}
|
||||
akey: EdgeLiteral = 'top'
|
||||
bkey: EdgeLiteral = 'bottom'
|
||||
if self.main_is_horizontal:
|
||||
return {'left': before, 'right': after, 'top': [], 'bottom': []}
|
||||
return {'top': before, 'bottom': after, 'left': [], 'right': []}
|
||||
akey, bkey = 'left', 'right'
|
||||
if before:
|
||||
ans[bkey] = before
|
||||
if after:
|
||||
ans[akey] = after
|
||||
return ans
|
||||
|
||||
def layout_state(self) -> dict[str, Any]:
|
||||
return {'biased_map': self.biased_map}
|
||||
|
|
|
|||
|
|
@ -943,12 +943,15 @@ class Tab: # {{{
|
|||
|
||||
def list_windows(self, self_window: Window | None = None, window_filter: Callable[[Window], bool] | None = None) -> Generator[WindowDict, None, None]:
|
||||
active_window = self.active_window
|
||||
cl = self.current_layout
|
||||
for w in self:
|
||||
if window_filter is None or window_filter(w):
|
||||
yield w.as_dict(
|
||||
is_active=w is active_window,
|
||||
is_focused=w.os_window_id == current_focused_os_window_id() and w is active_window,
|
||||
is_self=w is self_window)
|
||||
is_self=w is self_window,
|
||||
neighbors_map=cl.neighbors_for_window(w, self.windows)
|
||||
)
|
||||
|
||||
def list_groups(self) -> list[dict[str, Any]]:
|
||||
return [g.as_simple_dict() for g in self.windows.groups]
|
||||
|
|
|
|||
|
|
@ -234,3 +234,10 @@ def ac(group: ActionGroup, doc: str) -> Callable[[_T], _T]:
|
|||
|
||||
WindowMapper = Callable[[int], int | None]
|
||||
DecoratedFunc = TypeVar('DecoratedFunc', bound=Callable[..., Any])
|
||||
|
||||
|
||||
class NeighborsMap(TypedDict, total=False):
|
||||
left: list[int]
|
||||
top: list[int]
|
||||
right: list[int]
|
||||
bottom: list[int]
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ from .options.types import Options
|
|||
from .progress import Progress
|
||||
from .rgb import to_color
|
||||
from .terminfo import get_capabilities
|
||||
from .types import MouseEvent, OverlayType, WindowGeometry, ac, run_once
|
||||
from .types import MouseEvent, NeighborsMap, OverlayType, WindowGeometry, ac, run_once
|
||||
from .typing_compat import BossType, ChildType, EdgeLiteral, TabType, TypedDict
|
||||
from .utils import (
|
||||
color_as_int,
|
||||
|
|
@ -250,6 +250,7 @@ class WindowDict(TypedDict):
|
|||
at_prompt: bool
|
||||
created_at: int
|
||||
in_alternate_screen: bool
|
||||
neighbors: NeighborsMap
|
||||
|
||||
|
||||
class PipeData(TypedDict):
|
||||
|
|
@ -1938,7 +1939,12 @@ class Window:
|
|||
return get_mouse_data_for_window(self.os_window_id, self.tab_id, self.id)
|
||||
|
||||
# Serialization {{{
|
||||
def as_dict(self, is_focused: bool = False, is_self: bool = False, is_active: bool = False) -> WindowDict:
|
||||
def as_dict(
|
||||
self, is_focused: bool = False, is_self: bool = False, is_active: bool = False,
|
||||
neighbors_map: NeighborsMap | None = None,
|
||||
) -> WindowDict:
|
||||
if neighbors_map is None:
|
||||
neighbors_map = {}
|
||||
return {
|
||||
'id': self.id,
|
||||
'is_focused': is_focused,
|
||||
|
|
@ -1958,6 +1964,7 @@ class Window:
|
|||
'user_vars': self.user_vars,
|
||||
'created_at': self.created_at,
|
||||
'in_alternate_screen': self.screen.is_using_alternate_linebuf(),
|
||||
'neighbors': neighbors_map,
|
||||
}
|
||||
|
||||
def serialize_state(self) -> dict[str, Any]:
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ class TestLayout(BaseTest):
|
|||
windows[1].set_geometry(WindowGeometry(11, 0, 20, 10, 0, 0))
|
||||
windows[2].set_geometry(WindowGeometry(11, 11, 15, 20, 0, 0))
|
||||
windows[3].set_geometry(WindowGeometry(16, 11, 20, 20, 0, 0))
|
||||
self.ae(q.neighbors_for_window(windows[0], all_windows), {'left': [], 'right': [2, 3], 'top': [], 'bottom': []})
|
||||
self.ae(q.neighbors_for_window(windows[1], all_windows), {'left': [1], 'right': [], 'top': [], 'bottom': [3, 4]})
|
||||
self.ae(q.neighbors_for_window(windows[2], all_windows), {'left': [1], 'right': [4], 'top': [2], 'bottom': []})
|
||||
self.ae(q.neighbors_for_window(windows[3], all_windows), {'left': [3], 'right': [], 'top': [2], 'bottom': []})
|
||||
self.ae(q.neighbors_for_window(windows[0], all_windows), {'right': [2, 3]})
|
||||
self.ae(q.neighbors_for_window(windows[1], all_windows), {'left': [1], 'bottom': [3, 4]})
|
||||
self.ae(q.neighbors_for_window(windows[2], all_windows), {'left': [1], 'right': [4], 'top': [2]})
|
||||
self.ae(q.neighbors_for_window(windows[3], all_windows), {'left': [3], 'top': [2]})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue