initial commit
All checks were successful
Deploy docs / build-and-deploy (push) Successful in 3s

This commit is contained in:
sid 2026-02-23 20:34:35 +01:00
commit 95a533c876
451 changed files with 18255 additions and 0 deletions

View file

@ -0,0 +1,133 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.waybar;
clock = {
format = mkDefault "{:%a %d %b %H:%M}";
tooltip-format = mkDefault "<tt><small>{calendar}</small></tt>";
timezone = mkDefault "Europe/Berlin";
locale = mkDefault "en_US.UTF-8";
calendar = {
mode = mkDefault "year";
mode-mon-col = mkDefault 3;
weeks-pos = mkDefault "right";
on-scroll = mkDefault 1;
};
actions = {
on-click-right = mkDefault "mode";
on-click-forward = mkDefault "tz_up";
on-click-backward = mkDefault "tz_down";
on-scroll-up = mkDefault "shift_up";
on-scroll-down = mkDefault "shift_down";
};
};
"hyprland/workspaces" = {
active-only = mkDefault false;
all-outputs = mkDefault false;
format = mkDefault "{name}";
on-click = mkDefault "activate";
on-scroll-up = mkDefault "hyprctl dispatch workspace e-1";
on-scroll-down = mkDefault "hyprctl dispatch workspace e+1";
};
keyboard-state = {
numlock = mkDefault true;
capslock = mkDefault true;
scrolllock = mkDefault true;
format = {
scrolllock = mkDefault "S ";
capslock = mkDefault "C ";
numlock = mkDefault "N";
};
};
"hyprland/language" = {
format = mkDefault "{}";
format-en = mkDefault "us";
format-de = mkDefault "de";
# TODO: switch language on click
};
# Add your custom modules here
"custom/newsboat" = import ./modules/newsboat.nix { inherit lib pkgs; };
"pulseaudio#input" = import ./modules/pulseaudio/input.nix { inherit lib pkgs; };
"pulseaudio#output" = import ./modules/pulseaudio/output.nix { inherit lib pkgs; };
battery = import ./modules/battery.nix { inherit lib; };
bluetooth = import ./modules/bluetooth.nix { inherit lib; };
cpu = import ./modules/cpu.nix { inherit lib; };
disk = import ./modules/disk.nix { inherit lib; };
memory = import ./modules/memory.nix { inherit lib; };
network = import ./modules/network.nix { inherit lib; };
wireplumber = import ./modules/wireplumber.nix { inherit lib; };
inherit (lib) mkDefault mkIf;
in
{
imports = [
./modules/timer # TODO: Do not use imports. Move to let-in-block.
];
config = mkIf cfg.enable {
home.packages = with pkgs; [ font-awesome ];
programs.waybar = {
systemd.enable = mkDefault true;
settings = {
mainBar = {
output = mkDefault "";
modules-left = mkDefault [
"hyprland/workspaces"
"keyboard-state"
"hyprland/language"
];
modules-center = mkDefault [ "clock" ];
modules-right = mkDefault [
"network"
"cpu"
"memory"
"disk"
"pulseaudio#input"
"pulseaudio#output"
"tray"
];
inherit
"custom/newsboat"
"hyprland/language"
"hyprland/workspaces"
"pulseaudio#input"
"pulseaudio#output"
battery
bluetooth
clock
cpu
disk
keyboard-state
memory
network
wireplumber
;
};
otherBar = {
output = with cfg.settings.mainBar; if (output != "") then "!${output}" else "nowhere";
modules-left = mkDefault [
"hyprland/workspaces"
];
modules-center = mkDefault [ "clock" ];
inherit
"hyprland/workspaces"
clock
;
};
};
};
};
}

View file

@ -0,0 +1,28 @@
# battery
{ lib, ... }:
let
inherit (lib) mkDefault;
in
{
interval = mkDefault 10;
states = {
warning = mkDefault 20;
critical = mkDefault 10;
};
format = mkDefault "{icon} {capacity}";
format-icons = mkDefault [
""
""
""
""
""
];
tooltip-format = mkDefault ''
{timeTo}
Capacity: {capacity}%
Power Draw: {power} W
Charge Cycles: {cycles}
Health: {health}%
'';
}

View file

@ -0,0 +1,20 @@
# bluetooth
{ lib, ... }:
let
inherit (lib) mkDefault;
in
{
format = mkDefault " {status}";
format-connected = mkDefault " {device_alias}";
format-connected-battery = mkDefault " {device_alias} {device_battery_percentage}%";
format-disabled = mkDefault "";
format-off = mkDefault "";
format-on = mkDefault "";
max-length = mkDefault 12;
on-click = "bluetoothctl power off";
tooltip-format = mkDefault "{controller_alias}\t{controller_address}\n\n{num_connections} connected";
tooltip-format-connected = mkDefault "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}";
tooltip-format-enumerate-connected = mkDefault "{device_alias}\t{device_address}";
tooltip-format-enumerate-connected-battery = mkDefault "{device_alias}\t{device_address}\t{device_battery_percentage}%";
}

