507 lines
14 KiB
Nix
507 lines
14 KiB
Nix
#
|
|
# Use Waybar with our GUI.
|
|
#
|
|
# vim: et:ts=2:sw=2:
|
|
{
|
|
lib,
|
|
pkgs,
|
|
deprekages,
|
|
config,
|
|
...
|
|
}:
|
|
let
|
|
hostname = config.networking.hostName;
|
|
isSmallScreen = (hostname == "utol");
|
|
in
|
|
{
|
|
|
|
# Pull in some dependencies for our bar.
|
|
environment.systemPackages = with pkgs; [ networkmanagerapplet ];
|
|
|
|
# Enable the yubikey touch detector, for our icon.
|
|
programs.yubikey-touch-detector.enable = true;
|
|
|
|
#
|
|
# Set up our waybar configuration in home-manager.
|
|
#
|
|
home-manager.users.deprekated =
|
|
{ pkgs, config, ... }:
|
|
let
|
|
|
|
icons = rec {
|
|
calendar = " ";
|
|
clock = " ";
|
|
puclock = "";
|
|
cpu = "";
|
|
ram = "";
|
|
battery.charging = "";
|
|
battery.horizontal = [
|
|
" "
|
|
" "
|
|
" "
|
|
" "
|
|
" "
|
|
];
|
|
battery.vertical = [
|
|
""
|
|
""
|
|
""
|
|
""
|
|
""
|
|
""
|
|
""
|
|
""
|
|
""
|
|
""
|
|
];
|
|
battery.levels = battery.vertical;
|
|
network.disconnected = " ";
|
|
network.ethernet = " ";
|
|
network.strength = [
|
|
" "
|
|
" "
|
|
" "
|
|
" "
|
|
];
|
|
bluetooth.on = "";
|
|
bluetooth.off = "";
|
|
bluetooth.battery = "";
|
|
volume.source = "";
|
|
volume.muted = "";
|
|
volume.levels = [
|
|
""
|
|
""
|
|
""
|
|
];
|
|
idle = {
|
|
on = "<span color='#${colors.red}'></span>";
|
|
off = "";
|
|
};
|
|
vpn = " ";
|
|
music = {
|
|
playing = "";
|
|
paused = "";
|
|
stopped = "";
|
|
missing = "";
|
|
};
|
|
|
|
speed = {
|
|
slow = "";
|
|
medium = "";
|
|
fast = "";
|
|
};
|
|
};
|
|
colors = config.lib.stylix.colors;
|
|
|
|
# Create a TODO-list handler.
|
|
waybar-todos = pkgs.writeScriptBin "waybar-todos" ''
|
|
#!${pkgs.python3}/bin/python3
|
|
|
|
import subprocess
|
|
import json
|
|
|
|
def get_count(*filter):
|
|
return int(subprocess.run(['${pkgs.taskwarrior3}/bin/task', 'count', *filter], capture_output=True, text=True).stdout)
|
|
|
|
def get_tasks(*filter):
|
|
return subprocess.run(['${pkgs.taskwarrior3}/bin/task', 'ls', *filter], capture_output=True, text=True).stdout
|
|
|
|
priority = get_count("(+TODAY or +OVERDUE)", "priority:H")
|
|
due_today = get_count("+TODAY")
|
|
overdue = get_count("+OVERDUE")
|
|
|
|
overdue_color = ' color="#dc322f" ' if overdue else ' color="#93a1a1" '
|
|
overdue_text = "<span {overdue_color}> {overdue} </span>".format(overdue=overdue, overdue_color=overdue_color) if overdue else ""
|
|
|
|
priority_text = ' {priority} '.format(priority=priority) if priority else ""
|
|
|
|
today_color = "" if due_today else ' color="#93a1a1" '
|
|
|
|
data = {}
|
|
data['text'] = "{overdue_text}{priority_text}<span {today_color}> {due_today} </span>".format(overdue_text=overdue_text, due_today=due_today, today_color=today_color, priority_text=priority_text)
|
|
data['tooltip'] = get_tasks("(+TODAY or +OVERDUE)")
|
|
|
|
print(json.dumps(data))
|
|
'';
|
|
|
|
# From the Waybar wiki.
|
|
waybar-events = pkgs.writeScriptBin "waybar-events" ''
|
|
#!${pkgs.python3}/bin/python3
|
|
|
|
import calendar
|
|
import subprocess
|
|
import datetime
|
|
import json
|
|
import html
|
|
import sys
|
|
|
|
data = {}
|
|
|
|
today = datetime.date.today().strftime("%Y-%m-%d")
|
|
next_week = (datetime.date.today() +
|
|
datetime.timedelta(days=10)).strftime("%Y-%m-%d")
|
|
tomorrow = (datetime.date.today() +
|
|
datetime.timedelta(days=1)).strftime("%Y-%m-%d")
|
|
|
|
human_events = subprocess.check_output('khal list now ' + next_week, shell=True).decode('utf-8')
|
|
machine_events = subprocess.check_output('khal list now ' + next_week + ' -d "Holidays in United States" --once -f "{title}|{start-date}|{start-time}" -df ""', shell=True).decode('utf-8')
|
|
|
|
if not machine_events:
|
|
sys.exit(0)
|
|
|
|
next_event = machine_events.split("\n")[0]
|
|
event, date, time = next_event.split('|')
|
|
|
|
# Generate our hover-over text.
|
|
lines = human_events.split("\n")
|
|
new_lines = []
|
|
for line in lines:
|
|
if line.startswith("To hide observances") or (line == ""):
|
|
continue
|
|
|
|
clean_line = html.escape(line).split(" ::")[0]
|
|
if len(clean_line) and not clean_line[0] in ['0', '1', '2']:
|
|
clean_line = "\n<b><span color='#${colors.blue}'>"+clean_line+"</span></b>" if (',' in clean_line) else clean_line
|
|
|
|
new_lines.append(clean_line)
|
|
tooltip = "\n".join(new_lines).strip()
|
|
|
|
if tomorrow in date:
|
|
date = "tomorrow"
|
|
else:
|
|
weekday = datetime.datetime.fromisoformat(date).weekday()
|
|
date = calendar.day_name[weekday].lower()
|
|
|
|
|
|
# Add time suffixes when appropriate.
|
|
time_suffix = ""
|
|
if time:
|
|
time_suffix = " @ " + time
|
|
|
|
date_suffix = ""
|
|
if today not in date:
|
|
date_suffix = ", " + date
|
|
|
|
|
|
# In the typical case, display the next event.
|
|
data['text'] = html.escape(" " + event[0:30] + date_suffix + time_suffix)
|
|
|
|
# Display our nice, human-readable event ouptut on hover.
|
|
data['tooltip'] = tooltip
|
|
|
|
# Finally, send the data to Waybar.
|
|
print(json.dumps(data))
|
|
'';
|
|
|
|
waybar-title = pkgs.writeScriptBin "waybar-title" ''
|
|
#!${pkgs.bash}/bin/bash
|
|
niri msg --json focused-window | jq -c '{text: (if ((.title | length) > 40) then (.title[:38] + "…") else .title end), tooltip: .app_id}' | sed 's/&[ $]/\& /g'
|
|
'';
|
|
|
|
waybar-puck-countdown = pkgs.writeScriptBin "waybar-puck-countdown" ''
|
|
#!${pkgs.python3}/bin/python3
|
|
|
|
import json
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
now = datetime.now(timezone.utc)
|
|
puck_day = "2024-12-11 13:30:00-07:00"
|
|
puck_time = datetime.fromisoformat(puck_day)
|
|
until = puck_time - now
|
|
|
|
response = {
|
|
"text": f" {until.days}d {until.seconds // 60 // 60}h",
|
|
"tooltip": f"days until {puck_day}"
|
|
}
|
|
|
|
print(json.dumps(response))
|
|
'';
|
|
|
|
in
|
|
{
|
|
#
|
|
# Core Waybar settings.
|
|
#
|
|
programs.waybar = {
|
|
enable = true;
|
|
systemd.enable = true;
|
|
};
|
|
programs.waybar.settings.mainBar = {
|
|
layer = "top";
|
|
#mode = "overlay";
|
|
|
|
modules-left = [
|
|
"clock"
|
|
"clock#otherzone"
|
|
"mpd"
|
|
];
|
|
modules-center = [
|
|
"custom/title"
|
|
"wlr/taskbar"
|
|
];
|
|
modules-right = [
|
|
"tray"
|
|
"custom/events"
|
|
"privacy"
|
|
"custom/yubikey"
|
|
"wireplumber"
|
|
"custom/puckdown"
|
|
"battery"
|
|
];
|
|
|
|
battery = {
|
|
interval = 5;
|
|
format = "{icon} {capacity}%";
|
|
format-charging = "{icon} {capacity}% ${icons.battery.charging}";
|
|
format-icons = icons.battery.levels;
|
|
states.warning = 30;
|
|
states.critical = 15;
|
|
};
|
|
|
|
cpu = {
|
|
format = "${icons.cpu} {usage}% @ {avg_frequency:0.1f}GHz";
|
|
};
|
|
|
|
memory = {
|
|
format = "${icons.ram} {used:0.1f}G / {total:0.1f}G";
|
|
};
|
|
|
|
clock = {
|
|
interval = 1;
|
|
format = "${icons.clock} {:%H:%M %A, %B %d %Z}";
|
|
|
|
tooltip-format = "<tt>${icons.calendar}<u><b> {:%a, %Y-%m-%d}</b></u>\n\n{calendar}</tt>";
|
|
|
|
calendar = {
|
|
mode = "month";
|
|
format = {
|
|
weeks = "<b>W{}</b>";
|
|
months = "<span color='#${colors.magenta}'><b>{}</b></span>";
|
|
days = "<span color='#${colors.blue}'><b>{}</b></span>";
|
|
weekdays = "<span color='#${colors.cyan}'><b>{}</b></span>";
|
|
today = "<span color='#${colors.green}'><b>{}</b></span>";
|
|
};
|
|
};
|
|
};
|
|
|
|
"clock#otherzone" = {
|
|
interval = 1;
|
|
format = "${icons.puclock} {:%H:%M %Z}";
|
|
timezone = "Europe/Amsterdam";
|
|
tooltip-format = ''
|
|
<b><u>Homosexuality Statistics</u></b>
|
|
|
|
Homosexuality is <b><span color='#${colors.green}'>online</span></b>.
|
|
Homosexuality levels are <b><span color='#${colors.red}'>CRITICAL</span></b>.
|
|
'';
|
|
};
|
|
|
|
network = {
|
|
on-click = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor";
|
|
tooltip = false;
|
|
format-disconnected = icons.network.disconnected;
|
|
format-ethernet = "${icons.network.ethernet}";
|
|
format-wifi = "{icon} {essid}";
|
|
format-icons = icons.network.strength;
|
|
};
|
|
|
|
bluetooth = {
|
|
format = "{icon}";
|
|
format-disabled = "{icon}";
|
|
format-icons = {
|
|
inherit (icons.bluetooth) on off;
|
|
connected = icons.bluetooth.on;
|
|
};
|
|
format-connected = "{icon} {device_alias}";
|
|
};
|
|
"bluetooth#battery" = {
|
|
format = "";
|
|
format-connected-battery = "${icons.bluetooth.battery} {device_battery_percentage}%";
|
|
};
|
|
|
|
wireplumber = {
|
|
on-click = "${pkgs.pavucontrol}/bin/pavucontrol -t 1";
|
|
format = "{icon} {volume}%";
|
|
tooltip-format = "${icons.volume.source} {node_name}";
|
|
format-muted = "${icons.volume.muted}";
|
|
format-icons = icons.volume.levels;
|
|
reverse-scrolling = 1;
|
|
};
|
|
|
|
# Displays an icon when our yubikey is waiting for touch.
|
|
"custom/yubikey" = {
|
|
exec = ./waybar-yubikey.sh;
|
|
return-type = "json";
|
|
};
|
|
|
|
"custom/events" = {
|
|
exec = "${waybar-events}/bin/waybar-events";
|
|
format = "{}";
|
|
tooltip = true;
|
|
return-type = "json";
|
|
interval = 60;
|
|
on-click = "${pkgs.wezterm}/bin/wezterm start ikhal";
|
|
};
|
|
|
|
"custom/title" = {
|
|
exec = "${waybar-title}/bin/waybar-title";
|
|
format = "{}";
|
|
tooltip = true;
|
|
return-type = "json";
|
|
interval = 1;
|
|
};
|
|
|
|
"custom/puckdown" = {
|
|
exec = "${waybar-puck-countdown}/bin/waybar-puck-countdown";
|
|
format = "{}";
|
|
tooltip = true;
|
|
return-type = "json";
|
|
interval = 60 * 5;
|
|
};
|
|
|
|
"wlr/taskbar" = {
|
|
format = "{icon}";
|
|
tooltip-format = "{app_id}";
|
|
|
|
on-click = "activate";
|
|
};
|
|
|
|
tray = {
|
|
icon-size = 21;
|
|
spacing = 10;
|
|
};
|
|
|
|
# Display indicators when we're sharing video or audio.
|
|
privacy = {
|
|
icon-spacing = 4;
|
|
icon-size = 18;
|
|
transition-duration = 250;
|
|
modules = [
|
|
{
|
|
type = "screenshare";
|
|
tooltip = false;
|
|
tooltip-icon-size = 24;
|
|
}
|
|
{
|
|
type = "audio-out";
|
|
tooltip = false;
|
|
tooltip-icon-size = 24;
|
|
}
|
|
{
|
|
type = "audio-in";
|
|
tooltip = false;
|
|
tooltip-icon-size = 24;
|
|
}
|
|
];
|
|
};
|
|
|
|
mpd = {
|
|
on-click = "mpc toggle";
|
|
format = "${icons.music.playing} {artist} - {title}";
|
|
format-paused = "${icons.music.paused} {artist} - {title}";
|
|
format-stopped = "";
|
|
format-disconnected = "${icons.music.missing}";
|
|
tooltip-format = "${icons.music.playing} {artist} - {title}";
|
|
max-length = 60;
|
|
};
|
|
|
|
idle_inhibitor = {
|
|
format = "{icon}";
|
|
format-icons = {
|
|
activated = icons.idle.on;
|
|
deactivated = icons.idle.off;
|
|
};
|
|
|
|
tooltip-format-activated = "System <span color='#${colors.orange}'><b>blocked</b></span> from going idle.";
|
|
tooltip-format-deactivated = "System <span color='#${colors.green}'><b>allowed</b></span> to go idle.";
|
|
};
|
|
};
|
|
stylix.targets.waybar.enable = false;
|
|
programs.waybar.style =
|
|
let
|
|
colors = config.lib.stylix.colors;
|
|
modules = s: "${s ".modules-left"}, ${s ".modules-center"}, ${s ".modules-right"}";
|
|
module = s: modules (m: "${m} > ${s} > *");
|
|
in
|
|
''
|
|
* {
|
|
border: none;
|
|
font-family: ${config.stylix.fonts.monospace.name};
|
|
font-weight: 400;
|
|
font-size: ${if isSmallScreen then "17" else toString config.stylix.fonts.sizes.desktop}px;
|
|
color: #${colors.base06};
|
|
}
|
|
|
|
window#waybar {
|
|
background: #${colors.base00};
|
|
}
|
|
|
|
#taskbar button {
|
|
padding: 0 0.4em;
|
|
}
|
|
|
|
#taskbar button.active {
|
|
background: #${colors.base01};
|
|
}
|
|
|
|
#tray image,
|
|
#taskbar image {
|
|
-gtk-icon-transform: scale(0.75);
|
|
margin: -5px -4px;
|
|
padding: 0px 2px;
|
|
}
|
|
|
|
${modules lib.id} {
|
|
margin: 0;
|
|
}
|
|
|
|
${module "*"} {
|
|
padding: 0 5px;
|
|
margin: 0;
|
|
font-size: 75%;
|
|
}
|
|
|
|
${module ":not(:first-child)"} {
|
|
border-left: 1px solid #${colors.base01};
|
|
}
|
|
|
|
${module ":not(:last-child)"} {
|
|
border-right: 1px solid #${colors.base01};
|
|
}
|
|
|
|
#battery.charging {
|
|
color: #${colors.green};
|
|
}
|
|
|
|
#battery.warning:not(.charging) {
|
|
color: #${colors.yellow};
|
|
}
|
|
|
|
#battery.critical:not(.charging) {
|
|
animation: critical-blink steps(8) 1s infinite alternate;
|
|
}
|
|
|
|
@keyframes critical-blink {
|
|
to {
|
|
color: #${colors.red};
|
|
}
|
|
}
|
|
'';
|
|
|
|
#
|
|
# Restart waybar when niri starts.
|
|
#
|
|
programs.niri.settings.spawn-at-startup = [
|
|
{
|
|
command = [
|
|
"systemctl"
|
|
"--user"
|
|
"restart"
|
|
"waybar"
|
|
];
|
|
}
|
|
{ command = [ "nm-applet" ]; }
|
|
];
|
|
};
|
|
}
|