Eww-monitor/eww/eww.yuck
2026-02-20 21:15:08 -08:00

257 lines
8.6 KiB
Text

;; weather import
(defpoll ICON :interval "15m" `~/.config/eww/scripts/weather_info --icon`)
(defpoll STAT :interval "15m" `~/.config/eww/scripts/weather_info --stat`)
(defpoll TEMP :interval "5m" `~/.config/eww/scripts/weather_info --temp`)
(defpoll HEX :interval "15m" `~/.config/eww/scripts/weather_info --hex`)
(defpoll QUOTE :interval "15m" `~/.config/eww/scripts/weather_info --quote`)
(defpoll QUOTE2 :interval "15m" `~/.config/eww/scripts/weather_info --quote2`)
;;Time Date Weather ------------------------------------------------------
(defwidget time []
(box :class "box"
:orientation "h"
:space-evenly true
(label :class "time" :text "${time}" :halign "center" :hexpand true)))
(defpoll time :interval "1s"
"date '+%I:%M:%S %P'")
(defwindow time
:monitor 1
:geometry (geometry :x "0.5%"
:y "2%"
:width "270px"
:height "70px"
:anchor "bottom left")
:stacking "bottom"
(time))
(defpoll date :interval "1s"
"date '+%A %D'")
(defwidget date []
(box :class "box"
:orientation "h"
:space-evenly false
(label :class "date" :text "${date}" :xalign 0)))
(defwidget weather []
(box :class "box"
:orientation "h"
:space-evenly false
(label :class "date" :text "${ICON}${TEMP}" :halign "center" :hexpand true)))
(defwindow date
:monitor 1
:geometry (geometry :x "440" :y "2%"
:width "467px" :height "70px"
:anchor "bottom left")
:stacking "bottom"
(date))
(defwindow weather
:monitor 1
:geometry (geometry :x "285" :y "2%"
:width "145px" :height "70px"
:anchor "bottom left")
:stacking "bottom"
(weather))
;; --- Listeners & Polls ---
;; Use `deflisten` with `playerctl --follow` to react to player events
;; efficiently. When a player quits, `playerctl` exits, and the `|| echo`
;; part provides a default value, ensuring the UI updates correctly.
(deflisten song_title :initial "No Music Playing"
"playerctl metadata --format '{{title}}' --follow || echo 'No Music Playing'")
(deflisten song_artist :initial "Unknown Artist"
"playerctl metadata --format '{{artist}}' --follow || echo 'Unknown Artist'")
(deflisten player_status :initial "Stopped"
"playerctl metadata --format '{{status}}' --follow || echo 'Stopped'")
;; Polling is still needed for things that change continuously, like position,
;; but we can use longer, more efficient intervals.
(defpoll song_length_s :interval "2s"
:initial "1"
"playerctl metadata mpris:length | awk '{print $1 / 1000000}' || echo 1")
(defpoll song_position_s :initial "0" :interval "1s" "playerctl position || echo 0")
(defpoll formatted_position :interval "1s" "playerctl position -f '{{duration(position)}}' || echo '0:00'")
;; Cover art and volume can also be polled at a slower rate.
(defpoll cover_art_path :interval "1s" "$HOME/.config/eww/get-cover.sh")
;; Cava runs as a persistent listener, which is correct.
(deflisten cava :initial "" "bash $HOME/.config/eww/cava.sh")
;; --- Widget Definition ---
(defwidget music-widget []
(box :class "music-widget" :orientation "h" :space-evenly false
(box :class "cover-art" :style "background-image: url('${cover_art_path}');")
(box :class "music-info" :orientation "v" :space-evenly false
(label :class "song-title" :text song_title :limit-width 25)
(label :class "artist" :text song_artist :limit-width 25)
(box :class "controls" :orientation "h"
(button :onclick "playerctl previous" "󰒮")
(button :onclick "playerctl play-pause" {player_status == "Playing" ? "󰏤" : "󰐊"})
(button :onclick "playerctl next" "󰒭"))
(label :class "position" :text formatted_position)
(scale :class "progress-bar"
:min 0
:max song_length_s
:value song_position_s
:onchange "playerctl position {}")
(label :class "cava-visualizer" :text cava)
)
)
)
;; --- Window Definition ---
(defwindow music-widget
:monitor 1
:stacking "bottom"
:geometry (
geometry :x "467px"
:y "10px"
:width "440px"
:height "120px"
)
:wm-ignore true
(music-widget))
;;----------------------------------------------------------------------------------------
;;status widget
(defwidget spacer []
(box :class "spacer"))
(defwidget cpu []
(system-progress
:class "cpu"
:tip "CPU ${round(EWW_CPU.avg,1)}%"
:value {round(EWW_CPU.avg, 0)}
:icon ""
:pct "${round(EWW_CPU.avg, 0)}%"))
(defwidget cput []
(system-progress
:class "cput"
:tip "CPU Temp ${EWW_TEMPS["CORETEMP_PACKAGE_ID_0"]}°C"
:value {((EWW_TEMPS["CORETEMP_PACKAGE_ID_0"] - 25) / 75) * 100}
:icon ""
:pct "${EWW_TEMPS["CORETEMP_PACKAGE_ID_0"]}°"))
(defpoll gput :interval "2s" :initial "0"
"nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits")
(defwidget gput []
(system-progress
:class "gput"
:tip "GPU Temp ${gput}°C"
:value {((gput - 25) / 75) * 100}
:icon ""
:pct "${gput}°"))
(defpoll gpu :interval "2s" :initial "0"
"nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits")
(defwidget gpu []
(system-progress
:class "gpu"
:tip "GPU ${gpu}%"
:value {gpu}
:icon ""
:pct "${gpu}%"))
(defwidget ram []
(system-progress
:class "ram"
:tip "RAM ${round(EWW_RAM.used_mem / 1048576, 1)}MB"
:value {round(EWW_RAM.used_mem_perc, 0)}
:icon ""
:pct "${round(EWW_RAM.used_mem / 34359738368 * 100, 0)}%"))
(defwidget swap []
(system-progress
:class "swap"
:tip "Swap ${round((EWW_RAM.total_swap - EWW_RAM.free_swap) / 1048576, 1)}MB"
:value {round((EWW_RAM.total_swap - EWW_RAM.free_swap) / EWW_RAM.total_swap * 100, 0)}
:icon ""
:pct "${round((EWW_RAM.total_swap - EWW_RAM.free_swap) / EWW_RAM.total_swap * 100, 0)}%"))
(defwidget netdown []
(system-progress
:class "netdown"
:tip "Down ${round(EWW_NET["eno1"].NET_DOWN / 1048576, 1)} MB/s"
:value {min(max(log(EWW_NET["eno1"].NET_DOWN / 1024 + 1, 10000) * 100, 0), 100)}
:icon "󰇚"
:pct {EWW_NET["eno1"].NET_DOWN / 1048576 > 1 ? "${round(EWW_NET["eno1"].NET_DOWN / 1048576, 1)}M" : "${round(EWW_NET["eno1"].NET_DOWN / 1024, 0)}Kb"}))
(defwidget netup []
(system-progress
:class "netup"
:tip "Up ${round(EWW_NET["eno1"].NET_UP / 1048576, 1)} MB/s"
:value {min(max(log(EWW_NET["eno1"].NET_UP / 1024 + 1, 10000) * 100, 0), 100)}
:icon "󰕒"
:pct {EWW_NET["eno1"].NET_UP / 1048576 > 1 ? "${round(EWW_NET["eno1"].NET_UP / 1048576, 1)}M" : "${round(EWW_NET["eno1"].NET_UP / 1024, 0)}Kb"}))
(defwidget disk []
(system-progress
:class "disk"
:tip "SSD ${round(EWW_DISK["/"].used_perc, 1)}%"
:value {round(EWW_DISK["/"].used_perc, 0)}
:icon ""
:pct "${round(EWW_DISK["/"].used_perc, 1)}%"))
;;--------------------------------------------------------------------------------------------
(defwidget systemwidget []
(box
:class "system box"
:orientation "h"
:spacing 10
:space-evenly false
(box :orientation "v" :spacing 8 :space-evenly false :hexpand false
(image :path "/home/lorkan/cpu.svg" :image-width 40 :image-height 40)
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
(cpu)
(cput)))
(box :class "spacer" :orientation "v" :hexpand false)
(box :orientation "v" :spacing 8 :space-evenly false :hexpand false
(image :path "/home/lorkan/gpu.svg" :image-width 40 :image-height 40)
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
(gpu)
(gput)))
(box :class "spacer" :orientation "v" :hexpand false)
(box :orientation "v" :spacing 8 :space-evenly false :hexpand false
(image :class "svg" :path "/home/lorkan/ram.png" :image-width 40 :image-height 40)
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
(ram)
(swap)))
(box :class "spacer" :orientation "v" :hexpand false)
(box :orientation "h" :spacing 8 :space-evenly true :hexpand true
(netdown)
(netup)
(disk))))
(defwidget system-progress [class value icon pct tip]
(box
:class "progress"
:orientation "v"
:spacing 0
(progress
:orientation "v"
:flipped true
:class class
:value value
:halign "center"
:tooltip tip)
(box
:orientation "v"
(label :class "label" :text icon :halign "center")
(label :class "label2" :text pct :halign "center"))))
(defwindow status
:monitor 1
:geometry (geometry :x "10px" :y "10px" :width "80px" :height "30px"
:anchor "top l")
:stacking "bottom"
(systemwidget))