You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Update to an existing plugin (version bumped in plugin.toml)
What it does
A clean, minimalist layout switcher plugin for MangoWC. It provides a bar widget to see the current workspace layout, and a fast popup panel to switch workspace layouts on the fly directly from the desktop. Includes dynamic settings to customize the widget appearance (icon, text, colors) and a vertical list mode.
External dependencies
jq: Used to parse the JSON output from the MangoWC IPC.
mmsg: The MangoWC CLI utility used to read the active monitor state and set the new layout.
Testing
Toggled layouts using the panel grid and vertical list modes. Tested all dynamic plugin settings (glyph, text, color, layout visibility toggles). Verified mmsg IPC commands work seamlessly and panel updates instantly.
Tested on Niri
Tested on Hyprland
Tested on Sway
Tested on another compositor: MangoWC
Noctalia version tested against: v5
Plugin API level: 14
Screenshots / Videos
recording.mp4
Checklist
The directory name matches the part of id after the / in plugin.toml exactly.
It ships plugin.toml, README.md, thumbnail.webp, and translations/en.json.
README.md follows the README template, documents
every entry id and dependency, and includes exact panel IPC commands and launcher prefixes where applicable.
version follows semver and is bumped in this PR; plugin_api is the oldest API level this plugin requires.
Every non-English translation in this PR uses a locale supported by Noctalia core, and I can read, write, and
understand that language well enough to review and maintain it (no unreviewed machine/LLM translations).
I did not edit catalog.toml; CI generates it.
This PR touches exactly one plugin directory.
Code review attestation
Plugins run as trusted, unsandboxed Luau in the user's session. Confirm:
The code is readable and not obfuscated, minified, or generated.
It does not download and execute remote code.
Every network call, filesystem write, and spawned process is something the description above accounts for.
I have the right to publish this code under the license declared in plugin.toml.
Picking a layout does more than dispatch to the compositor. The spawned bash script
rewrites the user's MangoWC configuration file at
$HOME/.config/mango/conf.d/workspaces.conf: it copies the file to a mktemp temp file
in the same directory, runs sed -i over it, and then mv replaces the original.
Nothing declares this. The PR description lists only "reads the active monitor state
and set the new layout", README.md:56 says only that mmsg is used "for reading the
active monitor state and applying the selected layout", and the "Code review
attestation" checkbox asserting that every filesystem write is accounted for is
checked. A user installing a "layout switcher" has no way to know that a single click
permanently edits their compositor config.
The write is also destructive rather than additive. mv "$TMP_FILE" "$CONF_FILE"
replaces the original with no backup, so a sed pattern that matches something the
author did not anticipate silently rewrites the user's config with no way back. The
temp file comes from mktemp (mode 0600), so the moved-in file also silently loses the
original config file's permissions.
The default is the widest possible one. panel.luau:1 sets global_toggle = true, so
the "Apply to all" branch is what runs on the first click, and sed "s/layout_name:[a-zA-Z_]*/layout_name:$LAYOUT/g" rewrites every layout_name:
occurrence in the whole file, including tagrules for workspaces the user was not
switching. That toggle is not documented anywhere: it appears only as a hardcoded
"Apply to all" label at panel.luau:169 and is absent from the README settings tables.
To resolve: document the config-file rewrite in README.md and the PR description,
default the persistence toggle to off, and prefer a non-destructive update path
(preserve the original mode and keep a backup, or write only the targeted tagrule).
non-blocking - mango_layouts/plugin.toml:10
dependencies = ["jq", "mmsg"] omits the shell utilities the panel actually invokes: bash (panel.luau:32), plus mktemp, cp, sed, and mv (panel.luau:39-49).
Repo convention is to list these; see drive-health/plugin.toml:8 and
jetbrains-provider/plugin.toml:10, which declare bash, sed, mktemp, and mv explicitly.
README.md:14 likewise mentions only jq and mmsg.
non-blocking - mango_layouts/widget.luau:49-53
The custom_color setting is advertised as "Icon/Text Color"
(mango_layouts/translations/en.json:4, mango_layouts/README.md:52), but the widget only
calls barWidget.setColor, which sets text color, and barWidget.setForeground, which
is not part of the widget API at all (the binding table is setText, setGlyph, setImage,
setTooltip, clearTooltip, setFont, setColor, setGlyphColor, isVertical, outputName,
setVisible, render). Both calls are wrapped in pcall, so the failure is invisible.
With the shipped defaults (show_glyph = true at plugin.toml:22, show_text = false at
plugin.toml:28) the widget renders only a glyph, so setting custom_color produces no
visible effect whatsoever. barWidget.setGlyphColor is the missing call.
non-blocking - mango_layouts/widget.luau:40
barWidget.setGlyph(nil) cannot clear the glyph: the binding does a checked string
read of argument 1, so nil raises, and the surrounding pcall swallows it. Same at
widget.luau:58. Passing an empty string is the working form.
non-blocking - mango_layouts/widget.luau:27
A 500 ms update interval spawns /bin/sh -c "mmsg get all-monitors | jq ..." twice per
second for the lifetime of the session, which is three processes per tick. Every other
plugin in the repo that polls an external command uses 1000 ms or slower, including the
comparable mangowm-keymode/keymode.luau:20, which polls mmsg at 1000 ms.
non-blocking - mango_layouts/README.md:51
Documents show_text default as true; plugin.toml:28 sets default = false.
non-blocking - mango_layouts/panel.luau:169
The "Apply to all" label is a hardcoded English string even though the plugin ships
translations/en.json and routes every settings label through label_key. The layout
names at panel.luau:4-17 are hardcoded English as well.
I really don't see why you need to write to the config for a simple "Switcher" seems very overkill / dangerous.
Thank you so much for the review. You were right about the config file rewrite it was definitely overkill and not the right approach for such a simple switcher.
I've just pushed a new commit addressing all of your feedback:
Removed the config file rewrite (Blocking): The Bash script has been removed entirely. The panel now simply sends an mmsg dispatch setlayout,$LAYOUT command through noctalia.runAsync to switch the layout dynamically. Since the plugin no longer edits or persists changes to the user's configuration files, I also removed the undocumented "Apply to all" global toggle and simplified the overall logic.
Dependencies: With the Bash script gone, the plugin no longer relies on mktemp, cp, sed, or mv. The declared dependencies (jq and mmsg) are now accurate.
Widget Color API: Replaced the non-existent barWidget.setForeground call with barWidget.setGlyphColor, and removed the unnecessary pcall wrappers so the color is applied correctly.
Missing Glyph: Changed barWidget.setGlyph(nil) to barWidget.setGlyph("") so the glyph is cleared correctly without silently triggering errors.
Update Interval: Increased the polling interval in widget.luau from 500 ms to 1000 ms to match the repository's performance guidelines.
Hardcoded UI Strings: Moved all layout names (Tile, Monocle, etc.) into en.json and now apply them through noctalia.translate() inside panel.luau.
README: Corrected the show_text documentation to indicate that the default value is false.
If everything looks good now, let me know if there's anything else needed for approval!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plugin
ezequiel/mango_layoutsplugin.toml)What it does
A clean, minimalist layout switcher plugin for MangoWC. It provides a bar widget to see the current workspace layout, and a fast popup panel to switch workspace layouts on the fly directly from the desktop. Includes dynamic settings to customize the widget appearance (icon, text, colors) and a vertical list mode.
External dependencies
jq: Used to parse the JSON output from the MangoWC IPC.mmsg: The MangoWC CLI utility used to read the active monitor state and set the new layout.Testing
Toggled layouts using the panel grid and vertical list modes. Tested all dynamic plugin settings (glyph, text, color, layout visibility toggles). Verified mmsg IPC commands work seamlessly and panel updates instantly.
Screenshots / Videos
recording.mp4
Checklist
idafter the/inplugin.tomlexactly.plugin.toml,README.md,thumbnail.webp, andtranslations/en.json.README.mdfollows theREADME template, documents
every entry id and dependency, and includes exact panel IPC commands and launcher prefixes where applicable.
thumbnail.webpwith the thumbnail generator.versionfollows semver and is bumped in this PR;plugin_apiis the oldest API level this plugin requires.understand that language well enough to review and maintain it (no unreviewed machine/LLM translations).
catalog.toml; CI generates it.Code review attestation
Plugins run as trusted, unsandboxed Luau in the user's session. Confirm:
licensedeclared inplugin.toml.