Added: Waybar Conf
This commit is contained in:
		@@ -11,6 +11,8 @@ in
 | 
			
		||||
{
 | 
			
		||||
    imports = [
 | 
			
		||||
        ./kitty.nix # Terminal
 | 
			
		||||
        ../waybar 
 | 
			
		||||
        ../rofi
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										607
									
								
								home/waybar/config/config.jsonc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										607
									
								
								home/waybar/config/config.jsonc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,607 @@
 | 
			
		||||
//   --// waybar config generated by wbarconfgen.sh //--   //
 | 
			
		||||
 | 
			
		||||
[
 | 
			
		||||
/*{
 | 
			
		||||
  "layer": "top",
 | 
			
		||||
  "position": "left",
 | 
			
		||||
  "mod": "dock",
 | 
			
		||||
  "width": 20,
 | 
			
		||||
  "margin-top": 200,
 | 
			
		||||
  "margin-bottom": 200,
 | 
			
		||||
  "exclusive": true,
 | 
			
		||||
  "passthrough": false,
 | 
			
		||||
  "gtk-layer-shell": true,
 | 
			
		||||
  "reload_style_on_change": true,
 | 
			
		||||
  "output": "HDMI-A-2",
 | 
			
		||||
 | 
			
		||||
	"modules-left": [],
 | 
			
		||||
	"modules-center": ["wlr/taskbar"],
 | 
			
		||||
	"modules-right": [],
 | 
			
		||||
  
 | 
			
		||||
  "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": "<span color='#021c18'></span> <span color='#313436'></span> ",
 | 
			
		||||
    "format-alt": " <span color='#bbc2c7'></span> ",
 | 
			
		||||
    "on-click": "~/mouse.sh",
 | 
			
		||||
    "tooltip": false,
 | 
			
		||||
},
 | 
			
		||||
 | 
			
		||||
"upower": {
 | 
			
		||||
     "icon-size": 20,
 | 
			
		||||
      "format": "",
 | 
			
		||||
     "format-alt": "{}<span color='orange'>[{time}]</span>",
 | 
			
		||||
     "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": "<span color='grey'>{status_icon} {dynamic}</span>",
 | 
			
		||||
	"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": "<span  weight='bold' >{class}</span>",
 | 
			
		||||
 "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": "<tt>{calendar}</tt>",
 | 
			
		||||
        "calendar": {
 | 
			
		||||
            "mode": "month",
 | 
			
		||||
            "mode-mon-col": 3,
 | 
			
		||||
            "on-scroll": 1,
 | 
			
		||||
            "on-click-right": "mode",
 | 
			
		||||
            "format": {
 | 
			
		||||
                "months": "<span color='#ffead3'><b>{}</b></span>",
 | 
			
		||||
                "weekdays": "<span color='#ffcc66'><b>{}</b></span>",
 | 
			
		||||
                "today": "<span color='#ff6699'><b>{}</b></span>"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "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": "<span color='#a6d189'></span>",
 | 
			
		||||
        "format-plugged": "",
 | 
			
		||||
       // "format-alt": "<<span weight='bold' color='#c2864a'>{time} <span weight='bold' color='white'>| <span weight='bold' color='#82d457'>{capacity}%</span></span></span>",
 | 
			
		||||
        "format-icons": ["","","","","","","","",""],
 | 
			
		||||
     //  "format-icons": ["","","","","","","",""],  
 | 
			
		||||
       //"format-icons": ["", "", "", "", "", "", "", "", "", "", ""],
 | 
			
		||||
        "on-click-right": "pkill waybar & hyprctl dispatch exec waybar",
 | 
			
		||||
      //  "format-icons": [<i class='fa-solid fa-wifi-slash'></i>],
 | 
			
		||||
    
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    "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": "<i class='fa-solid fa-wifi-slash'></i>",
 | 
			
		||||
        "rotate": 0,
 | 
			
		||||
        "format-ethernet": " ",
 | 
			
		||||
        "tooltip-format": "Network: <big><b>{essid}</b></big>\nSignal strength: <b>{signaldBm}dBm ({signalStrength}%)</b>\nFrequency: <b>{frequency}MHz</b>\nInterface: <b>{ifname}</b>\nIP: <b>{ipaddr}/{cidr}</b>\nGateway: <b>{gwaddr}</b>\nNetmask: <b>{netmask}</b>",
 | 
			
		||||
        "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": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "chat-notification": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "warning-notification": "<span foreground='yellow'><sup></sup></span>",
 | 
			
		||||
            "error-notification": "<span foreground='red'><sup></sup></span>",
 | 
			
		||||
            "network-notification": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "battery-notification": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "update-notification": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "music-notification": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "volume-notification": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "notification": "<span foreground='white'><sup></sup></span>",
 | 
			
		||||
            "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": "<i class='fa-solid fa-wifi-slash'></i>",
 | 
			
		||||
    "rotate": 0,
 | 
			
		||||
    "format-ethernet": "{bandwidthTotalBits}  {bandwidthUpBits}  {bandwidthDownBits}   ",
 | 
			
		||||
    "tooltip-format": "Network: <big><b>{essid}</b></big>\nSignal strength: <b>{signaldBm}dBm ({signalStrength}%)</b>\nFrequency: <b>{frequency}MHz</b>\nInterface: <b>{ifname}</b>\nIP: <b>{ipaddr}/{cidr}</b>\nGateway: <b>{gwaddr}</b>\nNetmask: <b>{netmask}</b>",
 | 
			
		||||
    "format-linked": " {ifname} (No IP)",
 | 
			
		||||
    "format-disconnected": " ",
 | 
			
		||||
    "tooltip-format-disconnected": "Disconnected",
 | 
			
		||||
    "on-click": "/usr/local/bin/ags -t ControlPanel",
 | 
			
		||||
    "interval": 1,
 | 
			
		||||
    },
 | 
			
		||||
}]
 | 
			
		||||
							
								
								
									
										397
									
								
								home/waybar/config/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								home/waybar/config/style.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,397 @@
 | 
			
		||||
* {
 | 
			
		||||
    font-family: "JetBrains Mono Nerd Font";
 | 
			
		||||
    /*font-family: "JetBrainsMono Nerd Font";*/
 | 
			
		||||
    font-weight: bold; 
 | 
			
		||||
    font-size: 15px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-notification {
 | 
			
		||||
  font-family: "JetBrains Mono Nerd Font";
 | 
			
		||||
  font-size: 17px;
 | 
			
		||||
 color: #A1BDCE;
 | 
			
		||||
 margin: 2px 0px 0px 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
window#waybar {
 | 
			
		||||
    background: #092047; 
 | 
			
		||||
  /*  border-radius: 15px; */
 | 
			
		||||
 /*  border: 2px solid #124323; */
 | 
			
		||||
/* border: 0px solid #A1BDCE; */
 | 
			
		||||
 border: 3px solid rgba(172, 97, 185, 1);
 | 
			
		||||
 border-radius: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tooltip {
 | 
			
		||||
        background: #171717;
 | 
			
		||||
        color: #A1BDCE;
 | 
			
		||||
        font-size: 13px;
 | 
			
		||||
        border-radius: 7px;
 | 
			
		||||
       border: 2px solid #101a24;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
#workspaces{
 | 
			
		||||
background: rgba(23, 23, 23, 0.0);
 | 
			
		||||
    color: #888789;
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
	text-shadow: none;
 | 
			
		||||
    border-radius: 9px;
 | 
			
		||||
    transition: 0.2s ease;
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
    padding-top: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#workspaces button {
 | 
			
		||||
background: rgba(23, 23, 23, 0.0);
 | 
			
		||||
    color: #A1BDCE;
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
	text-shadow: none;
 | 
			
		||||
    border-radius: 9px;
 | 
			
		||||
    transition: 0.2s ease;
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
 /*   animation: ws_normal 20s ease-in-out 1; */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#workspaces button.active {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
  /* background-image: url("/home/anik/Documents/bar1.png");*/
 | 
			
		||||
    color: #FF2A6D;   
 | 
			
		||||
    transition: all 0.3s ease;
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
  /*  transition: all 0.4s cubic-bezier(.55,0.68,.48,1.682); */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#workspaces button:hover {
 | 
			
		||||
    background: none;
 | 
			
		||||
    color: #65DC98;
 | 
			
		||||
    animation: ws_hover 20s ease-in-out 1;
 | 
			
		||||
    transition: all 0.5s cubic-bezier(.55,-0.68,.48,1.682);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#taskbar button {
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
	text-shadow: none;
 | 
			
		||||
	font-size: 4px;
 | 
			
		||||
    padding: 0px;
 | 
			
		||||
    border-radius: 9px;
 | 
			
		||||
    margin-bottom: 3px;
 | 
			
		||||
    margin-left: 0px;
 | 
			
		||||
    padding-left: 3px;
 | 
			
		||||
    padding-right: 3px;
 | 
			
		||||
    margin-right: 0px;
 | 
			
		||||
    color: @wb-color;
 | 
			
		||||
    animation: tb_normal 20s ease-in-out 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#taskbar button.active {
 | 
			
		||||
    background: @wb-act-bg;
 | 
			
		||||
    color: @wb-act-color;
 | 
			
		||||
    margin-left: 3px;
 | 
			
		||||
    padding-left: 12px;
 | 
			
		||||
    padding-right: 12px;
 | 
			
		||||
    margin-right: 3px;
 | 
			
		||||
    animation: tb_active 20s ease-in-out 1;
 | 
			
		||||
    transition: all 0.4s cubic-bezier(.55,-0.68,.48,1.682);
 | 
			
		||||
    min-height: 9px; 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#taskbar button:hover {
 | 
			
		||||
    background: @wb-hvr-bg;
 | 
			
		||||
    color: @wb-hvr-color;
 | 
			
		||||
    animation: tb_hover 20s ease-in-out 1;
 | 
			
		||||
    transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#tray menu * {
 | 
			
		||||
    min-height: 16px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    font-size: 13px;
 | 
			
		||||
    color: #9488e3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#tray menu separator {
 | 
			
		||||
    min-height: 10px
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#custom-spacer{
 | 
			
		||||
opacity: 0.0;
 | 
			
		||||
}
 | 
			
		||||
#custom-smallspacer{
 | 
			
		||||
opacity: 0.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#custom-mouse{
 | 
			
		||||
font-size: 14px;
 | 
			
		||||
margin-bottom: 6px;
 | 
			
		||||
background:  #161320;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#custom-power{
 | 
			
		||||
    font-size: 15px;
 | 
			
		||||
    color: #FFFFFF;
 | 
			
		||||
    background:  rgba(22, 19, 32, 0.9);
 | 
			
		||||
    margin: 6px 0px 6px 0px;
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#backlight{
 | 
			
		||||
    color: #2096C0;
 | 
			
		||||
    background: rgba(23, 23, 23, 0.0);
 | 
			
		||||
    font-weight: normal;
 | 
			
		||||
    font-size: 19px;
 | 
			
		||||
    margin: 1px 0px 0px 0px;
 | 
			
		||||
    padding-left: 0px;
 | 
			
		||||
    padding-right: 2px;
 | 
			
		||||
 
 | 
			
		||||
}
 | 
			
		||||
#bluetooth,
 | 
			
		||||
#custom-cliphist{
 | 
			
		||||
    color: #E6E7E7;
 | 
			
		||||
    background:  #161320;
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    margin: 4px 0px 4px 0px;
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
 
 | 
			
		||||
}
 | 
			
		||||
#battery{
 | 
			
		||||
    font-weight: normal;
 | 
			
		||||
    font-size: 22px;
 | 
			
		||||
    color: #a6d189;
 | 
			
		||||
    background:  rgba(23, 23, 23, 0.0);
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    margin: 0px 0px 0px 0px;
 | 
			
		||||
    padding-left: 0px;
 | 
			
		||||
    padding-right: 0px;
 | 
			
		||||
 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#idle_inhibitor{
 | 
			
		||||
color: #24966e;
 | 
			
		||||
background: @bar-bg;
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    margin: 4px 0px 4px 0px;
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
#clock{
 | 
			
		||||
    color: #FDD870;
 | 
			
		||||
    font-size: 15px;
 | 
			
		||||
    font-weight: 900;
 | 
			
		||||
    font-family: "JetBrains Mono Nerd Font";
 | 
			
		||||
    background: rgba(23, 23, 23, 0.0);
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    margin: 3px 0px 0px 0px;
 | 
			
		||||
    padding-left: 10px;
 | 
			
		||||
    padding-right: 10px;
 | 
			
		||||
    border: none;
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
#pulseaudio{
 | 
			
		||||
font-weight: normal;
 | 
			
		||||
font-size: 18px;
 | 
			
		||||
color: #0A9CF5;
 | 
			
		||||
    background:  rgba(22, 19, 32, 0.0);
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    margin: 0px 0px 0px 0px;
 | 
			
		||||
    padding-left: 3px;
 | 
			
		||||
    padding-right: 3px;
 | 
			
		||||
}
 | 
			
		||||
#cpu{
 | 
			
		||||
font-weight: normal;
 | 
			
		||||
font-size: 22px;
 | 
			
		||||
color: #FF184C;
 | 
			
		||||
}
 | 
			
		||||