View file

@ -0,0 +1,25 @@
# cpu
{ lib, ... }:
let
inherit (lib) mkDefault;
in
{
interval = mkDefault 10;
format = mkDefault " {usage}";
tooltip-format = mkDefault ''
CPU Load: {load}
CPU Usage: {usage}%
Core 0 Usage: {usage0}%
Core 1 Usage: {usage1}%
Core 2 Usage: {usage2}%
Core 3 Usage: {usage3}%
Core 4 Usage: {usage4}%
Core 5 Usage: {usage5}%
Core 6 Usage: {usage6}%
Core 7 Usage: {usage7}%
Avg Frequency: {avg_frequency} GHz
Max Frequency: {max_frequency} GHz
Min Frequency: {min_frequency} GHz
'';
}

View file

@ -0,0 +1,11 @@
# disk
{ lib, ... }:
let
inherit (lib) mkDefault;
in
{
interval = mkDefault 3600;
format = mkDefault " {percentage_used}";
path = mkDefault "/";
}

View file

@ -0,0 +1,18 @@
# memory
{ lib, ... }:
let
inherit (lib) mkDefault;
in
{
interval = mkDefault 10;
format = mkDefault " {percentage}";
tooltip-format = mkDefault ''
Total Memory: {total} GiB
Used Memory: {used} GiB ({percentage}%)
Available Memory: {avail} GiB
Total Swap: {swapTotal} GiB
Used Swap: {swapUsed} GiB ({swapPercentage}%)
Available Swap: {swapAvail} GiB
'';
}

View file

@ -0,0 +1,48 @@
# network
{ lib, ... }:
let
inherit (lib) mkDefault;
in
{
interval = mkDefault 10;
format-wifi = mkDefault " {signalStrength}";
format-ethernet = mkDefault "";
format-disconnected = mkDefault ""; # An empty format will hide the module.
tooltip-format = mkDefault ''
Interface: {ifname}
IP Address: {ipaddr}
Gateway: {gwaddr}
Netmask: {netmask}
CIDR: {cidr}
ESSID: {essid}
Signal: {signaldBm} dBm / {signalStrength}%
Frequency: {frequency} GHz
Bandwidth Up: {bandwidthUpBits} / {bandwidthUpBytes}
Bandwidth Down: {bandwidthDownBits} / {bandwidthDownBytes}
Total Bandwidth: {bandwidthTotalBits} / {bandwidthTotalBytes}
Icon: {icon}
'';
tooltip-format-wifi = mkDefault ''
Interface: {ifname}
IP Address: {ipaddr}/{cidr}
Gateway: {gwaddr}
Netmask: {netmask}
ESSID: {essid}
Signal: {signaldBm} dBm / {signalStrength}%
Frequency: {frequency} GHz
Bandwidth Up: {bandwidthUpBits} / {bandwidthUpBytes}
Bandwidth Down: {bandwidthDownBits} / {bandwidthDownBytes}
Total Bandwidth: {bandwidthTotalBits} / {bandwidthTotalBytes}
'';
tooltip-format-ethernet = mkDefault ''
Interface: {ifname}
IP Address: {ipaddr}/{cidr}
Gateway: {gwaddr}
Netmask: {netmask}
Bandwidth Up: {bandwidthUpBits} / {bandwidthUpBytes}
Bandwidth Down: {bandwidthDownBits} / {bandwidthDownBytes}
Total Bandwidth: {bandwidthTotalBits} / {bandwidthTotalBytes}
'';
tooltip-format-disconnected = mkDefault "Disconnected";
}

View file

@ -0,0 +1,29 @@
# custom/newsboat
{
lib,
pkgs,
...
}:
let
newsboat-print-unread =
let
newsboat = "${pkgs.newsboat}/bin/newsboat";
in
(pkgs.writeShellScriptBin "newsboat-print-unread" ''
UNREAD=$(${newsboat} -x print-unread | awk '{print $1}')
if [[ $UNREAD -gt 0 ]]; then
printf " %i" "$UNREAD"
fi
'');
inherit (lib) mkDefault;
in
{
exec = mkDefault "${newsboat-print-unread}/bin/newsboat-print-unread";
format = mkDefault "{}";
hide-empty-text = mkDefault true; # disable module when output is empty
signal = mkDefault 10;
on-click = mkDefault "newsboat-reload";
}

View file

