From 954b7f381e3337838e175ca7c86b47ad2addfccd Mon Sep 17 00:00:00 2001 From: Breadway Date: Tue, 16 Jun 2026 17:06:44 +0800 Subject: [PATCH] Add ready-to-use example modules examples/modules/ ships complete, drop-in bread modules for common desktop automations (low-battery warning, pause-media-on-headphone-unplug, dock-monitors) plus a README on installing them. Complements Examples.md, which teaches the porting patterns. --- examples/modules/README.md | 28 ++++++++++++++++++ examples/modules/dock-monitors.lua | 26 +++++++++++++++++ examples/modules/low-battery-warning.lua | 29 +++++++++++++++++++ .../pause-media-on-headphone-unplug.lua | 25 ++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 examples/modules/README.md create mode 100644 examples/modules/dock-monitors.lua create mode 100644 examples/modules/low-battery-warning.lua create mode 100644 examples/modules/pause-media-on-headphone-unplug.lua diff --git a/examples/modules/README.md b/examples/modules/README.md new file mode 100644 index 0000000..e9636ec --- /dev/null +++ b/examples/modules/README.md @@ -0,0 +1,28 @@ +# Example bread modules + +Ready-to-use modules for common desktop automations. Unlike the snippets in +[`../../Examples.md`](../../Examples.md) (which teach the porting patterns), +these are complete files you can drop in as-is. + +## Installing + +Modules in `~/.config/bread/modules/` are **auto-discovered** — copy a file in +and reload; no `init.lua` edit needed: + +```sh +cp low-battery-warning.lua ~/.config/bread/modules/ +bread reload +``` + +## Modules + +| File | What it does | Config needed | +|------|--------------|---------------| +| `low-battery-warning.lua` | Critical notification once when the battery runs low; resets on AC. | none | +| `pause-media-on-headphone-unplug.lua` | Runs `playerctl pause` when a headphone/earbud device disconnects. | none (needs `playerctl`) | +| `dock-monitors.lua` | Applies a multi-monitor layout when an external display connects, reverts when removed. | edit output names/resolutions | + +Each module is the standard skeleton — `bread.module{...}`, an `on_load` that +registers subscriptions, `return M` — so they double as references for writing +your own. See [`../../Documentation.md`](../../Documentation.md) for the full +event list and Lua API. diff --git a/examples/modules/dock-monitors.lua b/examples/modules/dock-monitors.lua new file mode 100644 index 0000000..1fd92a6 --- /dev/null +++ b/examples/modules/dock-monitors.lua @@ -0,0 +1,26 @@ +-- dock-monitors — apply a monitor layout when an external display is plugged +-- in (a "dock") and revert to the laptop panel when it's removed. +-- +-- Drop-in: copy into ~/.config/bread/modules/ and edit the output names / +-- resolutions for your machine (see `hyprctl monitors`). + +local monitors = require("bread.monitors") +local M = bread.module({ name = "dock-monitors", version = "1.0.0" }) + +-- Named layouts ---------------------------------------------------------------- +monitors.layout("docked", function() + bread.hyprland.keyword("monitor", "eDP-1, 1920x1200@60, 0x0, 1") + bread.hyprland.keyword("monitor", "HDMI-A-1, preferred, 1920x0, 1") +end) + +monitors.layout("solo", function() + bread.hyprland.keyword("monitor", "eDP-1, preferred, 0x0, 1") +end) + +-- React to the external display ------------------------------------------------ +function M.on_load() + monitors.on({ when = "connected", monitors = { "HDMI-A-1" }, run = monitors.apply("docked") }) + monitors.on({ when = "disconnected", monitors = { "HDMI-A-1" }, run = monitors.apply("solo") }) +end + +return M diff --git a/examples/modules/low-battery-warning.lua b/examples/modules/low-battery-warning.lua new file mode 100644 index 0000000..eb68839 --- /dev/null +++ b/examples/modules/low-battery-warning.lua @@ -0,0 +1,29 @@ +-- low-battery-warning — notify once when the battery runs low. +-- +-- Drop-in: copy into ~/.config/bread/modules/ (auto-discovered; no init.lua +-- edit needed). Zero configuration. + +local M = bread.module({ name = "low-battery-warning", version = "1.0.0" }) + +-- Latch so we warn once per low-battery episode, not on every poll. +local warned = false + +function M.on_load() + bread.on("bread.power.battery.low", function(event) + if warned then return end + warned = true + local pct = event.data.battery_percent or "?" + bread.notify("Battery low (" .. pct .. "%). Plug in soon.", { + urgency = "critical", + title = "Battery", + timeout = 10000, + }) + end) + + -- Reset once back on AC so the next low episode warns again. + bread.on("bread.power.ac.connected", function() + warned = false + end) +end + +return M diff --git a/examples/modules/pause-media-on-headphone-unplug.lua b/examples/modules/pause-media-on-headphone-unplug.lua new file mode 100644 index 0000000..6b6d6e7 --- /dev/null +++ b/examples/modules/pause-media-on-headphone-unplug.lua @@ -0,0 +1,25 @@ +-- pause-media-on-headphone-unplug — pause playback when headphones disconnect, +-- so sound doesn't suddenly blast out of the speakers. +-- +-- Drop-in: copy into ~/.config/bread/modules/. Requires `playerctl`. + +local M = bread.module({ name = "pause-media-on-headphone-unplug", version = "1.0.0" }) + +local function looks_like_headphones(name) + if not name then return false end + name = name:lower() + return name:find("head") ~= nil + or name:find("earbud") ~= nil + or name:find("airpod") ~= nil + or name:find("buds") ~= nil +end + +function M.on_load() + bread.on("bread.device.disconnected", function(event) + if looks_like_headphones(event.data.name) then + bread.exec("playerctl pause") + end + end) +end + +return M