#custom-led{
 | 
			
		||||
background: #427287;
 | 
			
		||||
color: #FFFFFF;
 | 
			
		||||
margin-top: 7px;
 | 
			
		||||
margin-bottom: 7px;
 | 
			
		||||
padding-left: 6px;
 | 
			
		||||
border-radius: 7px;
 | 
			
		||||
margin-right: 6px;
 | 
			
		||||
}
 | 
			
		||||
#custom-gpuinfo,
 | 
			
		||||
#custom-keybindhint,
 | 
			
		||||
#language,
 | 
			
		||||
#memory{
 | 
			
		||||
font-weight: normal;
 | 
			
		||||
font-size: 22px;
 | 
			
		||||
color: #1AFE49;
 | 
			
		||||
}
 | 
			
		||||
#mpris{
 | 
			
		||||
color: white;
 | 
			
		||||
animation: repeat;
 | 
			
		||||
	animation-name: blink;
 | 
			
		||||
	animation-duration: 3s;
 | 
			
		||||
    animation-timing-function: linear;
 | 
			
		||||
    animation-iteration-count: infinite;
 | 
			
		||||
    animation-direction: alternate;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@keyframes blink {
 | 
			
		||||
    to {
 | 
			
		||||
        color: #4a4a4a;
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#network{
 | 
			
		||||
color: #FF6E27;
 | 
			
		||||
font-weight: normal;
 | 
			
		||||
font-size: 19px;
 | 
			
		||||
padding-right: 0px;
 | 
			
		||||
padding-left: 4px
 | 
			
		||||
}
 | 
			
		||||
#custom-notifications,
 | 
			
		||||
#custom-spotify,
 | 
			
		||||
#taskbar,
 | 
			
		||||
#custom-theme,
 | 
			
		||||
#custom-menu{
 | 
			
		||||
color: #E8EDF0;
 | 
			
		||||
background:  rgba(23, 23, 23, 0.0);
 | 
			
		||||
margin: 0px 0px 0px 0px;
 | 
			
		||||
    padding-left: 1px;
 | 
			
		||||
    padding-right: 1px;
 | 
			
		||||
    opacity: 0.1
 | 
			
		||||
}
 | 
			
		||||
