summaryrefslogtreecommitdiff
path: root/noctalia/.config/plugins/keybind-cheatsheet/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'noctalia/.config/plugins/keybind-cheatsheet/README.md')
-rw-r--r--noctalia/.config/plugins/keybind-cheatsheet/README.md272
1 files changed, 272 insertions, 0 deletions
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