mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-02 11:32:42 +00:00
90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
# ── tab_bar.py · kitty tab titles: repo dir, or the file nvim is editing ──
|
|
#
|
|
# kitty loads this file from the config dir and exposes `draw_title` as the
|
|
# `{custom}` field of tab_title_template (kitty/tab_bar.py:
|
|
# load_custom_draw_title). kitty still draws the powerline chrome; only the text
|
|
# inside a tab comes from here.
|
|
#
|
|
# A title is one of:
|
|
# 2 chezmoi <- repo the tab's cwd belongs to (dir name if no repo)
|
|
# 3 astrocore.lua <- nvim is the active process: the file it is editing
|
|
#
|
|
# No subprocesses, no timers: the repo root is found by walking up for `.git`,
|
|
# and the edited file comes from the window title nvim already sets
|
|
# (~/.config/nvim/lua/plugins/astrocore.lua, custom_title autocmd:
|
|
# "<file> | <org/repo>" or "<file> | Nvim", and "<org/repo>" / "Nvim" with no
|
|
# file). kitty repaints the tab bar whenever that title changes, so the tab
|
|
# tracks buffer switches for free.
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from typing import Any
|
|
|
|
# Nerd Font glyphs; VictorMono Nerd Font Mono covers both.
|
|
FOLDER = '\uf07b' # nf-fa-folder
|
|
NVIM = '\ue62b' # nf-custom-neovim
|
|
|
|
EDITORS = frozenset({'nvim', 'vim', 'nvim-qt'})
|
|
MAX_LEN = 28
|
|
|
|
# wd -> repo root (or ''), memoized: a working dir keeps its answer for the life
|
|
# of the kitty instance, so `git init` in an already-open dir needs a config
|
|
# reload (ctrl+shift+alt+, in the herdr host, ctrl+shift+f5 here) to show up.
|
|
_repo: dict[str, str] = {}
|
|
|
|
|
|
def draw_title(data: dict[str, Any]) -> str:
|
|
tab = data['tab']
|
|
label = ''
|
|
if tab.active_exe in EDITORS:
|
|
label = _nvim_file(data['title'])
|
|
if label:
|
|
return f'{data["index"]} {NVIM} {_elide(label)}'
|
|
wd = tab.active_wd
|
|
if wd:
|
|
label = os.path.basename(_repo_root(wd) or wd.rstrip('/'))
|
|
if wd == os.path.expanduser('~'):
|
|
label = '~'
|
|
return f'{data["index"]} {FOLDER} {_elide(label or data["title"])}'
|
|
|
|
|
|
def _repo_root(wd: str) -> str:
|
|
root = _repo.get(wd)
|
|
if root is None:
|
|
root = ''
|
|
path = wd
|
|
while True:
|
|
if os.path.exists(os.path.join(path, '.git')):
|
|
root = path
|
|
break
|
|
parent = os.path.dirname(path)
|
|
if parent == path:
|
|
break
|
|
path = parent
|
|
_repo[wd] = root
|
|
return root
|
|
|
|
|
|
def _nvim_file(title: str) -> str:
|
|
"""The file name out of an nvim window title, '' when it is editing none.
|
|
|
|
Handles this config's "<file> | <org/repo>" / "<file> | Nvim" and nvim's own
|
|
default "%t - Nvim" / "<file> (<dir>) - NVIM".
|
|
"""
|
|
text = title.strip()
|
|
for suffix in (' - NVIM', ' - Nvim', ' - nvim'):
|
|
if text.endswith(suffix):
|
|
text = text[: -len(suffix)]
|
|
text = text.split(' | ', 1)[0].strip()
|
|
if text.endswith(')') and ' (' in text:
|
|
text = text.split(' (', 1)[0].strip()
|
|
# Left with a bare repo slug ("org/repo") or the placeholder: no file open.
|
|
if not text or '/' in text or text.lower() == 'nvim':
|
|
return ''
|
|
return text
|
|
|
|
|
|
def _elide(label: str) -> str:
|
|
return label if len(label) <= MAX_LEN else label[: MAX_LEN - 1] + '…'
|