mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-09-22 03:57:30 +03:00
Merge branch 'neighboring_window_changes' of https://github.com/juho-p/kitty
This commit is contained in:
commit
294be2a772
@ -6,7 +6,7 @@
|
||||
from itertools import repeat
|
||||
from typing import (
|
||||
Dict, Generator, Iterable, Iterator, List, NamedTuple, Optional, Sequence,
|
||||
Tuple, Union, cast
|
||||
Tuple
|
||||
)
|
||||
|
||||
from kitty.constants import Edges, WindowGeometry
|
||||
@ -261,24 +261,14 @@ def neighbors(self, all_windows: WindowList) -> NeighborsMap:
|
||||
assert w is not None
|
||||
return self.neighbors_for_window(w, all_windows)
|
||||
|
||||
def move_window(self, all_windows: WindowList, delta: Union[str, int] = 1) -> bool:
|
||||
# delta can be either a number or a string such as 'left', 'top', etc
|
||||
# for neighborhood moves
|
||||
def move_window(self, all_windows: WindowList, delta: int = 1) -> bool:
|
||||
if all_windows.num_groups < 2 or not delta:
|
||||
return False
|
||||
|
||||
if isinstance(delta, int):
|
||||
return all_windows.move_window_group(by=delta)
|
||||
which = delta.lower()
|
||||
which = {'up': 'top', 'down': 'bottom'}.get(which, which)
|
||||
w = all_windows.active_window
|
||||
if w is None:
|
||||
return False
|
||||
neighbors = self.neighbors_for_window(w, all_windows)
|
||||
q: List[int] = cast(List[int], neighbors.get(which, []))
|
||||
if not q:
|
||||
return False
|
||||
return all_windows.move_window_group(to_group=q[0])
|
||||
return all_windows.move_window_group(by=delta)
|
||||
|
||||
def move_window_to_group(self, all_windows: WindowList, group: int) -> bool:
|
||||
return all_windows.move_window_group(to_group=group)
|
||||
|
||||
def add_window(self, all_windows: WindowList, window: WindowType, location: Optional[str] = None, overlay_for: Optional[int] = None) -> None:
|
||||
if overlay_for is not None and overlay_for in all_windows:
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
from functools import lru_cache
|
||||
from itertools import repeat
|
||||
from math import ceil, floor
|
||||
from typing import Callable, Dict, Generator, List, Optional, Sequence, Tuple
|
||||
|
||||
from kitty.constants import Edges
|
||||
@ -235,9 +236,17 @@ def neighbors(row: int, col: int) -> List[int]:
|
||||
|
||||
def side(row: int, col: int, delta: int) -> List[int]:
|
||||
neighbor_col = col + delta
|
||||
if col_counts[neighbor_col] == col_counts[col]:
|
||||
neighbor_nrows = col_counts[neighbor_col]
|
||||
nrows = col_counts[col]
|
||||
if neighbor_nrows == nrows:
|
||||
return neighbors(row, neighbor_col)
|
||||
return neighbors(min(row, col_counts[neighbor_col] - 1), neighbor_col)
|
||||
|
||||
start_row = floor(neighbor_nrows * row / nrows)
|
||||
end_row = ceil(neighbor_nrows * (row + 1) / nrows)
|
||||
xs = []
|
||||
for neighbor_row in range(start_row, end_row):
|
||||
xs.extend(neighbors(neighbor_row, neighbor_col))
|
||||
return xs
|
||||
|
||||
return {
|
||||
'top': neighbors(row-1, col) if row else [],
|
||||
|
@ -244,7 +244,7 @@ def modify_size_of_child(self, which: int, increment: float, is_horizontal: bool
|
||||
return parent.modify_size_of_child(which, increment, is_horizontal, layout_object)
|
||||
return False
|
||||
|
||||
def neighbors_for_window(self, window_id: int, ans: NeighborsMap, layout_object: 'Splits') -> None:
|
||||
def neighbors_for_window(self, window_id: int, ans: NeighborsMap, layout_object: 'Splits', all_windows: WindowList) -> None:
|
||||
|
||||
def quadrant(is_horizontal: bool, is_first: bool) -> Tuple[EdgeLiteral, EdgeLiteral]:
|
||||
if is_horizontal:
|
||||
@ -255,13 +255,27 @@ def quadrant(is_horizontal: bool, is_first: bool) -> Tuple[EdgeLiteral, EdgeLite
|
||||
return 'top', 'bottom'
|
||||
return 'bottom', 'top'
|
||||
|
||||
geometries = dict((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 isinstance(other, Pair):
|
||||
ans[which].extend(other.edge_windows(edge))
|
||||
neighbors = (
|
||||
w for w in other.edge_windows(edge)
|
||||
if is_neighbouring_geometry(geometries[w], geometries[window_id], which))
|
||||
ans[which].extend(neighbors)
|
||||
else:
|
||||
ans[which].append(other)
|
||||
|
||||
def is_neighbouring_geometry(a: WindowGeometry, b: WindowGeometry, direction: str) -> bool:
|
||||
def edges(g: WindowGeometry) -> Tuple[int, int]:
|
||||
return (g.top, g.bottom) if direction in ['left', 'right'] else (g.left, g.right)
|
||||
|
||||
a1, a2 = edges(a)
|
||||
b1, b2 = edges(b)
|
||||
|
||||
return a1 < b2 and a2 > b1
|
||||
|
||||
other = self.two if self.one == window_id else self.one
|
||||
extend(other, *quadrant(self.horizontal, self.one == window_id))
|
||||
|
||||
@ -418,15 +432,15 @@ def neighbors_for_window(self, window: WindowType, all_windows: WindowList) -> N
|
||||
pair = self.pairs_root.pair_for_window(wg.id)
|
||||
ans: NeighborsMap = {'left': [], 'right': [], 'top': [], 'bottom': []}
|
||||
if pair is not None:
|
||||
pair.neighbors_for_window(wg.id, ans, self)
|
||||
pair.neighbors_for_window(wg.id, ans, self, all_windows)
|
||||
return ans
|
||||
|
||||
def move_window(self, all_windows: WindowList, delta: Union[str, int] = 1) -> bool:
|
||||
def move_window_to_group(self, all_windows: WindowList, group: int) -> bool:
|
||||
before = all_windows.active_group
|
||||
if before is None:
|
||||
return False
|
||||
before_idx = all_windows.active_group_idx
|
||||
moved = super().move_window(all_windows, delta)
|
||||
moved = super().move_window_to_group(all_windows, group)
|
||||
after = all_windows.groups[before_idx]
|
||||
if moved and before.id != after.id:
|
||||
self.pairs_root.swap_windows(before.id, after.id)
|
||||
|
@ -410,15 +410,36 @@ def previous_window(self) -> None:
|
||||
|
||||
prev_window = previous_window
|
||||
|
||||
def neighboring_window(self, which: str) -> None:
|
||||
def most_recent_group(self, groups: List[int]) -> int:
|
||||
groups_set = set(groups)
|
||||
|
||||
for window_id in reversed(self.windows.active_window_history):
|
||||
group = self.windows.group_for_window(window_id)
|
||||
if group and group.id in groups_set:
|
||||
return group.id
|
||||
|
||||
return groups[0]
|
||||
|
||||
def neighboring_group_id(self, which: str) -> Optional[int]:
|
||||
neighbors = self.current_layout.neighbors(self.windows)
|
||||
candidates = cast(Optional[Tuple[int, ...]], neighbors.get(which))
|
||||
candidates = cast(Optional[List[int]], neighbors.get(which))
|
||||
if candidates:
|
||||
self.windows.set_active_group(candidates[0])
|
||||
return self.most_recent_group(candidates)
|
||||
|
||||
def neighboring_window(self, which: str) -> None:
|
||||
neighbor = self.neighboring_group_id(which)
|
||||
if neighbor:
|
||||
self.windows.set_active_group(neighbor)
|
||||
|
||||
def move_window(self, delta: Union[str, int] = 1) -> None:
|
||||
if self.current_layout.move_window(self.windows, delta):
|
||||
self.relayout()
|
||||
if isinstance(delta, int):
|
||||
if self.current_layout.move_window(self.windows, delta):
|
||||
self.relayout()
|
||||
elif isinstance(delta, str):
|
||||
neighbor = self.neighboring_group_id(delta)
|
||||
if neighbor:
|
||||
if self.current_layout.move_window_to_group(self.windows, neighbor):
|
||||
self.relayout()
|
||||
|
||||
def move_window_to_top(self) -> None:
|
||||
n = self.windows.num_groups
|
||||
|
@ -250,6 +250,10 @@ def test_splits(self):
|
||||
self.ae(q.pairs_root.pair_for_window(2).horizontal, False)
|
||||
q.add_window(all_windows, Window(4), location='vsplit')
|
||||
windows = list(all_windows)
|
||||
windows[0].set_geometry(WindowGeometry(0, 0, 10, 20, 0, 0))
|
||||
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': []})
|
||||
|
Loading…
Reference in New Issue
Block a user