From 6804d95a08cd0342c36bdb4d58a225682e10cd16 Mon Sep 17 00:00:00 2001
From: DerGrumpf
Date: Mon, 8 Sep 2025 16:29:01 +0200
Subject: [PATCH] Changed Waybar
---
home/hyprland/waybar/common.nix | 157 ++++++
home/hyprland/waybar/config.jsonc | 609 ------------------------
home/hyprland/waybar/configs/cava.sh | 42 ++
home/hyprland/waybar/configs/style.css | 485 +++++--------------
home/hyprland/waybar/configs/weather.py | 524 --------------------
home/hyprland/waybar/default.nix | 33 --
home/hyprland/waybar/dual.nix | 210 ++------
home/hyprland/waybar/hyprland.nix | 11 +
home/hyprland/waybar/single.nix | 173 ++-----
9 files changed, 393 insertions(+), 1851 deletions(-)
create mode 100644 home/hyprland/waybar/common.nix
delete mode 100644 home/hyprland/waybar/config.jsonc
create mode 100644 home/hyprland/waybar/configs/cava.sh
delete mode 100755 home/hyprland/waybar/configs/weather.py
create mode 100644 home/hyprland/waybar/hyprland.nix
diff --git a/home/hyprland/waybar/common.nix b/home/hyprland/waybar/common.nix
new file mode 100644
index 0000000..3606114
--- /dev/null
+++ b/home/hyprland/waybar/common.nix
@@ -0,0 +1,157 @@
+{
+ widgets = {
+ "group/media" = {
+ orientation = "horizontal";
+
+ modules = [
+ "mpris"
+ "custom/cava"
+ "wireplumber"
+ ];
+ };
+
+ mpris = {
+ format = "{player_icon}";
+ format-paused = "{status_icon}";
+ max-length = 100;
+ player-icons = {
+ default = "||";
+ mpv = "||";
+ };
+ status-icons = {
+ paused = "▶";
+ };
+ };
+
+ "custom/cava" = {
+ exec = "sh ~/.config/waybar/cava.sh";
+ format = "{} ♪";
+ };
+
+ wireplumber = {
+ format = "{volume}%";
+ format-muted = "";
+ max-volume = 110;
+ scroll-step = 0.2;
+ };
+
+ "group/hardware" = {
+ orientation = "horizontal";
+ modules = [
+ "cpu"
+ "network"
+ "memory"
+ "disk"
+ "temperature"
+ ];
+ };
+
+ network = {
+ # Wifi
+ tooltip = true;
+ format-wifi = "{icon} ";
+ format-icons = [
+ ""
+ ""
+ ""
+ ];
+ rotate = 0;
+
+ # Ethernet
+ format-ethernet = "ᯤ";
+ tooltip-format = "Network: {essid}\nSignal strength: {signaldBm}dBm ({signalStrength}%)\nFrequency: {frequency}MHz\nInterface: {ifname}\nIP: {ipaddr}/{cidr}\nGateway: {gwaddr}\nNetmask: {netmask}\nCurrent : {bandwidthTotalBits}\nUp : {bandwidthUpBits}\nDown : {bandwidthDownBits}";
+ format-linked = " {ifname} (No IP)";
+ format-disconnected = " ";
+ tooltip-format-disconnected = "Disconnected";
+ on-click = "/usr/local/bin/ags -t ControlPanel";
+ interval = 2;
+ };
+
+ memory = {
+ interval = 1;
+ rotate = 270;
+ format = "{icon}";
+ format-icons = [
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ];
+ max-length = 10;
+ };
+
+ cpu = {
+ interval = 1;
+ format = "{icon}";
+ rotate = 270;
+ format-icons = [
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ];
+ };
+
+ temperature = {
+ format = "{temperatureC}°C ";
+ thermal-zone = 0;
+ hwmon-path = "/sys/class/hwmon/hwmon0/temp1_input";
+ critical-threshold = 80;
+ };
+
+ disk = {
+ format = "{percentage_free}% ";
+ tooltip = true;
+ tooltip-format = "{free} / {total} ({percentage_free})";
+ };
+
+ clock = {
+ format = "{:%a %b %d, %I:%M %p}";
+ rotate = 0;
+ on-click = " ";
+ tooltip-format = "{calendar}";
+ calendar = {
+ mode = "month";
+ mode-mon-col = 3;
+ on-scroll = 1;
+ on-click-right = "mode";
+ format = {
+ months = "{}";
+ weekdays = "{}";
+ today = "{}";
+ };
+ };
+ actions = {
+ on-click-right = "mode";
+ on-click-forward = "tz_up";
+ on-click-backward = "tz_down";
+ on-scroll-up = "shift_up";
+ on-scroll-down = "shift_down";
+ };
+ };
+
+ "custom/nixicon" = {
+ format = "";
+ on-click = "rofi -show drun -theme $HOME/.config/rofi/custom.rasi";
+ tooltip = false;
+ };
+
+ "custom/weather" = {
+ format = "{}";
+ exec = "curl -s 'wttr.in/52.281311,10.527029?format=2'";
+ interval = 60;
+ tooltip = false;
+ };
+ };
+
+}
diff --git a/home/hyprland/waybar/config.jsonc b/home/hyprland/waybar/config.jsonc
deleted file mode 100644
index d7c5f45..0000000
--- a/home/hyprland/waybar/config.jsonc
+++ /dev/null
@@ -1,609 +0,0 @@
-// --// waybar config generated by wbarconfgen.sh //-- //
-
-[
-{
- "layer": "top",
- "position": "top",
- "mod": "dock",
- //"width": 20,
- "margin-top": 7,
- "margin-bottom": 0,
- "margin-left": 10,
- "margin-right": 10,
- "exclusive": true,
- "passthrough": false,
- "gtk-layer-shell": true,
- "reload_style_on_change": true,
- "output": "Virtual-1",
-
- "modules-left": [],
- "modules-center": ["wlr/taskbar"],
- "modules-right": ["cpu"],
-
- "wlr/taskbar": {
- "all-outputs": true,
- "format": "{icon}",
- "icon-size": 20,
- "active-first": true
- }
-},
-
-{
-// sourced from header module //
-
- "layer": "top",
- "position": "top",
- "mod": "dock",
- "margin-left": 10,
- "margin-right": 10,
- "margin-top": 7,
- "margin-bottom": 0,
- "exclusive": true,
- "passthrough": false,
- "gtk-layer-shell": true,
- "reload_style_on_change": true,
- "output": "DP-1",
-
-// positions generated based on config.ctl //
-
- "modules-left": ["custom/smallspacer","hyprland/workspaces","custom/spacer","mpris"],
- "modules-center": ["custom/padd","custom/l_end","custom/r_end","hyprland/window","custom/padd"],
- "modules-right": ["custom/padd","custom/l_end","group/expand","network","group/expand-3","group/expand-2","group/expand-4","memory","cpu","clock","custom/notification","custom/padd"],
-
-
-// sourced from modules based on config.ctl //
-
-"custom/led": {
- "format": " ",
- "format-alt": " ",
- "on-click": "~/mouse.sh",
- "tooltip": false,
-},
-
-"upower": {
- "icon-size": 20,
- "format": "",
- "format-alt": "{}[{time}]",
- "tooltip": true,
- "tooltip-spacing": 20,
- "on-click-right": "pkill waybar & hyprctl dispatch exec waybar"
-},
-
-"upower#headset": {
-"format": " {percentage}",
-"native-path": "/org/freedesktop/UPower/devices/headset_dev_A6_98_9A_0D_D3_49",
-"show-icon": false,
-"tooltip": false,
-},
-
-"group/expand-4": {
- "orientation": "horizontal",
- "drawer": {
- "transition-duration": 600,
- "children-class": "not-power",
- "transition-to-left": true,
- "click-to-reveal": true
- },
- "modules": ["upower","upower/headset"]
- },
-
-"custom/smallspacer":{
-"format": " ",
-},
-"memory": {
- "interval": 1,
- "rotate": 270,
- "format": "{icon}",
- "format-icons": ["","","","","","","","",""],
- "max-length": 10
-},
-"cpu": {
- "interval": 1,
- "format": "{icon}",
- "rotate": 270,
- "format-icons": ["","","","","","","","",""],
-},
-
-
-"mpris": {
- "format": "{player_icon} {dynamic}",
- "format-paused": "{status_icon} {dynamic}",
- "max-length": 100,
- "player-icons": {
- "default": "⏸",
- "mpv": "🎵"
- },
- "status-icons": {
- "paused": "▶"
- },
- // "ignored-players": ["firefox"]
-},
-"tray": {
- "icon-size": 16,
- "rotate": 0,
- "spacing": 3
- },
-
- "group/expand": {
- "orientation": "horizontal",
- "drawer": {
- "transition-duration": 600,
- "children-class": "not-power",
- "transition-to-left": true,
- // "click-to-reveal": true
- },
- "modules": ["custom/menu","custom/spacer","tray"]
- },
-
- "custom/menu":{
- "format": "",
- "rotate": 90,
- },
-
-
-"custom/notification": {
- "tooltip": false,
- "format": "{icon}",
- "format-icons": {
- "notification": "",
- "none": "",
- "dnd-notification": "",
- "dnd-none": "",
- "inhibited-notification": "",
- "inhibited-none": "",
- "dnd-inhibited-notification": "",
- "dnd-inhibited-none": ""
- },
- "return-type": "json",
- "exec-if": "which swaync-client",
- "exec": "swaync-client -swb",
- "on-click-right": "swaync-client -d -sw",
- "on-click": "swaync-client -t -sw",
- "escape": true
- },
-
- "hyprland/window": {
-//"format": "{}" // <--- these is the default value
-"format": "{class}",
- "max-length": 120,
- "icon": false,
- "icon-size": 13,
-},
-
- "custom/power": {
- "format": "@{}",
- "rotate": 0,
- "on-click": "ags -t ControlPanel",
- "on-click-right": "pkill ags",
- "tooltip": true
- },
-
- "custom/spacer":{
- "format": "|"
- },
-
-
-
-
-
-"hyprland/workspaces": {
- "format": "{icon}",
- "format-icons": {
- "default": "",
- "active": "",
- //"default": "○",
- //"default": "●"
- },
-},
-
-"wlr/workspaces": {
- "persistent-workspaces": {
- "3": [], // Always show a workspace with name '3', on all outputs if it does not exists
- "4": ["eDP-1"], // Always show a workspace with name '4', on output 'eDP-1' if it does not exists
- "5": ["eDP-1", "DP-2"] // Always show a workspace with name '5', on outputs 'eDP-1' and 'DP-2' if it does not exists
- }
-},
-
-
-"cava": {
- "cava_config": "~/.config/cava/config",
- "framerate": 60,
- "autosens": 1,
- "bars": 14,
- "lower_cutoff_freq": 50,
- "higher_cutoff_freq": 10000,
- "method": "pulse",
- "source": "auto",
- "stereo": true,
- "reverse": false,
- "bar_delimiter": 0,
- "monstercat": false,
- "waves": false,
- "noise_reduction": 0.77,
- "input_delay": 2,
- "format-icons" : ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ],
- "actions": {
- "on-click-right": "mode"
- }
- },
-
- "custom/script": {
- "on-click": "~/.config/waybar/volume.sh toggle",
- "format": "",
-
- },
-
- "custom/cliphist": {
- "format": "{}",
- "rotate": 0,
- "exec": "echo ; echo clipboard history",
- "on-click": "sleep 0.1 && cliphist.sh c",
- "on-click-right": "sleep 0.1 && cliphist.sh d",
- "on-click-middle": "sleep 0.1 && cliphist.sh w",
- "interval" : 86400, // once every day
- "tooltip": true
- },
-
- "custom/wbar": {
- "format": "𐌏{}", // //
- "rotate": 0,
- "exec": "echo ; echo show app menu",
- "on-click": "wofi --show drun",
- "on-click-right": "wbarconfgen.sh p",
- "on-click-middle": "sleep 0.1 && quickapps.sh kitty firefox spotify code dolphin",
- "interval" : 86400,
- "tooltip": true
- },
-
- "custom/theme": {
- "format": "{}",
- "rotate": 0,
- "exec": "echo ; echo pick color",
- "on-click": "hyprpicker",
- "on-click-right": "themeswitch.sh -p",
- "on-click-middle": "sleep 0.1 && themeselect.sh",
- "interval" : 86400, // once every day
- "tooltip": true
- },
-
- "custom/wallchange": {
- "format": "{}",
- "rotate": 0,
- "exec": "echo ; echo switch wallpaper",
- "on-click": "swww img --transition-type grow --transition-pos 0.071,0.988 --transition-step 255 --transition-fps 60 /home/anik/Downloads/skyway.jpg",
- "on-click-right": "swww img --transition-type grow --transition-pos 0.071,0.988 --transition-step 255 --transition-fps 60 /home/anik/Downloads/cloud.png",
- "on-click-middle": "swww img --transition-type grow --transition-pos 0.071,0.988 --transition-step 255 --transition-fps 60 /home/anik/Downloads/gradient.jpg",
- "on-scroll-up": "swww img --transition-type grow --transition-pos 0.071,0.988 --transition-step 255 --transition-fps 60 /home/anik/Downloads/torvalds.png",
- "on-scroll-down": "swww img --transition-type grow --transition-pos 0.071,0.988 --transition-step 255 --transition-fps 60 /home/anik/Downloads/night.png",
- "interval" : 86400, // once every day
- "tooltip": true
- },
- "custom/mouse":
- {
- "format": "",
- "format-alt": "",
-
- "on-click": "m8mouse -dpi 1 -led 2 -speed 4",
- "on-click-right": "m8mouse -dpi 1 -led 4 -speed 4",
- "on-click-middle": "m8mouse -dpi 1 -led 7 -speed 4",
- "tooltip": true
- },
-
- "wlr/taskbar": {
- "format": "{icon}",
- "rotate": 0,
- "icon-size": 18,
- "icon-theme": "Tela-circle-dracula",
- "spacing": 0,
- "tooltip-format": "{title}",
- "on-click": "activate",
- "on-click-middle": "close",
- "ignore-list": [
- "Alacritty"
- ],
- "app_ids-mapping": {
- "firefoxdeveloperedition": "firefox-developer-edition"
- }
- },
-
- "custom/spotify": {
- "exec": "mediaplayer.py --player spotify",
- "format": " {}",
- "rotate": 0,
- "return-type": "json",
- "on-click": "playerctl play-pause --player spotify",
- "on-click-right": "playerctl next --player spotify",
- "on-click-middle": "playerctl previous --player spotify",
- "on-scroll-up": "volumecontrol.sh -p spotify i",
- "on-scroll-down": "volumecontrol.sh -p spotify d",
- "max-length": 25,
- "escape": true,
- "tooltip": true
- },
-
- "idle_inhibitor": {
- "format": "{icon}",
- "rotate": 0,
- "format-icons": {
- "activated": "",
- "deactivated": ""
- }
- },
-
- "clock": {
- "format": "{:%I:%M %p}",
- "rotate": 0,
- "on-click": "/usr/local/bin/ags -t ActivityCenter",
- "tooltip-format": "{calendar}",
- "calendar": {
- "mode": "month",
- "mode-mon-col": 3,
- "on-scroll": 1,
- "on-click-right": "mode",
- "format": {
- "months": "{}",
- "weekdays": "{}",
- "today": "{}"
- }
- },
- "actions": {
- "on-click-right": "mode",
- "on-click-forward": "tz_up",
- "on-click-backward": "tz_down",
- "on-scroll-up": "shift_up",
- "on-scroll-down": "shift_down"
- }
- },
-
-
- "battery": {
- "states": {
- "good": 95,
- "warning": 30,
- "critical": 20
- },
- "format": "{icon}",
- "rotate": 0,
- "format-charging": "",
- "format-plugged": "",
- // "format-alt": "<{time} | {capacity}%",
- "format-icons": ["","","","","","","","",""],
- // "format-icons": ["","","","","","","",""],
- //"format-icons": ["", "", "", "", "", "", "", "", "", "", ""],
- "on-click-right": "pkill waybar & hyprctl dispatch exec waybar",
- // "format-icons": [],
-
- },
-
- "backlight": {
- "device": "intel_backlight",
- "rotate": 0,
- "format": "{icon}",
- "format-icons": ["", "", "", ""],
- "scroll-step": 1,
- "min-length": 2
- },
-
- "group/expand-2": {
- "orientation": "horizontal",
- "drawer": {
- "transition-duration": 600,
- "children-class": "not-power",
- "transition-to-left": true,
- "click-to-reveal": true
- },
- "modules": ["backlight","backlight/slider","custom/smallspacer","custom/led"]
- },
-
- "group/expand-3": {
- "orientation": "horizontal",
- "drawer": {
- "transition-duration": 600,
- "children-class": "not-power",
- "transition-to-left": true,
- "click-to-reveal": true
- },
- "modules": ["pulseaudio","pulseaudio/slider"]
- },
-
- "network": {
- "tooltip": true,
- "format-wifi": "{icon} ",
- "format-icons": ["", "", ""],
- // "format-wifi": "",
- "rotate": 0,
- "format-ethernet": " ",
- "tooltip-format": "Network: {essid}\nSignal strength: {signaldBm}dBm ({signalStrength}%)\nFrequency: {frequency}MHz\nInterface: {ifname}\nIP: {ipaddr}/{cidr}\nGateway: {gwaddr}\nNetmask: {netmask}",
- "format-linked": " {ifname} (No IP)",
- "format-disconnected": " ",
- "tooltip-format-disconnected": "Disconnected",
- "on-click": "/usr/local/bin/ags -t ControlPanel",
- "interval": 2,
- },
-
- "pulseaudio": {
- "format": "{icon}",
- "rotate": 0,
- "format-muted": "婢",
- "tooltip-format": "{icon} {desc} // {volume}%",
- "scroll-step": 5,
- "format-icons": {
- "headphone": "",
- "hands-free": "",
- "headset": "",
- "phone": "",
- "portable": "",
- "car": "",
- "default": ["", "", ""]
- }
- },
-
- "pulseaudio#microphone": {
- "format": "{format_source}",
- "rotate": 0,
- "format-source": "",
- "format-source-muted": "",
- "on-click": "pavucontrol -t 4",
- "on-click-middle": "volumecontrol.sh -i m",
- "on-scroll-up": "volumecontrol.sh -i i",
- "on-scroll-down": "volumecontrol.sh -i d",
- "tooltip-format": "{format_source} {source_desc} // {source_volume}%",
- "scroll-step": 5
- },
-
- "custom/notifications": {
- "tooltip": false,
- "format": "{icon} {}",
- "rotate": 0,
- "format-icons": {
- "email-notification": "",
- "chat-notification": "",
- "warning-notification": "",
- "error-notification": "",
- "network-notification": "",
- "battery-notification": "",
- "update-notification": "",
- "music-notification": "",
- "volume-notification": "",
- "notification": "",
- "none": ""
- },
- "return-type": "json",
- "exec-if": "which dunstctl",
- "exec": "notifications.py",
- "on-click": "sleep 0.1 && dunstctl history-pop",
- "on-click-middle": "dunstctl history-clear",
- "on-click-right": "dunstctl close-all",
- "interval": 1,
- "tooltip": true,
- "escape": true
- },
-
- "custom/keybindhint": {
- "format": " ",
- "rotate": 0,
- "on-click": "keybinds_hint.sh"
- },
-
-"custom/expand": {
- "on-click":"~/.config/hypr/scripts/expand_toolbar",
- "format":"{}",
- "exec":"~/.config/hypr/scripts/tools/expand arrow-icon"
- },
-
-// modules for padding //
-
- "custom/l_end": {
- "format": " ",
- "interval" : "once",
- "tooltip": false
- },
-
- "custom/r_end": {
- "format": " ",
- "interval" : "once",
- "tooltip": false
- },
-
- "custom/sl_end": {
- "format": " ",
- "interval" : "once",
- "tooltip": false
- },
-
- "custom/sr_end": {
- "format": " ",
- "interval" : "once",
- "tooltip": false
- },
-
- "custom/rl_end": {
- "format": " ",
- "interval" : "once",
- "tooltip": false
- },
-
- "custom/rr_end": {
- "format": " ",
- "interval" : "once",
- "tooltip": false
- },
-
- "custom/padd": {
- "format": " ",
- "interval" : "once",
- "tooltip": false
- },
-
-
-"backlight/slider": {
- "min": 5,
- "max": 100,
- "rotate": 0,
- "device": "intel_backlight",
- "scroll-step": 1,
- },
-
- "pulseaudio/slider": {
- "min": 5,
- "max": 100,
- "rotate": 0,
- "device": "pulseaudio",
- "scroll-step": 1,
- },
-},
-{
-// sourced from header module //
-
- "layer": "top",
- "position": "top",
- "mod": "dock",
- "margin-left": 10,
- "margin-right": 10,
- "margin-top": 7,
- "margin-bottom": 0,
- "exclusive": true,
- "passthrough": false,
- "gtk-layer-shell": true,
- "reload_style_on_change": true,
- "output": "HDMI-A-2",
-
-// positions generated based on config.ctl //
-
- "modules-left": ["hyprland/workspaces"],
- "modules-center": ["custom/weather"],
- "modules-right": ["network"],
-
-
-// sourced from modules based on config.ctl //
- "hyprland/workspaces": {
- "format": "{icon}",
- "format-icons": {
- "default": "",
- "active": "",
- //"default": "○",
- //"default": "●"
- }
- },
-
- "custom/weather": {
- "exec": "python3 ~/.config/waybar/weather.py waybar",
- "restart-interval": 900,
- "return-type": "json"
- },
-
- "network": {
- "tooltip": true,
- "format-wifi": "{icon} ",
- "format-icons": ["", "", ""],
- // "format-wifi": "",
- "rotate": 0,
- "format-ethernet": "{bandwidthTotalBits} {bandwidthUpBits} {bandwidthDownBits} ",
- "tooltip-format": "Network: {essid}\nSignal strength: {signaldBm}dBm ({signalStrength}%)\nFrequency: {frequency}MHz\nInterface: {ifname}\nIP: {ipaddr}/{cidr}\nGateway: {gwaddr}\nNetmask: {netmask}",
- "format-linked": " {ifname} (No IP)",
- "format-disconnected": " ",
- "tooltip-format-disconnected": "Disconnected",
- "on-click": "/usr/local/bin/ags -t ControlPanel",
- "interval": 1,
- },
-}]
diff --git a/home/hyprland/waybar/configs/cava.sh b/home/hyprland/waybar/configs/cava.sh
new file mode 100644
index 0000000..a12dac4
--- /dev/null
+++ b/home/hyprland/waybar/configs/cava.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# Not my own work. Credit to original author
+
+#----- Optimized bars animation without much CPU usage increase --------
+bar="▁▂▃▄▅▆▇█"
+dict="s/;//g"
+
+# Calculate the length of the bar outside the loop
+bar_length=${#bar}
+
+# Create dictionary to replace char with bar
+for ((i = 0; i < bar_length; i++)); do
+ dict+=";s/$i/${bar:$i:1}/g"
+done
+
+# Create cava config
+config_file="/tmp/bar_cava_config"
+cat >"$config_file" <`
-LATITUDE = 52.264149
-LONGITUDE = 10.526420
-
-# waybar colors
-GRAY = '#b7c1de'
-DARK = '#01012b'
-GREEN = '#65dc98'
-YELLOW = '#ffe69d'
-ORANGE = '#ff6e27'
-RED = '#ff124f'
-PURPLE = '#7a04eb'
-BLUE = '#8386f5'
-MOIST = '#e96d5e'
-
-
-### UTILITIES ###
-
-def print_error(msg: str):
- '''
- print an error message with appropriate prefix.
-
- @param str: the message to print
- '''
- print('\x1b[90m[\x1b[31merr\x1b[90m]\x1b[0m', msg)
-
-
-def print_help():
- '''
- print help message, to be used for the `--help` flag and as response to
- incorrect usage
- '''
- print('usage: \x1b[33m./weather.py [options]\x1b[0m')
- print()
- print('available subcommands:')
- print(' - \x1b[32mgeocoding\x1b[0m : search for city to get its coordinates')
- print(' - \x1b[32mcurrent\x1b[0m : print current weather information')
- print(' - \x1b[32mforecast[-daily]\x1b[0m : print forecast for the next ~5 days')
- print(' - \x1b[32mforecast-detail\x1b[0m : print detailed forecast in 3h intervals')
- print(' - \x1b[32mwaybar\x1b[0m : get output for usage with waybar')
-
-
-def make_request(call: str) -> list | dict:
- '''
- make a request to an openweathermap api and returns the response as either
- a list or a dictionary. the api key is added automatically. quits on error.
-
- @param call: the api path, e.g. `data/2.5/weather?...`
-
- @return response of the api request as a list or dict
- '''
- try:
- req = requests.get(f'https://api.openweathermap.org/{call}&appid={API_KEY}')
- return req.json()
- except:
- print_error(f'failed to make request to `/{call}`')
- quit(1)
-
-
-def get_wind_direction(deg: int) -> str:
- '''
- turn a wind direction specified by meteorological degrees into a
- human-readable form
-
- @param deg: degrees. expected to be in range [0..360]
-
- @return human-readable form (e.g. 'NE' for `deg == 45`)
- '''
- if deg < 22.5: return 'N'
- if deg < 67.5: return 'NE'
- if deg < 112.5: return 'E'
- if deg < 157.5: return 'SE'
- if deg < 202.5: return 'S'
- if deg < 247.5: return 'SW'
- if deg < 292.5: return 'W'
- if deg < 337.5: return 'NW'
- else: return 'N'
-
-
-def print_entry(label: str, content: str, indent: int = 0, label_width: int = 8):
- '''
- print an 'entry' that consists of a label (printed in gray) and some
- content. the labels are automatically filled with whitespace to align
- multiple lines properly.
-
- @param label: the label of the line
- @param content: content, printed after the label
- @param indent: number of spaces to indent with
- @param label_width: width of label
- '''
- label_with_whitespace = label.ljust(label_width)
- print(f'{" " * indent}\x1b[90m{label_with_whitespace}\x1b[0m {content}')
-
-
-def get_weekday(date: str) -> str:
- '''
- get weekday from date
-
- @param date: date as ISO-8601-formatted string (YYYY-mm-dd)
-
- @return weekday as lowercase string (e.g. 'monday')
- '''
- return datetime.datetime.strptime(date, '%Y-%m-%d').strftime('%A').lower()
-
-
-def colorize(text: str, color: str) -> str:
- '''
- wrap `text` with pango markup to colorize it for usage with waybar.
-
- @param text: the text to colorize
- @param color: the color as string ('#rrggbb')
- '''
- return f'{text}'
-
-
-def waybar_entry(label: str, content: str, indent: int = 2, label_width: int = 9):
- '''
- create an 'entry' for a waybar tooltip that consists of a label (printed in
- gray) and some content. the labels are automatically filled with whitespace
- to align multiple lines properly.
-
- @param label: the label of the line
- @param content: content, printed after the label
- @param indent: number of spaces to indent with
- @param label_width: width of label
-
- @return the entry for use within waybar
- '''
-
- label_with_whitespace = label.ljust(label_width)
- return f'{" " * indent}{colorize(label_with_whitespace, GRAY)} {content}\n'
-
-
-
-### GEOCODING ###
-
-def geocoding(search: str):
- '''
- call openweathermap's geocoding api to find the coordinates of cities. can
- be used to find the values required for the `LATITUDE` and `LONGITUDE`
- constants within this script. the results are printed.
-
- @param: search term in the format 'city[,state][,country]'
- '''
-
- res = make_request(f'geo/1.0/direct?q={search}&limit=5')
- num_results = len(res)
-
- if (num_results == 0):
- print_error('no results found')
- else:
- print(f'found {num_results} result{"" if num_results == 1 else "s"}:')
- for entry in res:
- # obtain data
- name = entry['name']
- state = entry['state'] if 'state' in entry.keys() else None
- country = entry['country']
- latitude = entry['lat']
- longitude = entry['lon']
-
- # print data
- print(f' - \x1b[32m{name}\x1b[90m',
- f'({f"{state}, " if state else ""}{country})\x1b[0m:',
- f'latitude = \x1b[35m{latitude}\x1b[0m,',
- f'longitude = \x1b[35m{longitude}\x1b[0m')
-
-
-### CURRENT WEATHER ###
-
-def get_current_weather_data() -> dict:
- '''
- get current weather data from openweathermap api. when the `rain` is not
- set (due to there not being any rain), it will be added with a rain amount
- of 0 mm over the last hour.
-
- @return api response
- '''
-
- res = make_request(f'data/2.5/weather?lat={LATITUDE}&lon={LONGITUDE}&units=metric')
-
- if 'rain' not in res.keys():
- res['rain'] = { '1h': 0 }
-
- return res
-
-
-def current_weather():
- '''
- print current weather information
- '''
-
- data = get_current_weather_data()
-
- # collect relevant data
- weather = data['weather'][0]['description'].lower()
- temperature = round(data['main']['temp'], 1)
- temperature_felt = round(data['main']['feels_like'], 1)
- humidity = data['main']['humidity']
- wind_speed = round(data['wind']['speed'], 1)
- wind_direction = get_wind_direction(data['wind']['deg'])
- rainfall = data['rain']['1h']
-
- # print data
- print_entry('weather', f'\x1b[32m{weather}\x1b[0m')
- print_entry('temp', f'\x1b[33m{temperature} °C\x1b[90m, feels like \x1b[33m{temperature_felt} °C\x1b[0m')
- print_entry('humidity', f'\x1b[31m{humidity} % RH\x1b[0m')
- print_entry('wind', f'\x1b[35m{wind_speed} m/s\x1b[90m ({wind_direction})\x1b[0m')
- print_entry('rain', f'\x1b[34m{rainfall} mm\x1b[0m')
-
-
-
-### FORECAST ###
-
-def get_forecast_data() -> dict:
- '''
- get forecast data for the next ~5 days from the openweathermap api, with
- data points separated by 3 hours. the data is grouped by date (the api does
- not group the data by default and instead sends it as one sequence).
-
- @return api response grouped by date
- '''
-
- res = make_request(f'data/2.5/forecast?lat={LATITUDE}&lon={LONGITUDE}&units=metric')
-
- days = dict()
- for i in res['list']:
- day = i['dt_txt'].split(' ')[0]
- if day not in days.keys():
- days[day] = list()
- if 'rain' not in i.keys():
- i['rain'] = { '3h': 0 }
- days[day].append(i)
-
- return days
-
-
-def get_daily_forecast_data() -> dict[dict]:
- '''
- obtain forecast data for the next ~5 days, where values are grouped by day.
- since the api only provides the data in 3h intervals, the properties of
- different data points are combined in order to provide appropriate data for
- each day.
-
- @return the processed data as a dict with key = date and value = data as
- another dict
- '''
-
- res = get_forecast_data()
-
- output = dict()
-
- for day in sorted(res):
- data = res[day]
- number_of_data_points = len(data)
-
- # collect relevant from data for each day
- temperatures = [i['main']['temp'] for i in data]
- weather_descriptions = [i['weather'][0]['description'].lower() for i in data]
- humidity = [i['main']['humidity'] for i in data]
- rainfall = [i['rain']['3h'] for i in data]
- precipitation_prob = [i['pop'] for i in data]
- wind_speeds = [i['wind']['speed'] for i in data]
- weekday = get_weekday(day)
-
- # min and max temperature for the day
- min_temperature = round(min(temperatures))
- max_temperature = round(max(temperatures))
-
- # obtain the average weather by finding the weather description with the highest number of occurances in `weather_descriptions`
- weather_count = {i: weather_descriptions.count(i) for i in set(weather_descriptions)}
- weather_count_max = max(weather_count.values())
- weather_average = tuple(filter(lambda x: weather_count[x] == weather_count_max, weather_count.keys()))[0]
-
- # humidiy
- humidity_average = round(statistics.mean(humidity))
-
- # total rainfall and probability of precipitation. also, estimate the total rainfall if not all data points for a day are available
- rainfall_total = round(sum(rainfall), 1)
- rainfall_total_estimated = round(rainfall_total / number_of_data_points * 8, 1)
- max_precipitation_prob = round(max(precipitation_prob) * 100)
-
- # average wind
- wind_average = round(statistics.mean(wind_speeds), 1)
-
- output[day] = {
- 'number_of_data_points': number_of_data_points,
- 'min_temperature': min_temperature,
- 'max_temperature': max_temperature,
- 'weather_average': weather_average,
- 'humidity_average': humidity_average,
- 'rainfall_total': rainfall_total,
- 'rainfall_total_estimated': rainfall_total_estimated,
- 'max_precipitation_prob': max_precipitation_prob,
- 'wind_average': wind_average,
- 'weekday': weekday,
- }
-
- return output
-
-
-def daily_forecast():
- '''
- print forecast data for the next ~5 days
- '''
-
- daily_data = get_daily_forecast_data()
-
- for day in sorted(daily_data):
- data = daily_data[day]
-
- # only display data point if at least half of the data points are available
- if data['number_of_data_points'] < 4:
- continue
-
- # print data
- print(f'\x1b[1m{day}\x1b[0m ({data["weekday"]}):')
- print_entry('weather', f'\x1b[32m{data["weather_average"]}\x1b[0m', indent = 2)
- print_entry('temp', f'\x1b[33m{data["max_temperature"]} °C\x1b[0m / \x1b[33m{data["min_temperature"]} °C\x1b[0m', indent = 2)
- print_entry('humidity', f'\x1b[31m{data["humidity_average"]} % RH\x1b[0m', indent = 2)
- print_entry('wind', f'\x1b[35m{data["wind_average"]} m/s\x1b[0m', indent = 2)
- print_entry('rain', f'\x1b[34m{data["rainfall_total_estimated"]} mm\x1b[0m' +
- f'\x1b[90m{f""" ({data["max_precipitation_prob"]}%)""" if data["max_precipitation_prob"] > 0 else ""}' +
- f'{f" (estimated)" if data["rainfall_total"] != data["rainfall_total_estimated"] else ""}\x1b[0m\n', indent = 2)
-
-
-
-### DETAILED FORECAST ###
-
-def detailed_forecast():
- '''
- print forecast data for the next ~5 days, where values are printed for
- every 3h interval provided by the api. some data (e.g. humidity or wind
- speeds) are omitted.
- '''
-
- res = get_forecast_data()
-
- for day in sorted(res):
- weekday = get_weekday(day)
- print(f'\x1b[1m{day}\x1b[0m ({weekday})')
-
- for entry in res[day]:
- # collect data
- weather = entry['weather'][0]['description'].lower()
- temperature = round(entry['main']['temp'], 1)
- rainfall = entry['rain']['3h']
- precipitation_prob = round(entry['pop'] * 100)
- time = f"{int(entry['dt_txt'].split(' ')[1].split(':')[0]):2}h"
-
- # print data
- output = ''
- output += f'\x1b[33m{temperature:4} °C\x1b[90m, '
- output += f'\x1b[32m{weather}\x1b[0m'
- if rainfall > 0:
- output += f'\x1b[90m: \x1b[34m{rainfall} mm \x1b[90m({precipitation_prob}%)\x1b[0m'
- print_entry(time, output, indent = 2, label_width = 3)
-
- print()
-
-
-
-### WAYBAR ###
-
-def waybar_widget(data: dict) -> str:
- '''
- get the widget component of the waybar output. contains the current weather
- group and temperature.
-
- @param current weather data
-
- @return widget component
- '''
-
- weather = data['weather'][0]['main'].lower()
- temperature = round(data['main']['temp'])
-
- return f'{colorize(weather, MOIST)} {temperature}°'
-
-
-def waybar_current(data: dict) -> str:
- '''
- get the current weather overview for the tooltip of the waybar output.
-
- @param current weather data
-
- @return formatted current weather overview
- '''
-
- # retrieve relevant data
- weather = data['weather'][0]['description'].lower()
- temperature = round(data['main']['temp'], 1)
- temperature_felt = round(data['main']['feels_like'], 1)
- humidity = data['main']['humidity']
- wind_speed = round(data['wind']['speed'], 1)
- wind_direction = get_wind_direction(data['wind']['deg'])
- rainfall = data['rain']['1h']
-
- # generate output
- output = ''
- output += waybar_entry('weather', colorize(weather, YELLOW))
- output += waybar_entry('temp', f'{colorize(f"{temperature} °C", ORANGE)}{colorize(", feels like ", GRAY)}{colorize(f"{temperature_felt} °C", ORANGE)}')
- output += waybar_entry('humidity', colorize(f'{humidity} % RH', RED))
- output += waybar_entry('wind', f'{colorize(f"{wind_speed} m/s", PURPLE)} {colorize(f"({wind_direction})", GRAY)}')
- output += waybar_entry('rain', colorize(f"{rainfall} mm", BLUE))
- return output
-
-
-def waybar_forecast(data: dict) -> str:
- '''
- get the daily forecast for the tooltip of the waybar output.
-
- @param forecast weather data
-
- @return formatted daily forecast
- '''
-
- output = ''
-
- daily_data = get_daily_forecast_data()
-
- for day in sorted(daily_data):
- data = daily_data[day]
-
- line_content = colorize(f'{data["max_temperature"]:2}°', ORANGE) + \
- colorize(' / ', GRAY) + \
- colorize(f'{data["min_temperature"]:2}°', ORANGE) + \
- colorize(', ', GRAY) + \
- colorize(data['weather_average'], YELLOW)
-
- if data['rainfall_total_estimated'] > 0:
- line_content += colorize(': ', GRAY) + \
- colorize(f'{data["rainfall_total_estimated"]} mm ', BLUE) + \
- colorize(f'({data["max_precipitation_prob"]}%)', GRAY)
-
- output += waybar_entry(data['weekday'], line_content)
-
- return output.rstrip()
-
-
-def waybar():
- '''
- get current and forecast weather data and output it formatted in a way that
- allows it to be included as a widget in waybar. only shows weather category
- and temperature in the widget, but reveals detailed weather information and
- a ~5 day forecast in the tooltip.
- '''
-
- current_data = get_current_weather_data()
- forecast_data = get_forecast_data()
-
- widget = waybar_widget(current_data)
- current = waybar_current(current_data)
- forecast = waybar_forecast(forecast_data)
- tooltip = colorize('current weather', GREEN) + '\n' + current + '\n' + \
- colorize('forecast', GREEN) + '\n' + forecast
-
- print(json.dumps({
- 'text': widget,
- 'tooltip': tooltip,
- }))
-
-
-
-### MAIN ###
-
-def main():
- '''
- main function
- '''
-
- # no parameters or `--help`
- if len(sys.argv) == 1 or sys.argv[1] in ('help', '-h', '--help'):
- print_help()
-
- # >= 1 parameter provided
- else:
- # geocoding
- if sys.argv[1] == 'geocoding':
- if len(sys.argv) == 3:
- geocoding(sys.argv[2])
- else:
- print_error('expected argument ``')
- print_help()
- # constants not set
- elif API_KEY is None or LATITUDE is None or LONGITUDE is None:
- print_error('please modify the constants within the script before use.')
- # current weather
- elif sys.argv[1] == 'current':
- current_weather()
- # daily forecast
- elif sys.argv[1] == 'forecast' or sys.argv[1] == 'forecast-daily':
- daily_forecast()
- # detailed forecast
- elif sys.argv[1] == 'forecast-detail':
- detailed_forecast()
- # waybar
- elif sys.argv[1] == 'waybar':
- waybar()
- # unknown command
- else:
- print_error(f'unknown command `{sys.argv[1]}`')
- print_help()
-
-if __name__ == '__main__':
- main()
-
diff --git a/home/hyprland/waybar/default.nix b/home/hyprland/waybar/default.nix
index 4e14d6e..f60c6e1 100644
--- a/home/hyprland/waybar/default.nix
+++ b/home/hyprland/waybar/default.nix
@@ -1,44 +1,11 @@
{
pkgs,
- config,
...
}:
{
programs.waybar = {
enable = true;
package = pkgs.waybar;
- /*
- settings = {
- mainBar = {
- layer = "top";
- position = "top";
- height = 30;
- output = [
- "eDP-1"
- "DP-1"
- "HDMI-A-1"
- "Virtual-1"
- ];
-
- modules-left = [ "sway/workspaces" "sway/mode" "wlr/taskbar" ];
- modules-center = [ "sway/window" "custom/hello-from-waybar" ];
- modules-right = [ "mpd" "custom/mymodule#with-css-id" "temperature" ];
-
- "sway/workspaces" = {
- disable-scroll = true;
- all-outputs = true;
- };
- "custom/hello-from-waybar" = {
- format = "hello {}";
- max-length = 40;
- interval = "once";
- exec = pkgs.writeShellScript "hello-from-waybar" ''
- echo "from within waybar $USER"
- '';
- };
- };
- };
- */
};
home.file.".config/waybar" = {
diff --git a/home/hyprland/waybar/dual.nix b/home/hyprland/waybar/dual.nix
index 5dc8858..a63bfc6 100644
--- a/home/hyprland/waybar/dual.nix
+++ b/home/hyprland/waybar/dual.nix
@@ -1,188 +1,42 @@
+let
+ common = import ./common.nix;
+ hyprland = import ./hyprland.nix;
+in
{
enable = true;
settings = {
- mainBar = {
- layer = "top";
- position = "top";
- height = 30;
- output = [ "DP-1" ];
-
- modules-left = [
- "hyprland/workspaces"
- "mpris"
- ];
-
- modules-center = [ ];
-
- modules-right = [
- "network"
- "memory"
- "cpu"
- "clock"
- ];
-
- # Widgets
- "sway/workspaces" = {
- disable-scroll = true;
- all-outputs = true;
- };
-
- mpris = {
- format = "{player_icon} {dynamic}";
- format-paused = "{status_icon} {dynamic}";
- max-length = 100;
-
- player-icons = {
- default = "⏸";
- mpv = "🎵";
- };
-
- status-icons = {
- paused = "▶";
- };
- };
-
- "hyprland/workspaces" = {
- format = "{icon}";
- format-icons = {
- default = "";
- active = "";
- };
- };
-
- network = {
- tooltip = true;
- format-wifi = "{icon} ";
- format-icons = [
- ""
- ""
- ""
+ mainBar =
+ {
+ layer = "top";
+ position = "top";
+ height = 30;
+ output = [ "DP-1" ];
+ modules-left = [
+ "custom/nixicon"
+ "clock"
];
- rotate = 0;
- format-ethernet = " ";
- tooltip-format = "Network: {essid}\nSignal strength: {signaldBm}dBm ({signalStrength}%)\nFrequency: {frequency}MHz\nInterface: {ifname}\nIP: {ipaddr}/{cidr}\nGateway: {gwaddr}\nNetmask: {netmask}";
- format-linked = " {ifname} (No IP)";
- format-disconnected = " ";
- tooltip-format-disconnected = "Disconnected";
- on-click = "/usr/local/bin/ags -t ControlPanel";
- interval = 2;
- };
-
- memory = {
- interval = 1;
- rotate = 270;
- format = "{icon}";
- format-icons = [
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
+ modules-center = [
+ "hyprland/workspaces"
];
- max-length = 10;
- };
-
- cpu = {
- interval = 1;
- format = "{icon}";
- rotate = 270;
- format-icons = [
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
+ modules-right = [
+ "group/hardware"
];
- };
+ }
+ // common.widgets
+ // hyprland.widgets;
- clock = {
- format = "{:%I:%M %p}";
- rotate = 0;
- on-click = "/usr/local/bin/ags -t ActivityCenter";
- tooltip-format = "{calendar}";
-
- calendar = {
- mode = "month";
- mode-mon-col = 3;
- on-scroll = 1;
- on-click-right = "mode";
- format = {
- months = "{}";
- weekdays = "{}";
- today = "{}";
- };
- };
-
- actions = {
- on-click-right = "mode";
- on-click-forward = "tz_up";
- on-click-backward = "tz_down";
- on-scroll-up = "shift_up";
- on-scroll-down = "shift_down";
- };
- };
-
- };
-
- secondBar = {
- layer = "top";
- position = "top";
- height = 30;
- output = [
- "HDMI-A-2"
- ];
-
- modules-left = [
- "hyprland/workspaces"
- ];
-
- modules-center = [
- ];
-
- modules-right = [
- "network"
- ];
-
- "hyprland/workspaces" = {
- format = "{icon}";
- format-icons = {
- default = "";
- active = "";
- };
- };
-
- "custom/weather" = {
- exec = "~/.config/waybar/weather.py waybar";
- restart-interval = 900;
- return-type = "json";
- };
-
- network = {
- tooltip = true;
- format-wifi = "{icon} ";
- format-icons = [
- ""
- ""
- ""
- ];
- rotate = 0;
- format-ethernet = "{bandwidthTotalBits} {bandwidthUpBits} {bandwidthDownBits} ";
- tooltip-format = "Network: {essid}\nSignal strength: {signaldBm}dBm ({signalStrength}%)\nFrequency: {frequency}MHz\nInterface: {ifname}\nIP: {ipaddr}/{cidr}\nGateway: {gwaddr}\nNetmask: {netmask}";
- format-linked = " {ifname} (No IP)";
- format-disconnected = " ";
- tooltip-format-disconnected = "Disconnected";
- on-click = "/usr/local/bin/ags -t ControlPanel";
- interval = 2;
- };
- };
+ secondBar =
+ {
+ layer = "top";
+ position = "top";
+ height = 30;
+ output = [ "HDMI-A-2" ];
+ modules-left = [ "group/media" ];
+ modules-center = [ "hyprland/workspaces" ];
+ modules-right = [ "custom/weather" ];
+ }
+ // common.widgets
+ // hyprland.widgets;
};
}
diff --git a/home/hyprland/waybar/hyprland.nix b/home/hyprland/waybar/hyprland.nix
new file mode 100644
index 0000000..59aa729
--- /dev/null
+++ b/home/hyprland/waybar/hyprland.nix
@@ -0,0 +1,11 @@
+{
+ widgets = {
+ "hyprland/workspaces" = {
+ format = "{icon}";
+ format-icons = {
+ default = "";
+ active = "";
+ };
+ };
+ };
+}
diff --git a/home/hyprland/waybar/single.nix b/home/hyprland/waybar/single.nix
index d1c27ac..c942a30 100644
--- a/home/hyprland/waybar/single.nix
+++ b/home/hyprland/waybar/single.nix
@@ -1,150 +1,39 @@
+let
+ common = import ./common.nix;
+ hyprland = import ./hyprland.nix;
+in
{
enable = true;
settings = {
- mainBar = {
- layer = "top";
- position = "top";
- height = 30;
- output = [
- "eDP-1"
- "DP-1"
- "HDMI-A-1"
- "Virtual-1"
- ];
-
- modules-left = [
- "hyprland/workspaces"
- "mpris"
- ];
-
- modules-center = [
- "custom/weather"
- ];
-
- modules-right = [
- "network"
- "memory"
- "cpu"
- "clock"
- ];
-
- # Widgets
- "sway/workspaces" = {
- disable-scroll = true;
- all-outputs = true;
- };
-
- mpris = {
- format = "{player_icon} {dynamic}";
- format-paused = "{status_icon} {dynamic}";
- max-length = 100;
-
- player-icons = {
- default = "⏸";
- mpv = "🎵";
- };
-
- status-icons = {
- paused = "▶";
- };
- };
-
- "hyprland/workspaces" = {
- format = "{icon}";
- format-icons = {
- default = "";
- active = "";
- };
- };
-
- network = {
- tooltip = true;
- format-wifi = "{icon} ";
- format-icons = [
- ""
- ""
- ""
+ mainBar =
+ {
+ layer = "top";
+ position = "top";
+ height = 30;
+ /*
+ Waybar should use every display available if not output is specified
+ output = [
+ "eDP-1"
+ "DP-1"
+ "HDMI-A-1"
+ "Virtual-1"
+ ];
+ */
+ modules-left = [
+ "custom/nixicon"
+ "clock"
+ "group/media"
];
- rotate = 0;
- format-ethernet = " ";
- tooltip-format = "Network = {essid}\nSignal strength: {signaldBm}dBm ({signalStrength}%)\nFrequency: {frequency}MHz\nInterface: {ifname}\nIP: {ipaddr}/{cidr}\nGateway: {gwaddr}\nNetmask: {netmask}";
- format-linked = " {ifname} (No IP)";
- format-disconnected = " ";
- tooltip-format-disconnected = "Disconnected";
- on-click = "/usr/local/bin/ags -t ControlPanel";
- interval = 2;
- };
-
- memory = {
- interval = 1;
- rotate = 270;
- format = "{icon}";
- format-icons = [
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
+ modules-center = [
+ "hyprland/workspaces"
];
- max-length = 10;
- };
-
- cpu = {
- interval = 1;
- format = "{icon}";
- rotate = 270;
- format-icons = [
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
+ modules-right = [
+ "custom/weather"
+ "group/hardware"
];
- };
-
- clock = {
- format = "{:%I:%M %p}";
- rotate = 0;
- on-click = "/usr/local/bin/ags -t ActivityCenter";
- tooltip-format = "{calendar}";
-
- calendar = {
- mode = "month";
- mode-mon-col = 3;
- on-scroll = 1;
- on-click-right = "mode";
- format = {
- months = "{}";
- weekdays = "{}";
- today = "{}";
- };
- };
-
- actions = {
- on-click-right = "mode";
- on-click-forward = "tz_up";
- on-click-backward = "tz_down";
- on-scroll-up = "shift_up";
- on-scroll-down = "shift_down";
- };
- };
-
- # Custom Widgets
- "custom/weather" = {
- exec = "python3 ~/.config/waybar/weather.py waybar";
- restart-interval = 900;
- return-type = "json";
- };
-
- };
+ # Widget configurations
+ }
+ // common.widgets
+ // hyprland.widgets;
};
-
}