#tray,
 | 
			
		||||
#custom-updates,
 | 
			
		||||
#custom-wallchange,
 | 
			
		||||
#custom-wbar,
 | 
			
		||||
#window{
 | 
			
		||||
color: #A1BDCE;
 | 
			
		||||
font-family: "Martian Mono";
 | 
			
		||||
}
 | 
			
		||||
#custom-l_end,
 | 
			
		||||
#custom-r_end,
 | 
			
		||||
#custom-sl_end,
 | 
			
		||||
#custom-sr_end,
 | 
			
		||||
#custom-rl_end,
 | 
			
		||||
#cava,
 | 
			
		||||
#upower#headset,
 | 
			
		||||
#upower{
 | 
			
		||||
color: #a6d189;
 | 
			
		||||
}
 | 
			
		||||
#mpris{
 | 
			
		||||
font-size: 15px;
 | 
			
		||||
font-weight: bold
 | 
			
		||||
}
 | 
			
		||||
#custom-rr_end {
 | 
			
		||||
font-weight: normal;
 | 
			
		||||
    color: #E8EDF0;
 | 
			
		||||
    background:  rgba(23, 23, 23, 0.0);
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    margin: 0px 0px 0px 0px;
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
  ;
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#backlight-slider slider,
 | 
			
		||||
