From 395c08d0a334cdffbcc370384bee67f19f964399 Mon Sep 17 00:00:00 2001 From: seraphim <18ycm9tx@anonaddy.me> Date: Fri, 24 Jul 2026 20:57:33 +0700 Subject: frst --- .../.config/plugins/keybind-cheatsheet/README.md | 272 +++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 noctalia/.config/plugins/keybind-cheatsheet/README.md (limited to 'noctalia/.config/plugins/keybind-cheatsheet/README.md') diff --git a/noctalia/.config/plugins/keybind-cheatsheet/README.md b/noctalia/.config/plugins/keybind-cheatsheet/README.md new file mode 100644 index 0000000..5c30b87 --- /dev/null +++ b/noctalia/.config/plugins/keybind-cheatsheet/README.md @@ -0,0 +1,272 @@ +# Keybind Cheatsheet for Noctalia + +Universal keyboard shortcuts cheatsheet plugin for Noctalia that **automatically detects** your compositor (Hyprland, Niri or MangoWC) and displays your keybindings with **recursive config parsing**. Supports the classic Hyprland `.conf` format, the new **Hyprland 0.55+ Lua config**, Niri KDL and MangoWC. + +![Preview](preview.png) + +## Features + +- **Automatic compositor detection** (Hyprland, Niri, MangoWC) +- **Hyprland Lua config support** (Hyprland 0.55+) via `hyprctl binds -j` +- **Recursive config parsing** - follows `source` (Hyprland `.conf`), `require()` (Hyprland Lua) and `include` (Niri) directives +- **Glob pattern support** - parses `~/.config/hypr/*.conf` style includes +- **Without Description section** - binds with no description are surfaced, not dropped; add a custom description or hide them inline +- **Full per-category color customization** - background + text color for every key category, with live preview and clipboard quick-paste +- **Search filter** - type to filter keybindings in the panel +- **Configurable paths & parser mode** - custom config locations and forced Lua/conf parser in settings +- **Smart key formatting** - XF86 keys display as readable names (Vol Up, Bright Down, etc.) +- **Flexible column layout** (1-4 columns) with auto-height +- **IPC support** - `toggle` and `refresh` for global hotkeys + +## Supported Compositors + +| Compositor | Default Config | How it's read | +|------------|----------------|----------------| +| **Hyprland 0.55+** | `~/.config/hypr/hyprland.lua` | `hyprctl binds -j` (live, already-evaluated binds) | +| **Hyprland (classic)** | `~/.config/hypr/hyprland.conf` | hyprlang `.conf` text parser (recursive) | +| **Niri** | `~/.config/niri/config.kdl` | KDL parser (recursive `include`) | +| **MangoWC** | `~/.config/mango/config.conf` | `bind=` / `axisbind=` / `mousebind=` parser | + +## Installation + +```bash +cp -r keybind-cheatsheet ~/.config/noctalia/plugins/ +``` + +## Usage + +### Bar Widget +Add the plugin to your bar configuration in Noctalia settings. Click the keyboard icon to open the cheatsheet. + +### Global Hotkey + +**Hyprland:** +```bash +bind = $mod, F1, exec, qs -c noctalia-shell ipc call plugin:keybind-cheatsheet toggle +``` +You can set your custom Super key variable (e.g. `$mainMod`) in the plugin settings. + +**Niri:** +```kdl +binds { + Mod+F1 { spawn-sh "qs -c noctalia-shell ipc call plugin:keybind-cheatsheet toggle"; } +} +``` + +**MangoWC:** +```bash +bind=SUPER,F1,spawn,qs -c noctalia-shell ipc call plugin:keybind-cheatsheet toggle +``` + +### IPC Commands + +| Command | Effect | +|---------|--------| +| `qs -c noctalia-shell ipc call plugin:keybind-cheatsheet toggle` | Open / close the cheatsheet panel | +| `qs -c noctalia-shell ipc call plugin:keybind-cheatsheet refresh` | Force a re-parse of your keybindings | + +`refresh` is useful after editing your config — bind it to a key to reload without restarting the shell. + +## Hyprland Lua Config (0.55+) + +Hyprland 0.55 replaced the static hyprlang `.conf` with a **Lua config** (`hyprland.lua`). Binds can now be generated with `require()`, `for` loops and runtime logic, so they **cannot be recovered by reading the file as text**. + +### How it works + +Instead of parsing the Lua file, the plugin asks Hyprland directly: + +1. **Authoritative bind list** — runs `hyprctl binds -j` and reads the already-evaluated JSON bind list. This correctly handles `require()` modules, `for` loops and multi-key chords — whatever Hyprland *actually* has bound at runtime. +2. **Category & description recovery** — the plugin then *lightly scans* `hyprland.lua` and every file it pulls in via `require()` to recover human-readable structure: + - **Category headers**: a comment in the form `-- N. NAME` (e.g. `-- 1. Applications`) + - **Static descriptions**: a `description = "..."` (or `desc = '...'`) literal maps that exact description to the current category + - **Loop-generated descriptions**: a concatenated literal such as `description = "Workspace " .. i` is treated as a *prefix* — any bind whose description starts with `Workspace ` is filed under that category +3. Binds whose description can't be matched fall into a generic **Other** category; binds with no description at all go to the **Without Description** section (see below). + +You don't need to change your Lua config — just keep using `-- N. NAME` comment headers and `description = "..."` fields where you want grouping. + +**Example Lua structure the scanner understands:** +```lua +-- 1. Applications +Hyprland.config.bind("$mod, T", function() ... end, { description = "Terminal" }) +Hyprland.config.bind("$mod, B", function() ... end, { description = "Browser" }) + +-- 2. Workspaces +for i = 1, 9 do + Hyprland.config.bind("$mod, " .. i, function() ... end, + { description = "Workspace " .. i }) -- prefix "Workspace " -> category "Workspaces" +end + +require("keybinds") -- followed and scanned recursively +``` + +### Parser mode + +A **Parser Mode** setting controls which Hyprland parser is used: + +| Mode | Behavior | +|------|----------| +| `auto` *(default)* | Use the Lua parser if `hyprland.lua` exists, otherwise fall back to the `.conf` parser | +| `lua` | Always use `hyprctl binds -j` (Lua parser) | +| `conf` | Always use the classic `.conf` text parser | + +The legacy hyprlang `.conf` parser is **kept unchanged** as a fallback for users still on hyprlang configs. + +## Without Description Section + +Binds with no description are no longer silently dropped. They appear in a dedicated **Without Description** section where you can: + +- **Add a custom description** inline — it is remembered and displayed like any other bind +- **Hide** a bind you don't care about + +Overrides are keyed by a **stable bind identity** (`submap | modmask | key | flags | dispatcher`) that deliberately excludes Hyprland's unstable internal Lua registry reference, so your custom descriptions and hidden binds **survive Hyprland restarts**. + +Settings provide a **"Show binds without a description"** toggle, plus **"Restore hidden"** and **"Clear all overrides"** actions. + +## Config Format + +### Hyprland (classic `.conf`) + +Recursively parses your main config and all `source` includes. + +```bash +# 1. APPLICATIONS +bind = $mainMod, T, exec, alacritty #"Terminal" +bind = $mainMod, B, exec, firefox #"Browser" + +# 2. WINDOW MANAGEMENT +bind = $mainMod, Q, killactive, #"Close window" +bind = $mainMod, F, fullscreen, #"Toggle fullscreen" +``` + +- Categories: `# N. CATEGORY NAME` (N is a number) +- Descriptions: `#"description"` at end of the bind line +- `source = ~/.config/hypr/keybinds.conf` and globs like `source = ~/.config/hypr/apps/*.conf` are followed automatically + +### Niri + +Parses the `binds { }` block and follows all `include` directives. + +```kdl +binds { + // #"Applications" + Mod+T hotkey-overlay-title="Terminal" { spawn "alacritty"; } + + // #"Window Management" + Mod+Q hotkey-overlay-title="Close window" { close-window; } + + // #"Workspaces" + Mod+1 { focus-workspace 1; } +} +``` + +- Categories: `// #"Category Name"` (exact format) +- Descriptions: `hotkey-overlay-title="description"` attribute +- Without descriptions, actions are auto-categorized by type (see table below) +- `include "~/.config/niri/binds.kdl"` is followed automatically + +### MangoWC + +Parses `bind=`, `axisbind=` and `mousebind=` directives from `~/.config/mango/config.conf`. + +```bash +# Applications +bind=SUPER,T,spawn,alacritty #"Terminal" +bind=SUPER,B,spawn,firefox #"Browser" + +# Window Management +bind=SUPER,Q,killclient, #"Close window" +``` + +- Categories: standalone `# Category Name` comment lines +- Descriptions: trailing `#"description"` on a bind line +- Modifier aliases recognized: `LOGO` = `SUPER`, `MOD1` = `ALT` +- XF86 media keys are formatted (Vol Up, Mute, Bright Up/Down, …) +- Lines without a preceding `# Category` use the localized default category + +## Auto-Categorization (Niri) + +When no category comment is provided, keybindings are grouped by action: + +| Action prefix | Category | +|---------------|----------| +| `spawn` | Applications | +| `focus-column-*` | Column Navigation | +| `focus-window-*` | Window Focus | +| `focus-workspace-*` | Workspace Navigation | +| `move-column-*` | Move Columns | +| `move-window-*` | Move Windows | +| `close-window`, `fullscreen-window` | Window Management | +| `maximize-column` | Column Management | +| `set-column-width` | Column Width | +| `screenshot*` | Screenshots | +| `power-off-monitors` | Power | +| `quit` | System | + +## Special Key Formatting + +| Raw Key | Display | +|---------|---------| +| `XF86AudioRaiseVolume` | Vol Up | +| `XF86AudioLowerVolume` | Vol Down | +| `XF86AudioMute` | Mute | +| `XF86MonBrightnessUp` | Bright Up | +| `XF86MonBrightnessDown` | Bright Down | +| `Print` | PrtSc | +| `Prior` / `Next` | PgUp / PgDn | + +## Color Customization + +Every key category has independently themeable **background** and **text** colors: +`Super`, `Ctrl`, `Shift`, `Alt`, `XF86`, `Print`, numeric, mouse and default letter keys — plus the description text color. + +- **Two-pill rows** per category: left pill = background, right pill = label text on that background. Click a pill to open the color picker. +- **Theme-aware defaults**: `Super` / `Ctrl` / `Shift` use an empty sentinel meaning "use the Material theme accent" (`mPrimary` / `mSecondary` / `mTertiary`), so themed setups stay untouched unless you deliberately override. +- **Clipboard quick-paste**: copy a `#RRGGBB` / `#RRGGBBAA` hex and a paste icon appears in each pill — one click applies it (clipboard polled via `wl-paste`). +- **Live preview + revert**: changes preview immediately; closing Settings without Save restores the snapshot taken when the panel opened. +- **Per-row reset** and a **"Reset all colors"** action restore theme defaults. + +## Settings + +Access settings via the gear icon in the panel header: + +- **Window width / height** (auto or manual) and **column count** (1-4) +- **Hyprland config path** — classic `.conf` location +- **Hyprland Lua path** — `hyprland.lua` location (0.55+) +- **Parser mode** — `auto` / `lua` / `conf` +- **Niri config path** / **MangoWC config path** +- **Show binds without a description** toggle + **Restore hidden** / **Clear all overrides** +- **Merge sequential binds** and **split large workspace category** (threshold configurable) +- **Per-category colors** — background + text for every category, with clipboard paste and reset +- **Refresh** — force reload keybindings + +## Troubleshooting + +### "Loading..." stays forever +1. Check the compositor is detected: look for logs tagged `[KeybindCheatsheet]` +2. Verify the config file exists at the configured path +3. On Hyprland 0.55+, confirm `hyprctl binds -j` works in your terminal + +### `hyprctl` error shown in the panel +The Lua parser depends on `hyprctl binds -j`. Ensure Hyprland is running and `hyprctl` is on your `PATH`, or force the classic parser by setting **Parser mode** to `conf`. + +### No categories found +- **Hyprland `.conf` / MangoWC:** categories must be `# 1.` / `# Category Name` comment lines +- **Hyprland Lua:** add `-- N. NAME` headers and `description = "..."` fields in `hyprland.lua` (and `require()`d modules) +- **Niri:** use `// #"Category Name"` format + +### Binds missing or under "Without Description" +On Lua configs, descriptions are matched from `description = "..."` literals against the live `hyprctl` binds. Loop-generated binds need a concatenated prefix literal (e.g. `"Workspace " .. i`). Anything unmatched lands in **Without Description**, where you can add a description or hide it. + +### Keybinds from included files not showing +The plugin follows `source` (Hyprland `.conf`), `require()` (Hyprland Lua) and `include` (Niri) directives automatically. Check logs to see which files are parsed. + +## Requirements + +- Noctalia Shell 3.6.0+ +- Hyprland (classic `.conf` or 0.55+ Lua), Niri, or MangoWC +- `hyprctl` on `PATH` for Hyprland Lua configs +- `wl-paste` (wl-clipboard) for the color clipboard quick-paste feature + +## License + +MIT -- cgit v1.2.3