Kieran's opinionated (and probably slightly dumb) nix config
at main 12 kB view raw
1{ 2 lib, 3 pkgs, 4 config, 5 ... 6}: 7let 8 commonDeps = with pkgs; [ 9 coreutils 10 gnugrep 11 systemd 12 ]; 13 # Function to simplify making waybar outputs 14 mkScript = 15 { 16 name ? "script", 17 deps ? [ ], 18 script ? "", 19 }: 20 lib.getExe ( 21 pkgs.writeShellApplication { 22 inherit name; 23 text = script; 24 runtimeInputs = commonDeps ++ deps; 25 } 26 ); 27 # Specialized for JSON outputs 28 mkScriptJson = 29 { 30 name ? "script", 31 deps ? [ ], 32 pre ? "", 33 text ? "", 34 tooltip ? "", 35 alt ? "", 36 class ? "", 37 percentage ? "", 38 }: 39 mkScript { 40 inherit name; 41 deps = [ pkgs.jq ] ++ deps; 42 script = '' 43 ${pre} 44 jq -cn \ 45 --arg text "${text}" \ 46 --arg tooltip "${tooltip}" \ 47 --arg alt "${alt}" \ 48 --arg class "${class}" \ 49 --arg percentage "${percentage}" \ 50 '{text:$text,tooltip:$tooltip,alt:$alt,class:$class,percentage:$percentage}' 51 ''; 52 }; 53in 54{ 55 config = lib.mkIf config.atelier.wm.hyprland.enable { 56 # Let it try to start a few more times 57 systemd.user.services.waybar = { 58 Unit.StartLimitBurst = 30; 59 }; 60 programs.waybar = { 61 enable = true; 62 package = pkgs.waybar.overrideAttrs (oa: { 63 mesonFlags = (oa.mesonFlags or [ ]) ++ [ "-Dexperimental=true" ]; 64 }); 65 systemd.enable = true; 66 settings = { 67 primary = { 68 exclusive = false; 69 passthrough = false; 70 height = 46; 71 margin = "6"; 72 position = "top"; 73 modules-left = [ 74 "custom/os" 75 "hyprland/workspaces" 76 "hyprland/submap" 77 ]; 78 79 modules-center = [ 80 "cpu" 81 "memory" 82 "disk" 83 "clock" 84 "pulseaudio" 85 "battery" 86 "idle_inhibitor" 87 ]; 88 89 modules-right = [ 90 "network" 91 "bluetooth" 92 "tray" 93 "privacy" 94 "custom/webcam" 95 "custom/hostname" 96 ]; 97 98 clock = { 99 interval = 1; 100 format = "{:%d/%m %H:%M:%S}"; 101 format-alt = "{:%Y-%m-%d %H:%M:%S %z}"; 102 on-click-left = "mode"; 103 tooltip-format = '' 104 <big>{:%Y %B}</big> 105 <tt><small>{calendar}</small></tt>''; 106 }; 107 108 cpu = { 109 format = " {usage}%"; 110 }; 111 112 memory = { 113 format = " {}%"; 114 interval = 5; 115 }; 116 117 disk = { 118 interval = 5; 119 unit = "GB"; 120 format = "󰋊 {percentage_used}%"; 121 }; 122 123 pulseaudio = { 124 format = "{icon} {volume}%"; 125 format-muted = " 0%"; 126 format-icons = { 127 headphone = "󰋋 "; 128 headset = "󰋎 "; 129 portable = " "; 130 default = [ 131 " " 132 " " 133 " " 134 ]; 135 }; 136 on-click = lib.getExe pkgs.pavucontrol; 137 }; 138 139 idle_inhibitor = { 140 format = "{icon}"; 141 format-icons = { 142 activated = "󰅶 "; 143 deactivated = "󰾫 "; 144 }; 145 tooltip-format-activated = "Caffinated! device will not sleep."; 146 tooltip-format-deactivated = "no caffeine :( device will sleep when not in use."; 147 }; 148 149 battery = { 150 interval = 5; 151 bat = "BAT1"; 152 # full-at = 94; 153 format = "{icon} {capacity}%"; 154 format-icons = [ 155 "󰁺" 156 "󰁻" 157 "󰁼" 158 "󰁽" 159 "󰁾" 160 "󰁿" 161 "󰂀" 162 "󰂁" 163 "󰂂" 164 "󰁹" 165 ]; 166 states = { 167 battery-10 = 10; 168 battery-20 = 20; 169 battery-30 = 30; 170 battery-40 = 40; 171 battery-50 = 50; 172 battery-60 = 60; 173 battery-70 = 70; 174 battery-80 = 80; 175 battery-90 = 90; 176 battery-100 = 100; 177 }; 178 # <https://github.com/Alexays/Waybar/issues/1938> 179 # the wiki lies about this, does not match 180 # /sys/class/power_supply/BAT0/status 181 format-plugged = "󰚥 AC"; 182 format-charging-battery-10 = "󰢜 {capacity}%"; 183 format-charging-battery-20 = "󰂆 {capacity}%"; 184 format-charging-battery-30 = "󰂇 {capacity}%"; 185 format-charging-battery-40 = "󰂈 {capacity}%"; 186 format-charging-battery-50 = "󰢝 {capacity}%"; 187 format-charging-battery-60 = "󰂉 {capacity}%"; 188 format-charging-battery-70 = "󰢞 {capacity}%"; 189 format-charging-battery-80 = "󰂊 {capacity}%"; 190 format-charging-battery-90 = "󰂋 {capacity}%"; 191 format-charging-battery-100 = "󰂅 {capacity}%"; 192 }; 193 194 "hyprland/workspaces" = { 195 format = "{icon} {windows}"; 196 window-rewrite-default = " "; 197 window-rewrite-seperator = ""; 198 window-rewrite = { 199 "title<.*github.*>" = "󰊤 "; 200 "title<.*youtube.*>" = " "; 201 "title<*Gmail*>" = "󰊫 "; 202 "class<firefox>" = " "; 203 "obs" = " "; 204 "alacritty" = " "; 205 "class<com.mitchellh.ghostty>" = "󰊠 "; 206 "foot" = " "; 207 "code" = "󰨞 "; 208 "slack" = "󰒱 "; 209 "spotify" = "󰓇 "; 210 "class<org.gnome.Nautilus>" = "󰉓 "; 211 "class<kicad>" = " "; 212 "class<dev.zed.Zed>" = " "; 213 "class<chromium-browser>" = " "; 214 "class<vesktop>" = " "; 215 }; 216 }; 217 218 network = { 219 interval = 3; 220 format-wifi = "{icon} {essid}"; 221 format-icons = [ 222 "󰤟" 223 "󰤢" 224 "󰤥" 225 "󰤨" 226 ]; 227 format-ethernet = "󰈁 Connected"; 228 format-disconnected = "󱐤 "; 229 tooltip-format = '' 230 {ifname} 231 {ipaddr}/{cidr} 232 Up: {bandwidthUpBits} 233 Down: {bandwidthDownBits}''; 234 on-click = mkScript { 235 deps = [ 236 pkgs.wpa_supplicant 237 pkgs.notify-desktop 238 ]; 239 script = ''wpa_cli reconnect; notify-desktop "reconnecting to wifi" -t 1200''; 240 }; 241 }; 242 243 bluetooth = { 244 format-on = "󰂯"; 245 format-off = "󰂲"; 246 format-disabled = "󰂲"; 247 format-connected = "󰂱 {num_connections}"; 248 format-connected-battery = "󰂱 {device_alias} ({device_battery_percentage}%) ({num_connections})"; 249 on-click = "overskride"; 250 }; 251 252 "custom/os" = { 253 interval = 1; 254 return-type = "json"; 255 exec = mkScriptJson { 256 text = " "; 257 tooltip = ''$(grep PRETTY_NAME /etc/os-release | cut -d '"' -f2)''; 258 }; 259 }; 260 261 "custom/hostname" = { 262 exec = mkScript { script = ''echo "$USER@$HOSTNAME"''; }; 263 on-click = mkScript { script = "systemctl --user restart waybar"; }; 264 }; 265 266 privacy = { 267 "icon-spacing" = 0; 268 "icon-size" = 18; 269 "transition-duration" = 250; 270 modules = [ 271 { 272 type = "screenshare"; 273 tooltip = true; 274 "tooltip-icon-size" = 24; 275 } 276 { 277 type = "audio-out"; 278 tooltip = true; 279 "tooltip-icon-size" = 24; 280 } 281 { 282 type = "audio-in"; 283 tooltip = true; 284 "tooltip-icon-size" = 24; 285 } 286 ]; 287 }; 288 289 "custom/webcam" = { 290 return-type = "json"; 291 interval = 2; 292 exec = mkScript { 293 deps = [ 294 pkgs.jq 295 pkgs.psmisc 296 ]; 297 script = '' 298 # get programs using the video0 endpoint 299 PIDS=$(fuser /dev/video0 2>/dev/null || echo "") 300 if [ -n "$PIDS" ]; then 301 # Using pgrep instead of grepping ps output 302 for pid in $PIDS; do 303 process_info=$(ps -p "$pid" -o pid,cmd --no-headers) 304 if [ -n "$process_info" ]; then 305 echo "$process_info" | awk '{command=$2; for(i=3;i<=NF;i++) command=command" "$i; print "{\"tooltip\": \""command"\"}"}' 306 fi 307 done | grep -v "grep" |\ 308 jq -s 'if length > 0 then {text: "󰄀 ", tooltip: (map(.tooltip) | join("\r"))} else {text: "", tooltip: ""} end' 309 else 310 echo '{"text": "", "tooltip": ""}' 311 fi | jq --unbuffered --compact-output 312 ''; 313 }; 314 }; 315 }; 316 }; 317 318 # Cheatsheet: 319 # x -> all sides 320 # x y -> vertical, horizontal 321 # x y z -> top, horizontal, bottom 322 # w x y z -> top, right, bottom, left 323 style = 324 # css 325 '' 326 * { 327 font-family: Fira Sans, FiraCode Nerd Font; 328 font-size: 12pt; 329 padding: 0; 330 margin: 0 0.4em; 331 } 332 333 window#waybar { 334 padding: 0; 335 border-radius: 0.5em; 336 background-color: shade(@surface0, 0.7); 337 color: @surface2 338 } 339 .modules-left { 340 margin-left: -0.65em; 341 } 342 .modules-right { 343 margin-right: -0.65em; 344 } 345 346 #workspaces button { 347 background-color: @surface0; 348 color: @surface2; 349 padding-left: 0.2em; 350 padding-right: 0.2em; 351 margin-left: 0.25em; 352 margin-right: 0.25em; 353 margin-top: 0.4em; 354 margin-bottom: 0.4em; 355 } 356 #workspaces button.hidden { 357 background-color: @surface0; 358 color: @surface2; 359 } 360 #workspaces button.focused, 361 #workspaces button.active { 362 background-color: shade(@blue, 0.7); 363 color: @green; 364 } 365 366 #workspaces button:hover { 367 background-color: @surface3; 368 color: @surface1; 369 } 370 371 #privacy-item { 372 margin-left: 0.1em; 373 margin-right: 0.1em; 374 } 375 376 #clock { 377 padding-right: 1em; 378 padding-left: 1em; 379 border-radius: 0.5em; 380 } 381 382 #custom-os { 383 background-color: @surface3; 384 color: @blue; 385 padding-right: 1em; 386 padding-left: 1em; 387 margin-right: 0; 388 border-radius: 0.5em; 389 } 390 #custom-hostname { 391 background-color: @surface3; 392 color: @blue; 393 padding-right: 1em; 394 padding-left: 1em; 395 margin-left: 0; 396 border-radius: 0.5em; 397 } 398 #custom-gpu, #cpu, #memory { 399 margin-left: 0.05em; 400 margin-right: 0.55em; 401 } 402 ''; 403 }; 404 }; 405}