@ -0,0 +1,20 @@
# pulseaudio input
{ lib, pkgs, ... }:
let
helvum = "${pkgs.helvum}/bin/helvum";
pactl = "${pkgs.pulseaudio}/bin/pactl";
inherit (lib) mkDefault;
in
{
format = mkDefault "{format_source}";
format-source = mkDefault " {volume}";
format-source-muted = mkDefault "";
on-click = mkDefault "${pactl} set-source-mute 0 toggle";
on-click-middle = mkDefault helvum;
on-scroll-down = mkDefault "${pactl} set-source-volume 0 -5%";
on-scroll-up = mkDefault "${pactl} set-source-volume 0 +5%";
scroll-step = mkDefault 1;
smooth-scrolling-threshold = mkDefault 1;
}

View file

@ -0,0 +1,27 @@
# pulseaudio output
{ lib, pkgs, ... }:
let
helvum = "${pkgs.helvum}/bin/helvum";
pactl = "${pkgs.pulseaudio}/bin/pactl";
inherit (lib) mkDefault;
in
{
format = mkDefault "{icon} {volume}";
format-muted = mkDefault "x";
format-icons = mkDefault {
default = mkDefault [
""
""
""
];
};
max-volume = mkDefault 150;
on-click = mkDefault "${pactl} set-sink-mute 0 toggle";
on-click-middle = mkDefault helvum;
on-scroll-down = mkDefault "${pactl} set-sink-volume 0 -5%";
on-scroll-up = mkDefault "${pactl} set-sink-volume 0 +5%";
scroll-step = mkDefault 5;
smooth-scrolling-threshold = mkDefault 1;
}

View file

@ -0,0 +1,28 @@
# custom/timer
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.waybar;
timer = pkgs.writeShellScriptBin "timer" (builtins.readFile ./timer.sh);
inherit (lib) mkDefault mkIf;
in
{
config = mkIf cfg.enable {
programs.waybar.settings.mainBar."custom/timer" = {
exec = mkDefault "${timer}/bin/timer print";
# `interval` is not needed since timer script will update the status bar
format = mkDefault "{}";
hide-empty-text = mkDefault true; # disable module when output is empty
signal = mkDefault 11;
on-click = mkDefault "${timer}/bin/timer stop";
};
home.packages = [ timer ]; # Add an additional check if the widget is enabled? Currently, the waybar module installs this package regardless of the config.
};
}

View file

@ -0,0 +1,78 @@
TIMER_FILE="/tmp/timer" # file to store the current time
SIGNAL=11 # signal number to send to status bar
STATUS_BAR="waybar" # Support for more status bars?
help() {
echo "Usage: $0 {start -h H -m M -s S|stop|print}"
}
start_timer() {
local hours=$1
local minutes=$2
local seconds=$3
local total_seconds=$((hours * 3600 + minutes * 60 + seconds))
(
notify-send "Timer Started" "Your countdown timer has been started."
trap "exit" INT TERM
trap "rm -f -- '$TIMER_FILE'" EXIT
while [ $total_seconds -gt 0 ]; do
hours=$(( total_seconds / 3600 ))
minutes=$(( (total_seconds % 3600) / 60 ))
seconds=$(( total_seconds % 60 ))
printf "%02d:%02d:%02d\n" $hours $minutes $seconds > $TIMER_FILE
pkill -RTMIN+$SIGNAL $STATUS_BAR
sleep 1
total_seconds=$(( total_seconds - 1 ))
done
notify-send "Timer Finished" "Your countdown timer has ended."
stop_timer
) &
}
stop_timer() {
rm -f $TIMER_FILE
pkill -RTMIN+$SIGNAL $STATUS_BAR
exit 0
}
print_time() {
if [[ -f $TIMER_FILE ]]; then
printf " %s" "$(cat $TIMER_FILE)"
else
echo "" # waybar widget will be hidden if stdout is empty
fi
}
if [ "$1" = "start" ]; then
shift
while getopts "h:m:s:" opt; do
case $opt in
h) HOURS=$OPTARG ;;
m) MINUTES=$OPTARG ;;
s) SECONDS=$OPTARG ;;
*) echo "Invalid option"; exit 1 ;;
esac
done
HOURS=${HOURS:-0}
MINUTES=${MINUTES:-0}
SECONDS=${SECONDS:-0}
start_timer $HOURS $MINUTES $SECONDS
elif [ "$1" = "stop" ]; then
notify-send "Timer Stopped" "Your countdown timer has been stopped."
stop_timer
elif [ "$1" = "print" ]; then
print_time
else
echo "Invalid command $1"
help
exit 1
fi

View file

@ -0,0 +1,18 @@
# wireplumber
{ lib, ... }:
let
inherit (lib) mkDefault;
in
{
format = mkDefault "{icon} {volume}";
format-muted = mkDefault "mute"; # <U+f6a9> does not render. See issue #144
format-icons = mkDefault [
""
""
""
];
on-click = mkDefault "helvum";
max-volume = mkDefault 150;
scroll-step = mkDefault 1;
}