8a03cb5880
These are integrated in neovim now
218 lines
5.6 KiB
Python
218 lines
5.6 KiB
Python
# pyright: reportMissingImports=false
|
|
# pyright: reportUnknownVariableType=false
|
|
# pyright: reportUnknownParameterType=false
|
|
# pyright: reportUnknownArgumentType=false
|
|
# pyright: reportUnknownMemberType=false
|
|
|
|
import datetime
|
|
import time
|
|
import subprocess
|
|
import psutil
|
|
import os
|
|
|
|
from kitty.boss import get_boss
|
|
from kitty.fast_data_types import Screen, add_timer
|
|
from kitty.tab_bar import (
|
|
DrawData,
|
|
ExtraData,
|
|
Formatter,
|
|
TabBarData,
|
|
as_rgb,
|
|
draw_attributed_string,
|
|
draw_tab_with_powerline,
|
|
)
|
|
|
|
timer_id = None
|
|
|
|
UNPLUGGED_ICONS = {
|
|
10: "",
|
|
20: "",
|
|
30: "",
|
|
40: "",
|
|
50: "",
|
|
60: "",
|
|
70: "",
|
|
80: "",
|
|
90: "",
|
|
100: "",
|
|
}
|
|
PLUGGED_ICONS = {
|
|
1: "",
|
|
}
|
|
|
|
|
|
class WakaTime:
|
|
def __init__(self):
|
|
self.cache = None
|
|
self.cache_time = 0
|
|
self.cache_duration = 60 # Cache duration in seconds (1 minute)
|
|
self.cli_path = os.path.expanduser("~/.wakatime/wakatime-cli")
|
|
|
|
def get_today_time(self):
|
|
current_time = time.time()
|
|
if self.cache is None or (current_time - self.cache_time) > self.cache_duration:
|
|
# Run the command
|
|
result = subprocess.run(
|
|
[self.cli_path, "--today"], stdout=subprocess.PIPE, text=True
|
|
)
|
|
self.cache = result.stdout.strip()
|
|
self.cache_time = current_time
|
|
return self.cache
|
|
|
|
|
|
waka_time = WakaTime()
|
|
|
|
|
|
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]:
|
|
return [
|
|
# get_current_artist_title(),
|
|
# format_cell(get_wakatime_today()),
|
|
format_cell(get_date()),
|
|
format_cell(get_time()),
|
|
get_battery_level()["icon"],
|
|
]
|
|
|
|
|
|
def format_cell(data: dict[str, str]) -> str:
|
|
return f"{data['icon']} {data['text']}"
|
|
|
|
|
|
def _redraw_tab_bar(timer_id: int):
|
|
for tm in get_boss().all_tab_managers:
|
|
tm.mark_tab_bar_dirty()
|
|
|
|
|
|
def get_time():
|
|
now = datetime.datetime.now().strftime("%H:%M")
|
|
return {"icon": " ", "color": "#669bbc", "text": now}
|
|
|
|
|
|
def get_date():
|
|
today = datetime.date.today()
|
|
if today.weekday() < 5:
|
|
return {"icon": " ", "color": "#2a9d8f", "text": today.strftime("%e %b")}
|
|
else:
|
|
return {"icon": " ", "color": "#f2e8cf", "text": today.strftime("%e %b")}
|
|
|
|
|
|
def get_battery_level():
|
|
battery = psutil.sensors_battery()
|
|
if battery is None:
|
|
return {"icon": "", "text": "Battery info not available"}
|
|
|
|
battery_percentage = round(battery.percent)
|
|
charging = battery.power_plugged
|
|
icon: str = ""
|
|
|
|
if charging:
|
|
icon = PLUGGED_ICONS[1]
|
|
else:
|
|
for level in sorted(UNPLUGGED_ICONS.keys(), reverse=True):
|
|
if battery_percentage >= level:
|
|
icon = UNPLUGGED_ICONS[level]
|
|
break
|
|
|
|
return {"icon": icon, "text": f"{battery_percentage}%"}
|
|
|
|
|
|
def get_current_artist_title():
|
|
try:
|
|
# Run playerctl to get the artist, ignoring Firefox and KDE Connect
|
|
artist = (
|
|
subprocess.check_output(
|
|
[
|
|
"playerctl",
|
|
"-i",
|
|
"firefox,kdeconnect,plasma-browser-integration",
|
|
"metadata",
|
|
"artist",
|
|
]
|
|
)
|
|
.decode("utf-8")
|
|
.strip()
|
|
)
|
|
# Run playerctl to get the title, ignoring Firefox and KDE Connect
|
|
title = (
|
|
subprocess.check_output(
|
|
[
|
|
"playerctl",
|
|
"-i",
|
|
"firefox,kdeconnect,plasma-browser-integration",
|
|
"metadata",
|
|
"title",
|
|
]
|
|
)
|
|
.decode("utf-8")
|
|
.strip()
|
|
)
|
|
if title == "":
|
|
return " "
|
|
if artist != "":
|
|
return f" {artist} - {title}"
|
|
else:
|
|
return f" {title}"
|
|
except subprocess.CalledProcessError:
|
|
return " "
|
|
except FileNotFoundError:
|
|
return "playerctl is not installed"
|
|
|
|
|
|
def get_wakatime_today():
|
|
time_spent = waka_time.get_today_time()
|
|
return {"icon": " ", "text": time_spent}
|