mirror of
https://github.com/DefectingCat/dotfiles
synced 2025-07-15 16:51:36 +00:00
335 lines
8.7 KiB
Python
335 lines
8.7 KiB
Python
# import json
|
|
# import subprocess
|
|
# from collections import defaultdict
|
|
# from datetime import datetime, timezone
|
|
#
|
|
# from kitty.boss import get_boss
|
|
# from kitty.fast_data_types import Screen, add_timer
|
|
# from kitty.rgb import Color
|
|
# from kitty.tab_bar import (
|
|
# DrawData,
|
|
# ExtraData,
|
|
# Formatter,
|
|
# TabBarData,
|
|
# as_rgb,
|
|
# draw_attributed_string,
|
|
# draw_title,
|
|
# )
|
|
# from kitty.utils import color_as_int
|
|
#
|
|
# timer_id = None
|
|
#
|
|
# ICON = " "
|
|
# RIGHT_MARGIN = 1
|
|
# REFRESH_TIME = 15
|
|
#
|
|
# icon_fg = as_rgb(color_as_int(Color(255, 250, 205)))
|
|
# icon_bg = as_rgb(color_as_int(Color(47, 61, 68)))
|
|
# # OR icon_bg = as_rgb(0x2f3d44)
|
|
# bat_text_color = as_rgb(0x999F93)
|
|
# clock_color = as_rgb(0x7FBBB3)
|
|
# dnd_color = as_rgb(0x465258)
|
|
# sep_color = as_rgb(0x999F93)
|
|
# utc_color = as_rgb(color_as_int(Color(113, 115, 116)))
|
|
#
|
|
#
|
|
# # cells = [
|
|
# # (Color(113, 115, 116), dnd),
|
|
# # (Color(135, 192, 149), clock),
|
|
# # (Color(113, 115, 116), utc),
|
|
# # ]
|
|
#
|
|
#
|
|
# def calc_draw_spaces(*args) -> int:
|
|
# length = 0
|
|
# for i in args:
|
|
# if not isinstance(i, str):
|
|
# i = str(i)
|
|
# length += len(i)
|
|
# return length
|
|
#
|
|
#
|
|
# def _draw_icon(screen: Screen, index: int) -> int:
|
|
# if index != 1:
|
|
# return 0
|
|
#
|
|
# fg, bg = screen.cursor.fg, screen.cursor.bg
|
|
# screen.cursor.fg = icon_fg
|
|
# screen.cursor.bg = icon_bg
|
|
# screen.draw(ICON)
|
|
# screen.cursor.fg, screen.cursor.bg = fg, bg
|
|
# screen.cursor.x = len(ICON)
|
|
# return screen.cursor.x
|
|
#
|
|
#
|
|
# def _draw_left_status(
|
|
# draw_data: DrawData,
|
|
# screen: Screen,
|
|
# tab: TabBarData,
|
|
# before: int,
|
|
# max_title_length: int,
|
|
# index: int,
|
|
# is_last: bool,
|
|
# extra_data: ExtraData,
|
|
# ) -> int:
|
|
# # print(extra_data)
|
|
# if draw_data.leading_spaces:
|
|
# screen.draw(" " * draw_data.leading_spaces)
|
|
#
|
|
# # TODO: https://github.com/kovidgoyal/kitty/discussions/4447#discussioncomment-2463083
|
|
# # tm = get_boss().active_tab_manager
|
|
# # if tm is not None:
|
|
# # w = tm.active_window
|
|
# # if w is not None:
|
|
# # cwd = w.cwd_of_child or ''
|
|
# # log_error(cwd)
|
|
#
|
|
# draw_title(draw_data, screen, tab, index)
|
|
# trailing_spaces = min(max_title_length - 1, draw_data.trailing_spaces)
|
|
# max_title_length -= trailing_spaces
|
|
# extra = screen.cursor.x - before - max_title_length
|
|
# if extra > 0:
|
|
# screen.cursor.x -= extra + 1
|
|
# screen.draw("…")
|
|
# if trailing_spaces:
|
|
# screen.draw(" " * trailing_spaces)
|
|
# end = screen.cursor.x
|
|
# screen.cursor.bold = screen.cursor.italic = False
|
|
# screen.cursor.fg = 0
|
|
# if not is_last:
|
|
# screen.cursor.bg = as_rgb(color_as_int(draw_data.inactive_bg))
|
|
# screen.draw(draw_data.sep)
|
|
# screen.cursor.bg = 0
|
|
# return end
|
|
#
|
|
#
|
|
# def _get_dnd_status():
|
|
# result = subprocess.run("~/.dotfiles/bin/dnd -k",
|
|
# shell=True, capture_output=True)
|
|
# status = ""
|
|
#
|
|
# if result.stderr:
|
|
# raise subprocess.CalledProcessError(
|
|
# returncode=result.returncode, cmd=result.args, stderr=result.stderr
|
|
# )
|
|
#
|
|
# if result.stdout:
|
|
# status = result.stdout.decode("utf-8").strip()
|
|
#
|
|
# return status
|
|
#
|
|
#
|
|
# # more handy kitty tab_bar things:
|
|
# # REF: https://github.com/kovidgoyal/kitty/discussions/4447#discussioncomment-2183440
|
|
# def _draw_right_status(screen: Screen, is_last: bool) -> int:
|
|
# if not is_last:
|
|
# return 0
|
|
# # global timer_id
|
|
# # if timer_id is None:
|
|
# # timer_id = add_timer(_redraw_tab_bar, REFRESH_TIME, True)
|
|
#
|
|
# draw_attributed_string(Formatter.reset, screen)
|
|
#
|
|
# clock = datetime.now().strftime("%H:%M")
|
|
# utc = datetime.now(timezone.utc).strftime(" (UTC %H:%M)")
|
|
# dnd = _get_dnd_status()
|
|
#
|
|
# cells = []
|
|
# if dnd != "":
|
|
# cells.append((dnd_color, dnd))
|
|
# cells.append((sep_color, " ⋮ "))
|
|
#
|
|
# cells.append((clock_color, clock))
|
|
# cells.append((utc_color, utc))
|
|
#
|
|
# # right_status_length = calc_draw_spaces(dnd + " " + clock + " " + utc)
|
|
#
|
|
# right_status_length = RIGHT_MARGIN
|
|
# for cell in cells:
|
|
# right_status_length += len(str(cell[1]))
|
|
#
|
|
# draw_spaces = screen.columns - screen.cursor.x - right_status_length
|
|
#
|
|
# if draw_spaces > 0:
|
|
# screen.draw(" " * draw_spaces)
|
|
#
|
|
# screen.cursor.fg = 0
|
|
# for color, status in cells:
|
|
# screen.cursor.fg = color # as_rgb(color_as_int(color))
|
|
# screen.draw(status)
|
|
# screen.cursor.bg = 0
|
|
#
|
|
# if screen.columns - screen.cursor.x > right_status_length:
|
|
# screen.cursor.x = screen.columns - right_status_length
|
|
#
|
|
# return screen.cursor.x
|
|
#
|
|
#
|
|
# # REF: https://github.com/kovidgoyal/kitty/discussions/4447#discussioncomment-1940795
|
|
# # def _redraw_tab_bar():
|
|
# # tm = get_boss().active_tab_manager
|
|
# # if tm is not None:
|
|
# # tm.mark_tab_bar_dirty()
|
|
#
|
|
#
|
|
# def draw_tab(
|
|
# draw_data: DrawData,
|
|
# screen: Screen,
|
|
# tab: TabBarData,
|
|
# before: int,
|
|
# max_title_length: int,
|
|
# index: int,
|
|
# is_last: bool,
|
|
# extra_data: ExtraData,
|
|
# ) -> int:
|
|
#
|
|
# _draw_icon(screen, index)
|
|
# _draw_left_status(
|
|
# draw_data,
|
|
# screen,
|
|
# tab,
|
|
# before,
|
|
# max_title_length,
|
|
# index,
|
|
# is_last,
|
|
# extra_data,
|
|
# )
|
|
# _draw_right_status(
|
|
# screen,
|
|
# is_last,
|
|
# )
|
|
#
|
|
# return screen.cursor.x
|
|
#
|
|
|
|
import datetime
|
|
import json
|
|
import subprocess
|
|
from collections import defaultdict
|
|
|
|
from kitty.rgb import Color
|
|
from kitty.boss import get_boss
|
|
from kitty.fast_data_types import Screen
|
|
from kitty.tab_bar import (
|
|
DrawData,
|
|
ExtraData,
|
|
Formatter,
|
|
TabBarData,
|
|
as_rgb,
|
|
draw_attributed_string,
|
|
draw_tab_with_powerline,
|
|
draw_title
|
|
)
|
|
from kitty.utils import color_as_int
|
|
|
|
timer_id = None
|
|
|
|
|
|
def draw_tab(
|
|
draw_data: DrawData,
|
|
screen: Screen,
|
|
tab: TabBarData,
|
|
before: int,
|
|
max_title_length: int,
|
|
index: int,
|
|
is_last: bool,
|
|
extra_data: ExtraData,
|
|
) -> int:
|
|
global timer_id
|
|
|
|
# if timer_id is None:
|
|
# timer_id = add_timer(_redraw_tab_bar, 2.0, True)
|
|
draw_tab_with_powerline(
|
|
draw_data, screen, tab, before, max_title_length, index, is_last, extra_data
|
|
)
|
|
|
|
if is_last:
|
|
draw_right_status(draw_data, screen)
|
|
return screen.cursor.x
|
|
|
|
|
|
def draw_right_status(draw_data: DrawData, screen: Screen) -> None:
|
|
# The tabs may have left some formats enabled. Disable them now.
|
|
draw_attributed_string(Formatter.reset, screen)
|
|
cells = create_cells()
|
|
# Drop cells that wont fit
|
|
while True:
|
|
if not cells:
|
|
return
|
|
padding = screen.columns - screen.cursor.x - \
|
|
sum(len(c) + 3 for c in cells)
|
|
if padding >= 0:
|
|
break
|
|
cells = cells[1:]
|
|
|
|
if padding:
|
|
screen.draw(" " * padding)
|
|
|
|
tab_bg = as_rgb(int(draw_data.inactive_bg))
|
|
tab_fg = as_rgb(int(draw_data.inactive_fg))
|
|
default_bg = as_rgb(int(draw_data.default_bg))
|
|
for cell in cells:
|
|
# Draw the separator
|
|
if cell == cells[0]:
|
|
screen.cursor.fg = tab_bg
|
|
screen.draw("")
|
|
else:
|
|
screen.cursor.fg = default_bg
|
|
screen.cursor.bg = tab_bg
|
|
screen.draw("")
|
|
screen.cursor.fg = tab_fg
|
|
screen.cursor.bg = tab_bg
|
|
screen.draw(f" {cell} ")
|
|
|
|
|
|
def create_cells() -> list[str]:
|
|
now = datetime.datetime.now()
|
|
return [
|
|
# currently_playing(),
|
|
# get_headphone_battery_status(),
|
|
now.strftime("%d %b"),
|
|
now.strftime("%H:%M"),
|
|
]
|
|
|
|
|
|
def get_headphone_battery_status():
|
|
try:
|
|
battery_pct = int(subprocess.getoutput("headsetcontrol -b -c"))
|
|
except Exception:
|
|
status = ""
|
|
else:
|
|
if battery_pct < 0:
|
|
status = ""
|
|
else:
|
|
status = f"{battery_pct}% {''[battery_pct // 10]}"
|
|
return f" {status}"
|
|
|
|
|
|
STATE = defaultdict(lambda: "", {"Paused": "", "Playing": ""})
|
|
|
|
|
|
def currently_playing():
|
|
# TODO: Work out how to add python libraries so that I can query dbus directly
|
|
# For now, implemented in a separate python project: dbus-player-status
|
|
status = " "
|
|
data = {}
|
|
try:
|
|
data = json.loads(subprocess.getoutput("dbus-player-status"))
|
|
except ValueError:
|
|
pass
|
|
if data:
|
|
if "state" in data:
|
|
status = f"{status} {STATE[data['state']]}"
|
|
if "title" in data:
|
|
status = f"{status} {data['title']}"
|
|
if "artist" in data:
|
|
status = f"{status} - {data['artist']}"
|
|
else:
|
|
status = ""
|
|
return status
|
|
|
|
|
|
def _redraw_tab_bar(timer_id):
|
|
for tm in get_boss().all_tab_managers:
|
|
tm.mark_tab_bar_dirty()
|