nixos-config/home/waybar.nix

243 lines
7.1 KiB
Nix

{pkgs, lib, super-config, config, ...}:
let
theme = import ../data/theme.nix {inherit config; };
utils = import ../utils.nix {inherit lib; };
in let
self = rec {
# ModuleDesc has the shape {name, config?, background?, color?, style?}
module-descs = [
{
name = "custom/left-most";
background = theme.background;
}
{
name = "pulseaudio";
config = {
format = "{volume}% {icon} {format_source}";
format-bluetooth = "{volume}% {icon} {format_source}";
format-muted = "{format_source}";
format-source = "{volume}% ";
format-source-muted = "";
format-icons = {
headphones = "";
default = ["" "" ""];
};
on-click = "pavucontrol";
};
background = theme.normal.yellow;
}
{
name = "network";
config = {
format-wifi = "{essid} {signalStrength}% {icon}";
format-ethernet = "{ipaddr} 󰈀";
format-disconnected = "Disconnected 󰤮";
tooltip-format = ''Interface: {ifname}
IP: {ipaddr}
Speed: {bandwidthUpBytes} / {bandwidthDownBytes}
Signal: {signalStrength}%
SSID: {essid} {frequency}'';
on-click = "iwgtk";
format-icons = ["󰤯" "󰤟" "󰤢" "󰤥" "󰤨"];
};
background = theme.normal.green;
}
{
name = "custom/vpn";
config = {
format = "{}";
excape = true;
interval = 30;
exec = "${pkgs.nordvpn-rofi}/bin/nordvpn-rofi --status-json";
return-type = "json";
on-click = "rofi -show vpn -modes 'vpn:nordvpn-rofi'";
};
style = {
connected.color = theme.normal.black;
disconnected.color = theme.normal.yellow;
};
background = theme.extra.teal;
}
]
++ (if (super-config.has_battery) then [{
name = "battery";
config = {
states = {
critical = 15;
warning = 25;
good = 80;
full = 90;
};
interval = 30;
format = "{capacity}% {icon}";
format-charging = "{capacity}% ";
format-plugged = "{capacity}% ";
format-icons = ["" "" "" "" ""];
};
background = theme.extra.aqua;
}] else [])
++ [
{
name = "cpu";
config = {
format = "{}% ";
};
background = theme.extra.brown;
}
{
name = "memory";
config = {
format = "{}% ";
};
background = theme.extra.darkbrown;
}
{
name = "temperature";
config = {
critical-threshold = 80;
hwmon-path = "/sys/class/hwmon/hwmon5/temp1_input";
format = "{temperatureC}°C {icon}";
format-icons = ["" "" ""];
};
background = theme.extra.darkerbrown;
}
{
name = "clock";
config = {
format = "{:%H:%M} 󰥔";
tooltip-format = "<tt><small>{calendar}</small></tt>";
calendar = {
mode = "month";
weeks-pos = "left";
on-scroll = 1;
format = {
months = "<span color=\"${theme.normal.yellow}\"><b>{}</b></span>";
days = "<span color=\"${theme.normal.white}\"><b>{}</b></span>";
weekdays = "<span color=\"${theme.bright.black}\"><b>{}</b></span>";
today = "<span color=\"${theme.normal.red}\"><b>{}</b></span>";
};
on-scroll-up = "shift_up";
on-scroll-down = "shift_down";
};
};
background = theme.normal.black;
}
{name = "tray"; config = { spacing = 10; }; background = theme.background;}
];
# default style for modules
default-style = "padding-left: 8pt; padding-right: 8pt;";
# ModuleDesc -> Module
mkModule = desc: let
background = desc.background or theme.background;
color = desc.color or theme.foreground;
config = desc.config or {};
# style = module.style or "";
style = default-style;
style-name = builtins.replaceStrings ["/"] ["-"] desc.name;
in {
inherit (desc) name;
setting = {
} // config;
style = "#${style-name} {" + default-style + ''background: ${background};color: ${color};'' + "}\n";
};
mkSpacer = idx: left: right: {
name = "custom/arrow${toString idx}";
setting = {
format = "";
tooltip = false;
};
style = "#custom-arrow${toString idx} {font-size: 14pt;background: ${left.background};color: ${right.background};}\n";
};
# modules interlaced with spacers
# [ModuleDesc] -> [Module]
mkSpacedModules = descs: with builtins;
let
len = length descs;
in lib.lists.flatten
(lib.lists.imap0
(n: descs: let
left = elemAt descs 0;
right = elemAt descs 1;
in if n == len then [
(mkModule left)
(mkSpacer n left right)
(mkModule right)
] else [
(mkModule left)
(mkSpacer n left right)
])
(utils.windows 2 descs)
);
# Module -> {"name" = setting}
mkModuleConfig = {name, setting, ...}: lib.attrsets.optionalAttrs (!utils.isEmptySet setting) {
"${name}" = setting;
};
# builds bar configuration with left, center, and right modules
# right modules get spacers in between them.
# {left: [ModuleDesc], center: [ModuleDesc], right: [ModuleDesc], config: {}} -> {config, style}
mkBar = {left, center, right, config, ...}:
let
# Create modules from the descriptions
right' = mkSpacedModules right;
left' = map (module: mkModule module) left;
center' = map (module: mkModule module) center;
in let
# Create lists of module names for the config
modules-left = map (module: module.name) left';
modules-center = map (module: module.name) center';
modules-right = map (module: module.name) right';
# Combine all modules into a single list
modules = lib.lists.flatten [left' center' right'];
in {
config = lib.attrsets.mergeAttrsList (lib.lists.flatten [
{
inherit modules-left modules-center modules-right;
}
config
(map mkModuleConfig modules)
]);
style = lib.strings.concatStringsSep "\n" (map (module: module.style) modules);
};
};
bar = self.mkBar {
left = [ {name = "sway/workspaces";} {name = "sway/mode";} ];
center = [ {name = "sway/window";} ];
right = self.module-descs;
config = {
height = 25;
spacing = 0;
position = "top";
};
};
in {
imports = [ ../options.nix ];
home.packages = with pkgs; [
waybar
pavucontrol
iwgtk
];
programs.waybar = {
enable = true;
settings = {
mainBar = bar.config;
};
style = ''
* {border: none; border-radius: 0; min-height: 0; margin: 0; padding: 0; box-shadow: none; text-shadow: none;}
#waybar { background: rgba(40, 40, 40, 0.3); color: #ffffff; font-family: "sans-serif"; font-size: 12pt; font-weight: 500; }
''
+ bar.style;
};
}