{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 = "transparent"; } { 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; color = theme.extra.white; } { 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; color = theme.extra.white; } { 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; color = theme.extra.white; } ] ++ (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; color = theme.extra.white; }] else []) ++ [ { name = "cpu"; config = { format = "{}% "; }; background = theme.extra.brown; color = theme.extra.white; } { name = "memory"; config = { format = "{}% "; }; background = theme.extra.darkbrown; color = theme.extra.white; } { name = "temperature"; config = { critical-threshold = 80; hwmon-path = "/sys/class/hwmon/hwmon5/temp1_input"; format = "{temperatureC}°C {icon}"; format-icons = ["" "" ""]; }; background = theme.extra.darkerbrown; color = theme.extra.white; } { 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; color = theme.normal.white; } { name = "tray"; config = { spacing = 10; }; background = theme.normal.white; color = theme.normal.black; } ]; # 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; lib.lists.flatten (let list = utils.windows 2 descs; len = length list; in lib.lists.imap0 (n: descs: let left = elemAt descs 0; right = elemAt descs 1; in if n == (len - 1) then [ (mkModule left) (mkSpacer n left right) (mkModule right) ] else [ (mkModule left) (mkSpacer n left right) ]) list ); # 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"; }; }; workspace-style = '' /* Workspaces stuff */ #workspaces button { color: ${theme.extra.white}; background: ${theme.extra.black}; padding-left: 5pt; padding-right: 5pt; border-radius: 5pt; margin-left: 2pt; margin-right: 2pt; margin-bottom: 2pt; } /* Inactive (on unfocused output) */ #workspaces button.visible { color: ${theme.extra.white}; background: ${theme.bright.magenta}; } /* Active (on focused output) */ #workspaces button.focused { color: ${theme.extra.black}; background: ${theme.bright.cyan}; } /* Contains an urgent window */ #workspaces button.urgent { color: ${theme.bright.red}; background: ${theme.extra.black}; } /* Style when cursor is on the button */ #workspaces button:hover { background: ${theme.bright.black}; color: ${theme.extra.white}; } #window { margin-right: 10pt; margin-left: 10pt; } ''; in { imports = [ ../options.nix ]; home.packages = with pkgs; [ waybar pavucontrol iwgtk ]; programs.waybar = { enable = true; settings = { mainBar = bar.config; }; style = '' /* Reset all styles */ * { 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: SF Compact Rounded; font-size: 11pt; font-weight: 500; } '' + workspace-style + bar.style; }; }