aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_data.lua
AgeCommit message (Collapse)AuthorFilesLines
3 daysfix(card): draw emoji in Noto Emoji instead of tofuHEADmasterDanilo M.1-0/+16
Cairo's toy text API binds one face with no per-glyph fallback, so an emoji in a calendar event title rendered as a box in Noto Sans. text/measure/advance now split strings into runs and draw emoji runs (U+1F000-1FAFF, U+2600-27BF) in monochrome Noto Emoji, restoring the caller's face afterwards. Nerd Font PUA icons stay in FONT_MONO. Plain strings and invalid UTF-8 take the old single-call path. No shaping: ZWJ sequences and flags draw as their parts. Pango via lgi (built for Lua 5.4) is the upgrade path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 daysfeat(gpu): show VRAM in use as a bar with a percentageDanilo M.1-0/+20
Sum drm-resident-vram0 from DRM fdinfo, the same per-client counters gputop reads, counting each drm-client-id once since a client repeats its totals on every fd it holds. One grep over /proc/*/fdinfo, about 10ms warm, sampled through new_gate every ~2s. The 12 GiB total is hardcoded: xe exposes no VRAM capacity in sysfs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
9 daysperf(dashboard): draw at 0.1s only while the dashboard is visibleDanilo M.1-0/+7
Conky gives Lua no way to request one redraw, so a scroll showed up to 2s late. Pointer enter and leave, which Hyprland sends on every toggle of the special workspace, now switch conky_set_update_interval between 0.1s and the config's 2s. At that rate the CPU and network counters would sample over 0.1s windows and the chart would fill 20x faster, so both now sample through data.new_gate on the /proc/uptime clock, about every 2s, and redraw their last values in between. The samplers move to texeci: execi runs in the main loop and a 0.7s nvtable or an Immich download stalled the scroll. Measured: about 12% of one core while visible, 0.5% while hidden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
9 daysfeat: add an updates card showing nvtable's package tableDanilo M.1-0/+17
Moves the nvchecker/nvtable table the login shell printed onto the dashboard, as a wide card at the bottom centre. bin/updates-sample.sh caches `nvtable -C -E` every ten minutes and starts nvchecker, fully detached, at most every 30 minutes. The widget parses the cache and colours it in the board's language: installed behind upstream is critical, a shipped .info behind is a warning, with nvtable's status dots per row and a legend on the bottom line. The mouse wheel scrolls rows that do not fit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 daysfeat(immich): fall back to the past week's memoriesDanilo M.1-0/+2
A day with no memories left the card showing only a notice. When today has none, immich-fetch.sh now merges the memories of each of the past six days, skipping a day whose request fails, and marks the index with a scope week line. The subtitle names where the photos come from, Today or This week, before the i/n counter, and the empty notice reads no memories this week. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 daysfeat: add an Immich memories card with click and scrollDanilo M.1-0/+13
A centred card showing today's "N years ago" photos from Immich, one at a time on a 30-second rotation, with when each was taken and where. bin/immich-fetch.sh runs from conky's execi every 30 minutes: it asks /api/memories for today, converts each preview to PNG (Cairo loads nothing else) and writes an index with the year, local capture time and place. The place needs the key's asset.read permission and reads '--' without it. The key lives in ~/.config/udt/immich.env, like the weather key, because a GPG-backed store would raise a pinentry unattended. The dashboard now registers lua_mouse_hook and hands pointer events to the widget under the pointer. On this card, scrolling steps through the photos and a left click opens the photo in Immich's web UI and hides the dashboard so the browser is not stuck beneath it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-18feat: add a breaktimer cardDanilo M.1-0/+62
Replaces the Waybar module that used to show breaktimer.sh with a card on the dashboard. The card's big value is the phase countdown, coloured by phase with the same language the Waybar module used, and two rows name the phase and what the countdown leads to. Data comes from bin/breaktimer-sample.sh, run by conky at execi 5, which reads the daemon's runtime files into a cache. The sampler owns the kill -0 liveness check, because conky's Lua cannot run a process and a dead daemon must read as 'fermo' rather than a stale 'running'. Drops outside the work-hours window freeze the countdown while the phase stays 'working'. The sampler detects this from the remain file's age and the card reads it as 'outside working hours', which also covers a hung daemon. The phase words and colour roles live in data.breaktimer_parse so they are unit-tested; the card only draws the result.
2026-09-18feat: add a calendar card reading khalDanilo M.1-0/+61
The month grid with the week's appointments below it, colour-coded by calendar. Events come from a cache file rather than a live call: khal costs about 200ms of Python startup, which is two orders of magnitude over the 2-second draw budget, so bin/calendar-sample.sh writes the cache on a 5-minute execi and the widget only parses. Calendar colours are read out of khal's own config by the sampler and mapped onto the board's palette roles, so the card follows a scheme change instead of pinning three literal hues. khal will not emit an ISO date: {start-date} uses the user's dateformat, which carries no year here, and a strftime spec inside the field raises. The sampler asks for {start-date-long} and data.calendar_date recovers the numbers by position, resolving day/month by magnitude and reading a genuinely ambiguous pair day-first. A 2-digit year is refused rather than guessed at. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: add the network cardDanilo M.1-0/+13
Two lines on one chart against a shared ceiling, one sample per pixel column so nothing is interpolated. The history is module state sized from the card's width, so moving the card reframes the window rather than clearing it. The public address is refused once stale: an address that may no longer be yours, displayed with confidence, is worse than a dash. The fixture uses TEST-NET-1. This repository is public. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: read the available column from dfDanilo M.1-0/+21
Free space is read rather than derived: size - used overstates it by the root-reserved blocks, tens of gigabytes on a large filesystem, none of it available to anyone but root. Also asserts fs[3], the row whose device name ends in a digit. It sits next to a numeric column and is the row most likely to break a parser counting fields, and nothing covered it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17fix: strip the clock from every Intel form, not just the fixture'sDanilo M.1-0/+14
The pattern required a literal CPU token immediately before the @, which the one Intel fixture happens to carry. A Xeon reads 'E5-2680 v4 @ 2.40GHz' and a Tiger Lake 'i7-1165G7 @ 2.80GHz', so both kept their clock on the card. A generation prefix hid the vendor word from its anchor for the same reason: '11th Gen Intel Core i7-1165G7' kept 'Intel'. Three more forms added as tests. The Intel fixture was meant to keep the stripping a rule, and one fixture was not enough to do it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: parse the CPU and motherboard model stringsDanilo M.1-0/+35
Stripping by rule rather than by a table of known parts: a leading vendor word, trademark noise, a trailing core count or clock. The Intel fixture exists to keep it a rule. DMI placeholders read as no board at all. 'To Be Filled By O.E.M.' on the dashboard is worse than a blank row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: parse the sampler's key/value cache formatDanilo M.1-0/+21
Only the first space separates, so a value keeps its own spaces. Values stay strings: the sampler writes epochs and the widget decides whether an age reads as hours or days. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17test: cover the rate counter's explicit fallback intervalDanilo M.1-0/+9
The widget passes conky's update_interval rather than letting it default, so the argument path is the one that ships and nothing exercised it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17feat: add a byte-rate counter for interface statisticsDanilo M.1-0/+31
Mirrors new_cpu_counter: cumulative counters need two samples to yield a rate, and each direction carries its own previous reading. Clamps a negative delta to zero rather than letting a 32-bit wrap or an interface reset produce a spike. One bogus sample sets the shared autoscale and flattens the entire window. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17fix: restore the line width card.ring sets, add card.truncateDanilo M.1-0/+28
A ring left its line width behind, so the next stroke on the card inherited a hairline several pixels thick. It already restored the cap for the same reason. card.truncate replaces byte slicing, which cuts a multi-byte character in half and emits an invalid sequence Cairo draws as a box. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17docs: correct the system-widget comments and defer the age markerDanilo M.1-1/+1
Fix the conky.conf.in comment to name all three samplers and the README to say the cache sampler runs every 15 minutes. Rewrite the disks layout comment to match per_row = n (no wrapping), drop the stale "seventeenth bar" note, and record in the spec that the cache age marker is deliberately deferred with the epoch-line upgrade path.
2026-09-17feat: parse df and du output for the disk and cache cardsDanilo M.1-0/+59
2026-09-17feat: add per-core CPU times and named sensor readsDanilo M.1-0/+37
2026-09-16docs: fix a comment naming a function that does not existDanilo M.1-1/+1
The test comment said "cpu_percent", but the API is new_cpu_counter() plus :sample(). Prose only, the code was always consistent, but a comment naming a nonexistent function sends the next reader looking for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16feat: add stateful CPU percentage counterDanilo M.1-0/+18
Load is a delta, so one reading cannot yield a percentage. The first call returns nil rather than a fabricated number: 100% on startup reads as a real spike. A non-advancing counter also returns nil instead of dividing by zero, and the result is clamped because a suspend/resume can produce a nonsense delta. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16feat: add /proc and /sys parsers with fixture testsDanilo M.1-0/+39
Parsers take file contents as a string, not a path, so they test against committed fixtures with no filesystem mocking. hwmon is globbed by its name file rather than a fixed index, carried over from the old config: indices drift across kernel reorders and a stale one silently reads a different chip. Failure returns nil, never 0. A sensor reading 0 C is legitimate, so 0 cannot double as an error value. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>