From 813efca594541de562dae4de62b2f1b338a3e95a Mon Sep 17 00:00:00 2001 From: Robert Ward <2489404+DotNetRob@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:01:42 -0500 Subject: [PATCH] Add Cat plugin (#59) An animated cat bar widget whose pace reflects CPU usage: sleeps idle, walks under light load, runs under heavy load. Color follows the theme by default or a pinned custom color. Cat artwork traced from the MIT-licensed CatWalk plasmoid into a custom icon font. --- cat/README.md | 38 ++++++++++ cat/cat.luau | 159 +++++++++++++++++++++++++++++++++++++++ cat/fonts/catwalk2.otf | Bin 0 -> 2268 bytes cat/plugin.toml | 76 +++++++++++++++++++ cat/thumbnail.webp | Bin 0 -> 23794 bytes cat/translations/en.json | 35 +++++++++ 6 files changed, 308 insertions(+) create mode 100644 cat/README.md create mode 100644 cat/cat.luau create mode 100644 cat/fonts/catwalk2.otf create mode 100644 cat/plugin.toml create mode 100644 cat/thumbnail.webp create mode 100644 cat/translations/en.json diff --git a/cat/README.md b/cat/README.md new file mode 100644 index 0000000..81659c8 --- /dev/null +++ b/cat/README.md @@ -0,0 +1,38 @@ +# Cat + +An animated cat that lives in your bar. It sleeps when your CPU is idle, +walks as load picks up, and breaks into a full sprint under heavy load — +colored to match your theme, or any color you pick. + +## Plugin + +| Field | Value | +| --- | --- | +| ID | `dotnetrob/cat` | +| Entries | Bar widget: `cat` | + +## Usage + +Add the "Cat" widget to any bar from Settings → Bar → Add Widget. Click the +widget to show a notification with the current CPU percentage. + +## Settings + +| Setting | Type | Default | Description | +| --- | --- | --- | --- | +| `cat_size` | `int` | `24` | Sprite size in the bar, in pixels (12–48). | +| `show_cpu_percent` | `bool` | `false` | Display the CPU percentage next to the cat. | +| `walk_threshold` | `int` | `15` | CPU percentage at which the cat wakes up and starts walking. | +| `run_threshold` | `int` | `60` | CPU percentage at which the cat breaks into a run. | +| `poll_interval` | `int` | `2` | How often to sample CPU usage, in seconds. | +| `cat_color_mode` | `select` | `theme` | `theme` colors the cat with the palette's `secondary` role and tracks theme changes; `custom` uses the color below. | +| `cat_color` | `color` | `#E8A24C` | Used when `cat_color_mode` is `custom`. | + +## Notes + +Every `poll_interval` seconds the widget reads `/proc/stat` to compute CPU +usage — no other files are read or written, nothing is downloaded, and no +processes are spawned. The cat's shape comes from a small custom icon font +(`fonts/catwalk2.otf`) traced from the MIT-licensed +[CatWalk](https://store.kde.org/p/2055225) plasmoid by Driglu4it, which lets +it be recolored like normal bar text instead of a fixed-color image. diff --git a/cat/cat.luau b/cat/cat.luau new file mode 100644 index 0000000..72e904e --- /dev/null +++ b/cat/cat.luau @@ -0,0 +1,159 @@ +--!nonstrict +-- Cat: an animated running cat bar widget. Pace reflects CPU usage, sampled +-- from /proc/stat, with separately configurable walk/run thresholds. Color +-- follows the theme's secondary role by default, or a pinned custom color. +-- +-- The cat shape is a custom pictographic font (fonts/catwalk2.otf, traced +-- from the MIT-licensed CatWalk plasmoid by Driglu4it) so it can be colored +-- like any other bar text: "a" = idle/asleep, "b".."f" = the 5-frame run +-- cycle. Each glyph's advance width is trimmed to the shared ink extent +-- (non-negative left bearing, no dead trailing space) so bar layout doesn't +-- overlap the previous widget or leave a large gap before the next one. +-- +-- Font registration is process-global and keyed by file path/family, so this +-- filename must change (not just its contents) whenever the glyph set changes +-- during development, or the shell keeps rendering whatever it cached the +-- first time it saw this path. + +local catFont = noctalia.loadFont("fonts/catwalk2.otf") + +local GLYPH_IDLE = "a" +local RUN_GLYPHS = { "b", "c", "d", "e", "f" } + +local TICK_MS = 80 +local WALK_MAX_MS = 380 +local WALK_MIN_MS = 180 +local RUN_MAX_MS = 160 +local RUN_MIN_MS = 55 + +local catSize = noctalia.getConfig("cat_size") +local showCpuPercent = noctalia.getConfig("show_cpu_percent") +local walkThreshold = noctalia.getConfig("walk_threshold") +local runThreshold = noctalia.getConfig("run_threshold") +local pollIntervalMs = noctalia.getConfig("poll_interval") * 1000 +local colorMode = noctalia.getConfig("cat_color_mode") +local customColor = noctalia.getConfig("cat_color") + +local frameIndex = 1 +local frameElapsed = 0 +local frameDurationMs = WALK_MAX_MS + +local sampleElapsed = pollIntervalMs -- sample immediately on first tick +local cpuPercent = 0 +local prevTotal, prevIdle = nil, nil + +local function sampleCpu() + local stat = noctalia.readFile("/proc/stat") + if not stat then + return + end + + local line = stat:match("^cpu%s+(.-)\n") or stat:match("^cpu%s+(.-)$") + if not line then + return + end + + local fields = {} + for n in line:gmatch("%d+") do + table.insert(fields, tonumber(n)) + end + + local idle = (fields[4] or 0) + (fields[5] or 0) + local total = 0 + for _, v in fields do + total += v + end + + if prevTotal then + local totalDelta = total - prevTotal + local idleDelta = idle - prevIdle + if totalDelta > 0 then + cpuPercent = math.clamp((totalDelta - idleDelta) / totalDelta * 100, 0, 100) + end + end + + prevTotal = total + prevIdle = idle +end + +-- Returns ("idle" | "walk" | "run", frame-duration-ms-for-that-pace). +local function paceFor(cpu) + local runFloor = math.max(runThreshold, walkThreshold + 1) + + if cpu < walkThreshold then + return "idle", WALK_MAX_MS + elseif cpu < runFloor then + local range = math.max(runFloor - walkThreshold, 1) + local t = math.clamp((cpu - walkThreshold) / range, 0, 1) + return "walk", WALK_MAX_MS - t * (WALK_MAX_MS - WALK_MIN_MS) + else + local range = math.max(100 - runFloor, 1) + local t = math.clamp((cpu - runFloor) / range, 0, 1) + return "run", RUN_MAX_MS - t * (RUN_MAX_MS - RUN_MIN_MS) + end +end + +local function resolveColor() + if colorMode == "custom" and customColor and customColor ~= "" then + return customColor + end + return "secondary" +end + +local function render(pace) + local glyph = pace == "idle" and GLYPH_IDLE or RUN_GLYPHS[frameIndex] + local color = resolveColor() + + local children = { + ui.label({ text = glyph, fontFamily = catFont, baseline = "inkCentered", fontSize = catSize, color = color }), + } + + if showCpuPercent then + table.insert(children, ui.label({ text = `{math.floor(cpuPercent)}%`, fontSize = 11, color = color })) + end + + local container = barWidget.isVertical() and ui.column or ui.row + barWidget.render(container({ gap = 4, align = "center" }, children)) + barWidget.setTooltip(`Cat — CPU {math.floor(cpuPercent)}% ({pace})`) +end + +noctalia.setUpdateInterval(TICK_MS) + +function update() + sampleElapsed += TICK_MS + if sampleElapsed >= pollIntervalMs then + sampleElapsed = 0 + sampleCpu() + end + + local pace, duration = paceFor(cpuPercent) + frameDurationMs = duration + + if pace == "idle" then + frameElapsed = 0 + frameIndex = 1 + else + frameElapsed += TICK_MS + if frameElapsed >= frameDurationMs then + frameElapsed = 0 + frameIndex = frameIndex % #RUN_GLYPHS + 1 + end + end + + render(pace) +end + +function onClick() + noctalia.notify(noctalia.tr("title"), `CPU {math.floor(cpuPercent)}%`) +end + +function onConfigChanged() + catSize = noctalia.getConfig("cat_size") + showCpuPercent = noctalia.getConfig("show_cpu_percent") + walkThreshold = noctalia.getConfig("walk_threshold") + runThreshold = noctalia.getConfig("run_threshold") + pollIntervalMs = noctalia.getConfig("poll_interval") * 1000 + colorMode = noctalia.getConfig("cat_color_mode") + customColor = noctalia.getConfig("cat_color") + render((paceFor(cpuPercent))) +end diff --git a/cat/fonts/catwalk2.otf b/cat/fonts/catwalk2.otf new file mode 100644 index 0000000000000000000000000000000000000000..006a4ab74cad1f33f5fa50e533f8bfa388f46a35 GIT binary patch literal 2268 zcmeYd3Grv(WN2VuW)N_8b5meWGjL{LU~*t!U~BOY);Drxa9YQ}z{tSBz>tufn^?fG zlfj08f$<3g1A|RQYGR7MPLl-#1H&8!1_rZ?jMPMyBTQBd3=CHo7#LJCa!V>W&VjUY z9ARK!5X()hC}7|S015nHU|?X&OUzCEp!Tw#fq^lBfq|j1AiubTff*#tq`<(ypa8a( zk%8gY?m~ljew(ih%*-!9vd@|o*1&1u|6)vk7+x_jFfcPPfkYX=&Sm`akB5N)tlo*~ z9M~kNB$#4mUkFG7}Y?6HCey zbFvkTf>P5l{M|BaEkaKPLAr!t zx)2@(#U3LAgA*$Q2NMG$0~Z4?!+pjFOy5~JScTcde$~7en>w|To$p5$-_IpKe7|Rk zF1S_79u>^Gx6EQb+n%GWv25>tGl|YRUc;W2%DS=EdnVh)jjS1L-vfV}h;}d9ysS-r zUPoYXw{(3UYxk@p{WbD6{fU_+Io;h!jnxrV;ZENfi{=!~$ysk%$YEJjl#nKsJE5+* zPOe*T>b1%8ldd1GpVBj>XYQ1ah3$(nrWQ1E6f^`DSV&pyO?_A>SM=aJclSo=4c}AR zX3v!GzO&@yo|fs=bL8zei*`5kw^zz{FI+Tfa&t+y^vOKY2^~%S-O}B2X14dpxA(Nv zbW8L7T=G-wyN>9x{!Qh5a(xxKA>Go=U98=c_O%tsw-)ExcT0CSG!-<G z7?<4L9p9VQn%|J$kdYqO7u#Rf+*{pOJ-cH`C&$u`lXEsNUNUp}q~%?0(eoyD#B|2a zi(6H+s%YAbo>{%KvNv_k>Y6>TuCJY=w_{cAl9r{d^&6TNHZ7XHVC95W{WGgu%UjDk z^Op23?cH*se|_JE3G)|C;#fR+>!R)3Vi$Ky8FY%)cjPs8OLzBeo3dKIv8%DOQEru; zXk*jV8Plgsn>uYuLw#LSV}tzGhoa5>ZN1Gs-Q5!w&6&_w-&Nnyz_G|$w4r(GjOml7 zPMbElvA(Xku|Xab07|W*eUn))OkTL7eMQHroMrX>9NkkcRFvj~cS|?3b$9QomF~*R zw(OQ}Y3ZscE8{3Di|k95?nzG0>Xxq0nAn#qpWExxUfo&Msai6zbYkh&nR_Sin|z~Z zUhCY}vdqlJtfsuonre=k>bl(3U8_4+t(`S-)`W)Awz}5Zmc&J!3%l0tn>c0C)D<%( zPUM(4Y0lhk>F!g#6IaWxp15l9?B3bEi>fEKPi)&!xUiL@ZDH?HgkNg5uG-rp{};6p`o#9+RPbKrcISEJ0)7z z(^}Il-P_jM(<(h>?!<|cdN|^Lvx_!1O`9>0czeadP~6kijP=)X7gN zO%3aoZt7*7db+Hxu%xi0IJ&Buqq?SiLh9VqxpA#kO&pEYH50p~yQ9}mtdXyolr%T8 zC$cxGth>9ca#78q2@5CepR}QQebb?&uKKR}(z3!fj-pn#h>n8J!d0CsX04pHsJ^>9 zzo0W~QQM-n`HNRBU9oJ%^qp-x+pbRR?&g?RaVB|j!=n0SllrFjP0v`~H@R=py1JS3 zr_c3X+1T6IH*rdL_u9VIlc#LtNZ%)*g=T z*^7Fn$?GSJwzXDwbxU_oTQzN&d{=cxV|^pXMpw~#NSIBZKDD8)wy~ieoKCXOiFPkN z)?Y0@B_}(zTe`WIwR_TvnO*XoGcsz*tIDfVLyH?r8Vc5DEKOe$Uf$i^+*`M}a7odU zg82bcI0C2USM=5Q)lKX^+j^sALCU<+xuwM=Ww~X!lgj!F`->K}^riKuO{rfznPbu9 z#vA=oUAIRx z+*DuR+}H>X3f1qNqTTb4PpXukSdo&@E#275I&n{1e_mN$S#e5ROKWRuN$9fBWtr7E zEgU(`9%*T{X|-t+n|qskQkU1()K<@`o?SPqeq-C}o;5wM*L8PKY;N!EE#~MgT2VT= zX;M>LV^1+hN$`(pXmyDmB*J744omw|BC9Ph)3Ob8~xNdv9AW#~OXn#^x#0r%j$Z bb?W5ChWh5FMtMF^Ezfw3fq_{7wUPn=vxIeB literal 0 HcmV?d00001 diff --git a/cat/plugin.toml b/cat/plugin.toml new file mode 100644 index 0000000..59dd8cc --- /dev/null +++ b/cat/plugin.toml @@ -0,0 +1,76 @@ +id = "dotnetrob/cat" +name = "Cat" +version = "1.1.2" +plugin_api = 3 +author = "DotNetRob" +license = "MIT" +dependencies = [] +icon = "paw" +description = "An animated running cat bar widget whose speed reflects CPU usage." +tags = ["bar", "animation", "system", "fun"] + +[[widget]] +id = "cat" +entry = "cat.luau" + + [[widget.setting]] + key = "cat_size" + type = "int" + label_key = "settings.cat_size.label" + description_key = "settings.cat_size.description" + default = 24 + min = 12 + max = 48 + + [[widget.setting]] + key = "show_cpu_percent" + type = "bool" + label_key = "settings.show_cpu_percent.label" + description_key = "settings.show_cpu_percent.description" + default = false + + [[widget.setting]] + key = "walk_threshold" + type = "int" + label_key = "settings.walk_threshold.label" + description_key = "settings.walk_threshold.description" + default = 15 + min = 0 + max = 100 + + [[widget.setting]] + key = "run_threshold" + type = "int" + label_key = "settings.run_threshold.label" + description_key = "settings.run_threshold.description" + default = 60 + min = 0 + max = 100 + + [[widget.setting]] + key = "poll_interval" + type = "int" + label_key = "settings.poll_interval.label" + description_key = "settings.poll_interval.description" + default = 2 + min = 1 + max = 10 + + [[widget.setting]] + key = "cat_color_mode" + type = "select" + label_key = "settings.cat_color_mode.label" + description_key = "settings.cat_color_mode.description" + default = "theme" + options = [ + { value = "theme", label_key = "settings.cat_color_mode.option_theme" }, + { value = "custom", label_key = "settings.cat_color_mode.option_custom" }, + ] + + [[widget.setting]] + key = "cat_color" + type = "color" + label_key = "settings.cat_color.label" + description_key = "settings.cat_color.description" + default = "#E8A24C" + visible_when = { key = "cat_color_mode", values = ["custom"] } diff --git a/cat/thumbnail.webp b/cat/thumbnail.webp new file mode 100644 index 0000000000000000000000000000000000000000..fcf8a0a441775f57e4ec8440548edb9881b68ee4 GIT binary patch literal 23794 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 L`cyq&U|;|Mmw<-L literal 0 HcmV?d00001 diff --git a/cat/translations/en.json b/cat/translations/en.json new file mode 100644 index 0000000..a208e6f --- /dev/null +++ b/cat/translations/en.json @@ -0,0 +1,35 @@ +{ + "title": "Cat", + "settings": { + "cat_size": { + "label": "Cat Size", + "description": "Sprite size in the bar, in pixels." + }, + "show_cpu_percent": { + "label": "Show CPU Percentage", + "description": "Display the CPU percentage next to the cat." + }, + "walk_threshold": { + "label": "Walk Threshold", + "description": "CPU percentage at which the cat wakes up and starts walking." + }, + "run_threshold": { + "label": "Run Threshold", + "description": "CPU percentage at which the cat breaks into a run." + }, + "poll_interval": { + "label": "CPU Poll Interval", + "description": "How often to sample CPU usage, in seconds." + }, + "cat_color_mode": { + "label": "Cat Color", + "description": "Use the current theme color, or pick a custom color below.", + "option_theme": "Match Theme", + "option_custom": "Custom" + }, + "cat_color": { + "label": "Custom Color", + "description": "Used when Cat Color is set to Custom." + } + } +}