{lib, 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 = "nordvpn-rofi.sh --status-json"; return-type = "json"; on-click = "rofi -show vpn -modes 'vpn:nordvpn-rofi.sh'"; }; style = { connected.color = theme.normal.black; disconnected.color = theme.normal.yellow; }; background = theme.extra.teal;} ] ++ (if (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 = "{calendar}"; calendar = { mode = "month"; weeks-pos = "left"; on-scroll = 1; format = { months = "{}"; days = "{}"; weekdays = "{}"; today = "{}"; }; 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 ]; 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; }; }