from kittens.tui.handler import result_handler from kittens.tui.handler import kitten_ui # from kittens.tui.loop import debug from kitty.boss import Boss from kitty.rc.base import MatchError from kitty.tabs import Tab, TabManager from kitty.fast_data_types import swap_tabs # from pprint import pprint def get_tab_vt(tab: Tab) -> str | None: """Get the 'vt' user var from a tab's windows, or None if not set.""" for window in tab: vt = window.user_vars.get("vt") if vt is not None: return vt return None def reorder_tabs_by_vt(tm: TabManager) -> None: """Reorder tabs so those without 'vt' come first, then those with 'vt' sorted by value.""" tabs = tm.tabs if len(tabs) <= 1: return # Build list of (tab, vt_value) tuples tab_vt_pairs: list[tuple[Tab, str | None]] = [ (tab, get_tab_vt(tab)) for tab in tabs ] # Sort: tabs without vt first (None sorts before strings with key trick), # then tabs with vt sorted by vt value def sort_key(pair: tuple[Tab, str | None]) -> tuple[int, int, str]: tab, vt = pair if vt is None: return (0, 0, "") # No vt: sort first # Try numeric sort first, fall back to string sort try: return (1, int(vt), "") # Numeric vt except ValueError: return (2, 0, vt) # Non-numeric vt: sort after numeric, by string sorted_pairs = sorted(tab_vt_pairs, key=sort_key) sorted_tabs = [pair[0] for pair in sorted_pairs] # Check if already in correct order if sorted_tabs == tabs: return # Reorder by swapping to target positions # We'll do a simple bubble-sort style swap to get tabs in place for target_idx, target_tab in enumerate(sorted_tabs): current_idx = tabs.index(target_tab) while current_idx > target_idx: # Swap with previous position tabs[current_idx], tabs[current_idx - 1] = ( tabs[current_idx - 1], tabs[current_idx], ) swap_tabs(tm.os_window_id, current_idx, current_idx - 1) current_idx -= 1 tm.mark_tab_bar_dirty() # @kitten_ui(allow_remote_control=True) def main(args: list[str]) -> None: pass @result_handler(no_ui=True) def handle_result( args: list[str], answer: str, target_window_id: int, boss: Boss ) -> None: target_id = args[1] # pprint(("target_id: ", target_id)) # pprint(("args: ", args)) w = boss.window_id_map.get(target_window_id) tm = boss.active_tab_manager_with_dispatch if tm is None: raise RuntimeError("No tab manager?") tabs = list(boss.match_tabs(f"var:vt=^{target_id}$")) if len(tabs) > 0: tm.set_active_tab(tabs[0]) return # pprint(("tm", tm, "tabs", list(tabs))) if w is not None: try: boss.call_remote_control( w, ("focus-tab", "--match", f"var:vt=^{target_id}$") ) except MatchError: # pprint("No match, need to create tab") boss.call_remote_control( w, ("launch", "--type", "tab", "--var", f"vt={target_id}", *args[2:]) ) reorder_tabs_by_vt(tm) tabs = list(boss.match_tabs(f"var:vt=^{target_id}$")) if len(tabs) > 0: tm.set_active_tab(tabs[0]) return