2021-07-17 14:10:02 +02:00
|
|
|
|
{ config, lib, nixosConfig, pkgs, ... }:
|
|
|
|
|
let
|
2022-05-01 18:25:21 +02:00
|
|
|
|
inherit ((import ../common.nix).colorschemes) solarized;
|
|
|
|
|
|
2021-07-17 14:10:02 +02:00
|
|
|
|
watchUserUnitState = unit: started: stopped: pkgs.writeShellScript "watch-user-unit-${unit}-state" ''
|
|
|
|
|
${pkgs.systemd}/bin/journalctl --user -u ${unit} -t systemd -o cat -f \
|
|
|
|
|
| ${pkgs.gnugrep}/bin/grep --line-buffered -Eo '^(Started|Stopped)' \
|
|
|
|
|
| ${pkgs.jq}/bin/jq --unbuffered -Rc 'if . == "Started" then ${builtins.toJSON started} else ${builtins.toJSON stopped} end'
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
toggleUserUnitState = unit: pkgs.writeShellScript "toggle-user-unit-${unit}-state" ''
|
|
|
|
|
if ${pkgs.systemd}/bin/systemctl --user show ${unit} | ${pkgs.gnugrep}/bin/grep -q ActiveState=active; then
|
|
|
|
|
${pkgs.systemd}/bin/systemctl --user stop ${unit}
|
|
|
|
|
else
|
|
|
|
|
${pkgs.systemd}/bin/systemctl --user start ${unit}
|
|
|
|
|
fi
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
# nerd fonts are abusing arabic which breaks latin text
|
|
|
|
|
# context: https://github.com/Alexays/Waybar/issues/628
|
|
|
|
|
lrm = "‎";
|
|
|
|
|
|
|
|
|
|
# for fine-grained control over spacing
|
|
|
|
|
thinsp = " ";
|
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
# home-manager’s waybar module performs additional checks that are overly strict
|
|
|
|
|
xdg.configFile."waybar/config".text = lib.generators.toJSON { } {
|
|
|
|
|
layer = "top";
|
|
|
|
|
position = "top";
|
|
|
|
|
height = 24;
|
|
|
|
|
|
|
|
|
|
modules-center = [ ];
|
|
|
|
|
modules-left = [
|
|
|
|
|
"sway/workspaces"
|
|
|
|
|
"sway/mode"
|
|
|
|
|
];
|
|
|
|
|
modules-right = [
|
|
|
|
|
"tray"
|
|
|
|
|
"custom/screencast"
|
|
|
|
|
"custom/redshift"
|
|
|
|
|
"idle_inhibitor"
|
|
|
|
|
"backlight"
|
|
|
|
|
"mpd"
|
|
|
|
|
"pulseaudio"
|
|
|
|
|
"network"
|
|
|
|
|
"custom/vpn"
|
|
|
|
|
"memory"
|
|
|
|
|
"cpu"
|
|
|
|
|
"temperature"
|
|
|
|
|
"battery"
|
|
|
|
|
"clock"
|
2021-07-17 16:13:45 +02:00
|
|
|
|
"custom/calendar"
|
2022-05-01 18:25:21 +02:00
|
|
|
|
"custom/notification"
|
2021-07-17 14:10:02 +02:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
"sway/workspaces" = {
|
|
|
|
|
disable-scroll = true;
|
|
|
|
|
};
|
|
|
|
|
"sway/mode" = {
|
|
|
|
|
format = "{}";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
tray = {
|
|
|
|
|
spacing = 5;
|
|
|
|
|
};
|
|
|
|
|
"custom/redshift" = {
|
|
|
|
|
exec = watchUserUnitState
|
|
|
|
|
"gammastep"
|
|
|
|
|
{ class = "active"; }
|
|
|
|
|
{ class = "inactive"; };
|
|
|
|
|
on-click = toggleUserUnitState "gammastep";
|
|
|
|
|
return-type = "json";
|
|
|
|
|
format = "";
|
|
|
|
|
tooltip = false;
|
|
|
|
|
};
|
|
|
|
|
idle_inhibitor = {
|
|
|
|
|
format = "{icon}";
|
|
|
|
|
format-icons = {
|
|
|
|
|
activated = " ";
|
|
|
|
|
deactivated = " ";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
"custom/screencast" = {
|
2021-08-05 13:23:07 +02:00
|
|
|
|
exec = pkgs.writeScript "screencast-monitor" /* python */ ''
|
2021-07-17 14:10:02 +02:00
|
|
|
|
#!${pkgs.python3}/bin/python3
|
|
|
|
|
import subprocess
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
active_outputs = 0
|
|
|
|
|
|
|
|
|
|
with subprocess.Popen(
|
|
|
|
|
["${pkgs.coreutils}/bin/stdbuf", "-o0", "${nixosConfig.services.pipewire.package}/bin/pw-link", "-m", "-o", "xdg-desktop-portal-wlr"],
|
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
|
text=True,
|
|
|
|
|
) as proc:
|
|
|
|
|
for line in proc.stdout:
|
|
|
|
|
action = line.split(" ")[0]
|
|
|
|
|
if action == "=" or action == "+":
|
|
|
|
|
active_outputs += 1
|
|
|
|
|
elif action == "-":
|
|
|
|
|
active_outputs -= 1
|
|
|
|
|
else:
|
|
|
|
|
print(f"Invalid action {action} (in line {line})", file=sys.stderr)
|
|
|
|
|
|
|
|
|
|
if active_outputs > 0:
|
|
|
|
|
print("${lrm} ")
|
|
|
|
|
else:
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
sys.stdout.flush()
|
|
|
|
|
'';
|
|
|
|
|
format = "{}";
|
|
|
|
|
tooltip = false;
|
|
|
|
|
};
|
|
|
|
|
backlight = {
|
|
|
|
|
format = "{percent}% {icon}";
|
|
|
|
|
format-icons = [ " " " " " " " " " " " " " " ];
|
|
|
|
|
on-scroll-up = "${pkgs.brightnessctl}/bin/brightnessctl -q set +5%";
|
|
|
|
|
on-scroll-down = "${pkgs.brightnessctl}/bin/brightnessctl -q set 5%-";
|
|
|
|
|
};
|
|
|
|
|
mpd = {
|
|
|
|
|
server = config.services.mpd.network.listenAddress;
|
|
|
|
|
format = "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} – {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ";
|
|
|
|
|
format-disconnected = "Disconnected ";
|
|
|
|
|
format-stopped = "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ";
|
|
|
|
|
unknown-tag = "N/A";
|
|
|
|
|
interval = 2;
|
|
|
|
|
tooltip-format = "MPD (connected)";
|
|
|
|
|
tooltip-format-disconnected = "MPD (disconnected)";
|
|
|
|
|
on-scroll-up = "${pkgs.mpc_cli}/bin/mpc -q -h ${config.services.mpd.network.listenAddress} volume +2";
|
|
|
|
|
on-scroll-down = "${pkgs.mpc_cli}/bin/mpc -q -h ${config.services.mpd.network.listenAddress} volume -2";
|
2021-08-19 22:22:08 +02:00
|
|
|
|
title-len = 48;
|
|
|
|
|
artist-len = 24;
|
2021-07-17 14:10:02 +02:00
|
|
|
|
consume-icons = {
|
|
|
|
|
on = " ";
|
|
|
|
|
};
|
|
|
|
|
random-icons = {
|
|
|
|
|
off = "劣 ";
|
|
|
|
|
on = "列 ";
|
|
|
|
|
};
|
|
|
|
|
repeat-icons = {
|
|
|
|
|
on = "凌 ";
|
|
|
|
|
};
|
|
|
|
|
single-icons = {
|
|
|
|
|
on = "綾 ";
|
|
|
|
|
};
|
|
|
|
|
state-icons = {
|
|
|
|
|
paused = "";
|
|
|
|
|
playing = "契";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
pulseaudio = {
|
|
|
|
|
format = "{volume}% {icon} {format_source}";
|
|
|
|
|
format-bluetooth = "{volume}% {icon} {format_source}";
|
|
|
|
|
format-bluetooth-muted = "${lrm}ﱝ${lrm} {icon} {format_source}";
|
|
|
|
|
format-muted = "${lrm}ﱝ${lrm} {format_source}";
|
|
|
|
|
format-source = "{volume}% ${thinsp}";
|
|
|
|
|
format-source-muted = "${thinsp}";
|
|
|
|
|
format-icons = {
|
|
|
|
|
car = " ";
|
|
|
|
|
default = [ "奄" "奔" "墳" ];
|
|
|
|
|
hands-free = " ";
|
|
|
|
|
headphone = " ";
|
|
|
|
|
headset = " ";
|
|
|
|
|
phone = " ";
|
|
|
|
|
portable = " ";
|
|
|
|
|
};
|
2021-12-21 21:50:45 +01:00
|
|
|
|
on-click = "${pkgs.pavucontrol}/bin/pavucontrol";
|
|
|
|
|
on-click-right = "${pkgs.helvum}/bin/helvum";
|
2021-07-17 14:10:02 +02:00
|
|
|
|
};
|
|
|
|
|
network = {
|
|
|
|
|
format-wifi = "{essid} ({signalStrength}%) 直 ";
|
2021-10-27 19:42:51 +02:00
|
|
|
|
format-ethernet = "{ipaddr}/{cidr} ";
|
2021-07-17 14:10:02 +02:00
|
|
|
|
format-linked = "{ifname} (No IP) ";
|
|
|
|
|
format-disconnected = "Disconnected ⚠ ";
|
|
|
|
|
format-alt = "{ifname}: {ipaddr}/{cidr}";
|
|
|
|
|
tooltip = false;
|
2022-07-06 01:09:59 +02:00
|
|
|
|
on-click-right = "foot -e ${pkgs.networkmanager}/bin/nmtui";
|
2021-07-17 14:10:02 +02:00
|
|
|
|
};
|
|
|
|
|
"custom/vpn" = {
|
|
|
|
|
interval = 10;
|
|
|
|
|
exec = pkgs.writeShellScript "vpn-state" ''
|
|
|
|
|
${pkgs.iproute}/bin/ip -j link \
|
|
|
|
|
| ${pkgs.jq}/bin/jq --unbuffered --compact-output '
|
2022-09-30 12:02:46 +02:00
|
|
|
|
[[.[].ifname | select(. | startswith("mlv"))][] | sub("mlv-"; "") + " ${thinsp}"] as $conns
|
2021-07-17 14:10:02 +02:00
|
|
|
|
| { text: ($conns[0] // ""), class: (if $conns | length > 0 then "connected" else "disconnected" end) }'
|
|
|
|
|
'';
|
|
|
|
|
return-type = "json";
|
|
|
|
|
format = "{}";
|
|
|
|
|
tooltip = false;
|
|
|
|
|
};
|
|
|
|
|
memory = {
|
|
|
|
|
interval = 2;
|
|
|
|
|
format = "{:2}% ";
|
|
|
|
|
};
|
|
|
|
|
cpu = {
|
|
|
|
|
interval = 2;
|
|
|
|
|
format = "{usage:2}% ";
|
|
|
|
|
tooltip = false;
|
|
|
|
|
};
|
|
|
|
|
temperature = {
|
|
|
|
|
critical-threshold = 80;
|
|
|
|
|
format = "{temperatureC}°C {icon}";
|
|
|
|
|
format-icons = [ "" "" "" "" "" ];
|
2022-01-20 18:21:36 +01:00
|
|
|
|
};
|
2021-07-17 14:10:02 +02:00
|
|
|
|
battery = {
|
|
|
|
|
interval = 5;
|
|
|
|
|
format = "{capacity}% {icon}";
|
|
|
|
|
format-charging = "{capacity}% ";
|
2021-10-29 19:25:11 +02:00
|
|
|
|
format-plugged = "{capacity}% ${lrm}ﮣ";
|
2021-07-17 14:10:02 +02:00
|
|
|
|
format-alt = "{time} {icon}";
|
|
|
|
|
format-icons = [ "" "" "" "" "" "" "" "" "" "" "" ];
|
|
|
|
|
states = {
|
|
|
|
|
critical = 15;
|
|
|
|
|
good = 95;
|
|
|
|
|
warning = 30;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
clock = {
|
|
|
|
|
format = "{:%H:%M %Z}";
|
|
|
|
|
format-alt = "{:%Y-%m-%d (%a)}";
|
|
|
|
|
tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
|
|
|
|
|
};
|
2021-07-17 16:13:45 +02:00
|
|
|
|
"custom/calendar" = {
|
|
|
|
|
interval = 300;
|
2021-08-05 13:23:07 +02:00
|
|
|
|
exec = pkgs.writeScript "calendar" /* python */ ''
|
2021-07-17 16:13:45 +02:00
|
|
|
|
#!${pkgs.python3}/bin/python3
|
2022-04-13 11:54:11 +02:00
|
|
|
|
import html
|
2021-07-17 16:13:45 +02:00
|
|
|
|
import json
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def khal(args):
|
2022-07-07 18:03:50 +02:00
|
|
|
|
completed = subprocess.run(["khal"] + args, capture_output=True)
|
2021-07-17 16:13:45 +02:00
|
|
|
|
assert completed.returncode == 0
|
|
|
|
|
return completed.stdout.decode("utf-8")
|
|
|
|
|
|
|
|
|
|
|
2021-07-29 06:31:59 +02:00
|
|
|
|
events_today = khal(["list", "today", "today", "-df", "", "-f", "{title}"]).rstrip().split("\n")
|
2022-04-13 11:54:11 +02:00
|
|
|
|
events_2d = (
|
|
|
|
|
html.escape(
|
|
|
|
|
khal(
|
|
|
|
|
[
|
|
|
|
|
"list",
|
|
|
|
|
"today",
|
|
|
|
|
"tomorrow",
|
|
|
|
|
"-df",
|
|
|
|
|
"WAYBARSTARTKHAL{name}, {date}WAYBARENDKHAL",
|
|
|
|
|
]
|
|
|
|
|
).rstrip()
|
|
|
|
|
)
|
|
|
|
|
.replace("WAYBARSTARTKHAL", "<b>")
|
|
|
|
|
.replace("WAYBARENDKHAL", "</b>")
|
|
|
|
|
)
|
2021-07-17 16:13:45 +02:00
|
|
|
|
|
2022-07-08 11:23:38 +02:00
|
|
|
|
if events_today == [""]:
|
2021-07-18 08:38:05 +02:00
|
|
|
|
events_today = []
|
|
|
|
|
|
2021-07-17 16:13:45 +02:00
|
|
|
|
if len(events_today) == 0:
|
|
|
|
|
text = " "
|
|
|
|
|
else:
|
|
|
|
|
text = f"{len(events_today)} "
|
|
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
json.dumps(
|
|
|
|
|
{
|
|
|
|
|
"class": "active" if len(events_today) > 0 else "",
|
|
|
|
|
"text": text,
|
|
|
|
|
"tooltip": events_2d,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
'';
|
|
|
|
|
return-type = "json";
|
|
|
|
|
format = "{}";
|
|
|
|
|
};
|
2022-05-01 18:25:21 +02:00
|
|
|
|
"custom/notification" = {
|
|
|
|
|
tooltip = false;
|
|
|
|
|
format = "{icon}";
|
|
|
|
|
format-icons = {
|
|
|
|
|
notification = "${thinsp}";
|
|
|
|
|
none = "${thinsp}";
|
|
|
|
|
dnd-notification = "${thinsp}";
|
|
|
|
|
dnd-none = "${thinsp}";
|
|
|
|
|
};
|
|
|
|
|
return-type = "json";
|
2022-05-31 14:35:00 +02:00
|
|
|
|
exec = "${pkgs.swaynotificationcenter}/bin/swaync-client -swb";
|
|
|
|
|
on-click = "${pkgs.swaynotificationcenter}/bin/swaync-client -t -sw";
|
|
|
|
|
on-click-right = "${pkgs.swaynotificationcenter}/bin/swaync-client -d -sw";
|
2022-05-01 18:25:21 +02:00
|
|
|
|
escape = true;
|
|
|
|
|
};
|
2021-07-17 14:10:02 +02:00
|
|
|
|
};
|
|
|
|
|
xdg.configFile."waybar/style.css".source = pkgs.substituteAll ({
|
|
|
|
|
src = ./waybar.css;
|
2022-05-01 18:25:21 +02:00
|
|
|
|
} // solarized);
|
2021-07-17 14:10:02 +02:00
|
|
|
|
|
|
|
|
|
systemd.user.services.waybar = {
|
|
|
|
|
Unit = {
|
|
|
|
|
Description = "Highly customizable Wayland bar for Sway and Wlroots based compositors.";
|
|
|
|
|
Documentation = "https://github.com/Alexays/Waybar/wiki/";
|
|
|
|
|
PartOf = [ "sway-session.target" ];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Install.WantedBy = [ "sway-session.target" ];
|
|
|
|
|
|
|
|
|
|
Service = {
|
|
|
|
|
# ensure sway is already started, otherwise workspaces will not work
|
|
|
|
|
ExecStartPre = "${config.wayland.windowManager.sway.package}/bin/swaymsg";
|
|
|
|
|
ExecStart = "${pkgs.waybar}/bin/waybar";
|
|
|
|
|
ExecReload = "${pkgs.utillinux}/bin/kill -SIGUSR2 $MAINPID";
|
|
|
|
|
Restart = "on-failure";
|
|
|
|
|
RestartSec = "1s";
|
|
|
|
|
};
|
|
|
|
|
};
|
2021-08-28 16:39:37 +02:00
|
|
|
|
|
|
|
|
|
services.blueman-applet.enable = lib.mkIf nixosConfig.sbruder.full true;
|
2021-07-17 14:10:02 +02:00
|
|
|
|
}
|