#pulseaudio-slider slider {
 | 
			
		||||
  background: #A1BDCE;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  box-shadow: none;
 | 
			
		||||
  margin-right: 7px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#backlight-slider trough,
 | 
			
		||||
#pulseaudio-slider trough {
 | 
			
		||||
  margin-top: -3px;
 | 
			
		||||
  min-width: 90px;
 | 
			
		||||
  min-height: 10px;
 | 
			
		||||
  margin-bottom: -4px;
 | 
			
		||||
  border-radius: 8px;
 | 
			
		||||
  background: #343434;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#backlight-slider highlight,
 | 
			
		||||
#pulseaudio-slider highlight {
 | 
			
		||||
  border-radius: 8px;
 | 
			
		||||
  background-color: #2096C0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#battery.charging, #battery.plugged {
 | 
			
		||||
	color: #E8EDF0;
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#battery.critical:not(.charging) {
 | 
			
		||||
    color: red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#taskbar {
 | 
			
		||||
    padding: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-r_end {
 | 
			
		||||
    border-radius: 0px 7px 7px 0px;
 | 
			
		||||
    margin-right: 1px;
 | 
			
		||||
    padding-right: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-l_end {
 | 
			
		||||
    border-radius: 7px 0px 0px 7px;
 | 
			
		||||
    margin-left: 1px;
 | 
			
		||||
    padding-left: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-sr_end {
 | 
			
		||||
    border-radius: 0px;
 | 
			
		||||
    margin-right: 1px;
 | 
			
		||||
    padding-right: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-sl_end {
 | 
			
		||||
    border-radius: 0px;
 | 
			
		||||
    margin-left: 1px;
 | 
			
		||||
    padding-left: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-rr_end {
 | 
			
		||||
    border-radius: 0px 7px 7px 0px;
 | 
			
		||||
    margin-right: 1px;
 | 
			
		||||
    padding-right: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-rl_end {
 | 
			
		||||
    border-radius: 7px 0px 0px 7px;
 | 
			
		||||
    margin-left: 1px;
 | 
			
		||||
    padding-left: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Style for launchers */
 | 
			
		||||
 | 
			
		||||
#custom-expand {
 | 
			
		||||
    min-width: 25px;
 | 
			
		||||
    color: #A1BDCE;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#group-minimized {
 | 
			
		||||
    border-left: solid;
 | 
			
		||||
    border-left-width: 0.5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#custom-quote {
 | 
			
		||||
  padding-top:0px;
 | 
			
		||||
  color: #999999;
 | 
			
		||||
  font-family: "JetBrains Mono Nerd Font";
 | 
			
		||||
  font-size: 13px;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										528
									
								
								home/waybar/config/weather.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										528
									
								
								home/waybar/config/weather.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,528 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
import datetime
 | 
			
		||||
import json
 | 
			
		||||
import requests
 | 
			
		||||
import statistics
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# TODO
 | 
			
		||||
# - snowfall data
 | 
			
		||||
# - weather warnings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### CONSTANTS ###
 | 
			
		||||
 | 
			
		||||
# api key - get it at https://openweathermap.org/
 | 
			
		||||
API_KEY = "bfca28ca110b5595380d9aad164d5ee5"
 | 
			
		||||
 | 
			
		||||
# latitude and longitude of the city you want to query
 | 
			
		||||
# can be obtained through `./weather.py geocoding <city[,state,country]>`
 | 
			
		||||
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 <subcommand> [options]\x1b[0m')
 | 
			
		||||
    print()
 | 
			
		||||
    print('available subcommands:')
 | 
			
		||||
    print(' - \x1b[32mgeocoding\x1b[0m <city[,state][,country]> : 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'<span foreground="{color}">{text}</span>'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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 `<city[,state][,country]>`')
 | 
			
		||||
                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()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								home/waybar/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								home/waybar/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  pkgs,
 | 
			
		||||
  config,
 | 
			
		||||
  ...
 | 
			
		||||
}: {
 | 
			
		||||
    programs.waybar = {
 | 
			
		||||
        enable = true;
 | 
			
		||||
        package = pkgs.waybar;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    home.file.".config/waybar" = {
 | 
			
		||||
        source = ./configs;
 | 
			
		||||
        # copy the scripts directory recursively
 | 
			
		||||
        recursive = true;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
    
 | 
			
		||||
    ../../home/hyprland
 | 
			
		||||
    ../../home/programs
 | 
			
		||||
    ../../home/rofi
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  programs.git = {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user