From 269079df3429922c6d3d5aa3e4831fe3ff7ddfdb Mon Sep 17 00:00:00 2001 From: Michael Wegener Date: Thu, 9 Jul 2026 11:01:51 +0200 Subject: [PATCH] chore(hyprland): enable mouse window drag/resize and migrate cheatsheets to learn portal Co-authored-by: Junie --- CHANGELOG.md | 3 + .../roles/hyprland/templates/hyprland.lua.j2 | 8 +- docs/hyprland-keybindings.md | 135 -------------- docs/neovim-cheatsheet.md | 64 ------- docs/screenshot-cheatsheet.md | 102 ----------- docs/yazi-cheatsheet.md | 167 ------------------ 6 files changed, 9 insertions(+), 470 deletions(-) delete mode 100644 docs/hyprland-keybindings.md delete mode 100644 docs/neovim-cheatsheet.md delete mode 100644 docs/screenshot-cheatsheet.md delete mode 100644 docs/yazi-cheatsheet.md diff --git a/CHANGELOG.md b/CHANGELOG.md index e6af5a3..c61c76a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Fixed +- Fixed Hyprland configuration warning/error by changing the DVI-D-1 monitor `transform` property from a string `"1"` to an integer `1` (2026-07-09). - tuigreet boot error: removed invalid `--numlock` flag from greetd config (not a valid tuigreet parameter). Replaced X11-only `numlockx on` in Hyprland with native `numlock_by_default = true` in the `input` section (2026-06-01). - hypridle SEGV crash loop (ADR N/A, hotfix): sdbus-cpp 2.3.0 had an ABI incompatibility causing hypridle to SIGSEGV in `libsdbus-c++.so.2` `registerSignalHandler`. Fixed by upgrading sdbus-cpp from 2.3.0-1 to 2.3.1-1 (Arch upstream, pulled ahead of Manjaro mirror sync). Also resolves latent ABI issues for hyprlock and xdg-desktop-portal-hyprland (2026-05-22). - Resolved kitty cursor keys not working by disabling the `TERM=xterm-256color` override in `.bashrc`, allowing Kitty to correctly set `TERM=xterm-kitty`. Added Ansible management for `kitty.conf` to ensure proper terminal behavior and shell integration (2026-05-19). @@ -17,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Identified failed `archlinux-keyring-wkd-sync.service` in system health check. ### Added +- Enabled click-and-drag window movement and resizing under the SUPER modifier, and enabled border dragging to resize tiled windows natively, updating both the Hyprland configuration template and keybindings cheatsheet (2026-07-09). - Documented local dev services in `docs/tech/stack.md`: Caddy (systemd `caddy.service` on port 443) with 14 `*.localhost` sites and mkcert TLS at `/etc/caddy/`. Registered as a manual override in `docs/tech/manual-overrides.md` (no `caddy` Ansible role exists yet) (2026-07-06). - Investigation learning record `docs/learnings/2026-07-06-caddy-onlyoffice-mcp-sse-investigation.md`: Caddy `context canceled` SSE aborts (~1.5ms) on `onlyoffice.localhost/mcp` forwarded to `localhost:3847` (OnlyOffice MCP server). Upstream verified alive (HTTP 406 to plain GET = expected). Handed off to GitLab issue [satware/mcp/onlyoffice#92](https://gitlab.satware.com/satware/mcp/onlyoffice/-/work_items/92) with 5 hypotheses, 7 investigation tasks, and a proposed Caddy `flush_interval -1` + `transport http { versions 1.1 }` mitigation (not applied yet) (2026-07-06). - Waybar USB module: auto-mount USB sticks via udisks2, show hover details (device/model/size/fs/mountpoint), left-click opens in yazi, right-click ejects. Script at `~/.config/waybar/scripts/usb.sh`, Ansible-managed via `hyprland` role template `waybar_usb_script.sh.j2` (2026-05-22). @@ -37,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Comprehensive health report for `mw-pfeddersheim-workstation` (2026-03-09). ### Removed +- Moved workstation-specific cheatsheets (`hyprland-keybindings.md`, `screenshot-cheatsheet.md`, `yazi-cheatsheet.md`, and the obsolete workstation copy of `neovim-cheatsheet.md`) to the central `learn` repository (2026-07-09). - `alesi-routine-morning.service` / `alesi-routine-morning.timer` user-level systemd units — daily 07:45 morning routine was failing (exit 128, git outside repo). Script `scripts/daily-routine.sh` retained for manual use (2026-05-26). - Tier 1 package cleanup (ADR 0007): removed 25 X11/KDE/legacy packages via Ansible — lightdm, lightdm-slick-greeter, lightdm-settings, sddm, sddm-kcm, sddm-breath-theme, xf86-video-{amdgpu,ati,intel,nouveau,vesa}, xf86-input-synaptics, xterm, xorg-{twm,xinit,xkill,server-xvfb}, x11vnc, numlockx, startup-notification, illyria-wallpaper, ntp, spectacle, pamac-tray-icon-plasma. All have Wayland-native replacements already in use. Frees ~80-120 MiB direct + cascade deps (2026-05-22). - Tier 2 package cleanup (ADR 0007): removed KDE Plasma stack — kwin, plasma-desktop, plasma-workspace, kdeplasma-addons, plasma-nm, plasma-pa, plasma-x11-session, kde-gtk-config, powerdevil, xdg-desktop-portal-kde, plasma-integration, dolphin, dolphin-plugins, kdegraphics-thumbnailers. Plus 45 cascade orphan deps. Dolphin replaced by yazi. Frees ~400 MiB total (2026-05-22). diff --git a/ansible/roles/hyprland/templates/hyprland.lua.j2 b/ansible/roles/hyprland/templates/hyprland.lua.j2 index 93292f8..9e49cdb 100644 --- a/ansible/roles/hyprland/templates/hyprland.lua.j2 +++ b/ansible/roles/hyprland/templates/hyprland.lua.j2 @@ -18,7 +18,7 @@ local mainMod = "SUPER" -- 2. DVI-D-1 BenQ BL2405 1920x1080@60 (rotated 90 CW) -- 3. HDMI-A-1 TERRA 3280W 2560x1440@144 (3640x0) hl.monitor({ output = "DP-1", mode = "2560x1440@60", position = "0x0", scale = "1" }) -hl.monitor({ output = "DVI-D-1", mode = "1920x1080@60", position = "2560x0", scale = "1", transform = "1" }) +hl.monitor({ output = "DVI-D-1", mode = "1920x1080@60", position = "2560x0", scale = "1", transform = 1 }) hl.monitor({ output = "HDMI-A-1", mode = "2560x1440@60", position = "3640x0", scale = "1" }) hl.workspace_rule({ workspace = 1, monitor = "DP-1", default = true }) @@ -62,7 +62,7 @@ hl.config({ active_border = { colors = {"rgba(33ccffee)", "rgba(00ff99ee)"}, angle = 45 }, inactive_border = "rgba(595959aa)", }, - resize_on_border = false, allow_tearing = false, layout = "dwindle", + resize_on_border = true, allow_tearing = false, layout = "dwindle", }, decoration = { rounding = 10, rounding_power = 2, @@ -172,6 +172,10 @@ hl.bind(mainMod .. " + Print", hl.dsp.exec_cmd("grimblast copysave activ hl.bind(mainMod .. " + SHIFT + Print", hl.dsp.exec_cmd("grimblast copysave output")) hl.bind(mainMod .. " + ALT + Print", hl.dsp.exec_cmd('grim -g "$(slurp)" - | satty -f -')) +-- Mouse binds +hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true }) +hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true }) + -------------------------------- ---- WINDOW RULES ---- -------------------------------- diff --git a/docs/hyprland-keybindings.md b/docs/hyprland-keybindings.md deleted file mode 100644 index cafce53..0000000 --- a/docs/hyprland-keybindings.md +++ /dev/null @@ -1,135 +0,0 @@ -# Hyprland Keybindings - Full Cheatsheet - -**Layout:** German (de) | **Mod key:** SUPER (Windows key) | **Config:** `hyprland.lua` (Hyprland 0.55+) - ---- - -## General - -| Shortcut | Action | Details | -|----------|--------|---------| -| `SUPER+Q` | Kill active window | killactive | -| `SUPER+T` | Open terminal | kitty | -| `SUPER+Enter` | Open terminal | kitty | -| `SUPER+M` | Exit Hyprland | exit | -| `SUPER+E` | File manager | dolphin | -| `SUPER+V` | Toggle floating | togglefloating | -| `SUPER+D` | App launcher | hyprlauncher | -| `SUPER+P` | Toggle pseudo-split | pseudo | -| `SUPER+J` | Toggle split direction | layoutmsg togglesplit | -| `SUPER+F` | Toggle fullscreen | fullscreen 0 | -| `SUPER+R` | Reload config | hyprctl reload | -| `SUPER+SPACE` | Toggle float (popup) | togglefloating | -| `SUPER+TAB` | Cycle next window | cyclenext | -| `SUPER+SHIFT+TAB` | Cycle previous window | cyclenext prev | -| `SUPER+` `` ` `` (Grave) | Toggle scratchpad | togglespecialworkspace | -| `SUPER+SHIFT+` `` ` `` | Send window to scratchpad | movetoworkspace special | -| `SUPER+CTRL+K` | Keybind cheat menu | *(broken - pipelines to grep+fuzzel)* | -| `SUPER+CTRL+L` | Lock screen | hyprlock | -| `SUPER+B` | Web browser | google-chrome-stable | - -## Navigation / Focus - -| Shortcut | Action | -|----------|--------| -| `SUPER+TAB` | Cycle next window | -| `SUPER+SHIFT+TAB` | Cycle previous window | -| `SUPER+H` | Move focus left | -| `SUPER+L` | Move focus right | -| `SUPER+left arrow` | Move focus left | -| `SUPER+right arrow` | Move focus right | -| `SUPER+up arrow` | Move focus up | -| `SUPER+down arrow` | Move focus down | - -## Window Movement - -| Shortcut | Action | -|----------|--------| -| `SUPER+SHIFT+H` | Move window left | -| `SUPER+SHIFT+L` | Move window right | -| `SUPER+SHIFT+K` | Move window up | -| `SUPER+SHIFT+J` | Move window down | -| `SUPER+SHIFT+left` | Move window left | -| `SUPER+SHIFT+right` | Move window right | -| `SUPER+SHIFT+up` | Move window up | -| `SUPER+SHIFT+down` | Move window down | - -## Window Resize - -| Shortcut | Action | -|----------|--------| -| `SUPER+ALT+H` | Resize active: width -40 | -| `SUPER+ALT+L` | Resize active: width +40 | -| `SUPER+ALT+K` | Resize active: height -40 | -| `SUPER+ALT+J` | Resize active: height +40 | - -## Screenshots - -| Shortcut | Action | Tool | -|----------|--------|------| -| `Print` | Area select → save + copy | grimblast copysave area | -| `SUPER+Print` | Active window → save + copy | grimblast copysave active | -| `SUPER+SHIFT+Print` | Full monitor → save + copy | grimblast copysave output | -| `SUPER+ALT+Print` | Area select → annotate | grim | slurp | satty | - -## Workspaces - -| Shortcut | Action | -|----------|--------| -| `SUPER+1..9` | Switch to workspace 1-9 | -| `SUPER+SHIFT+1..9` | Move active window to workspace 1-9 | -| `SUPER+` `` ` `` | Toggle scratchpad (togglespecialworkspace) | -| `SUPER+SHIFT+` `` ` `` | Move to scratchpad (movetoworkspace special) | - -### Workspace Layout - -| Workspace | Monitor | Position | -|-----------|---------|----------| -| 1 | DP-1 (TERRA 3280W) | Left, 2560x1440@60 | -| 2 | DVI-D-1 (BenQ BL2405) | Center, 1920x1080@60 rotated 90deg | -| 3 | HDMI-A-1 (TERRA 3280W) | Right, 2560x1440@60 | - -## Kitty Title Bar - -Every kitty terminal tile shows a title bar with: - -| Field | Description | -|-------|-------------| -| `{hostname}` | Machine hostname | -| `{cwd}` | Current working directory | -| `{title}` | Process/window title | - -**Config:** `window_title_bar top` + `window_title_bar_min_windows 1` (kitty 0.46.2) - -## Notes - -- `SUPER+CTRL+K` (keybind menu) does **not work** - the `sed` pipeline breaks. - The Lua config format makes this harder to grep; consider a different approach. -- Config migrated from `.conf` to `.lua` format (Hyprland 0.55+). - See `docs/tech/hyprland-lua-migration.md` for the migration mapping. - -## Troubleshooting - -| Issue | Check | -|-------|-------| -| Print key not working | `hyprctl binds | grep Print` | -| `SUPER+R` not working | `hyprctl binds | grep 'reload'` | -| Screenshots fail | `which grimblast satty slurp grim` | -| Clipboard empty | `echo test | wl-copy && wl-paste` | - -## Satty Editor Shortcuts - -| Action | Shortcut | -|--------|----------| -| Freehand | F | -| Rectangle | R | -| Ellipse | E | -| Line/Arrow | L | -| Text | T | -| Blur | B | -| Crop | C | -| Undo | Ctrl+Z | -| Redo | Ctrl+Shift+Z | -| Copy | Ctrl+C | -| Save | Ctrl+S | -| Quit | Esc or Ctrl+Q | diff --git a/docs/neovim-cheatsheet.md b/docs/neovim-cheatsheet.md deleted file mode 100644 index 2b5f0de..0000000 --- a/docs/neovim-cheatsheet.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "Neovim v0.12.2 Cheatsheet" -author: "mw-pfeddersheim-workstation" -date: "June 2026" ---- - -# Neovim Cheatsheet - -**Version:** v0.12.2 (LuaJIT 2.1) **Config:** `~/.config/nvim/init.lua` - -## Search - -### Buffer Search (current file) - -| Command | Action | -|---------|--------| -| `/pattern` | Search forward | -| `?pattern` | Search backward | -| `n` | Next match (forward) | -| `N` | Previous match (backward) | - -### File Search (across files) - -| Command | Action | -|---------|--------| -| `:grep pattern` | Search current directory with ripgrep | -| `:grep pattern /path/to/dir` | Search specific directory | -| `:cfirst` | Jump to first match | -| `:cnext` / `:cprev` | Next / previous match | -| `:copen` | Open quickfix window with all results | -| `:cclose` | Close quickfix window | - -## Editing - -| Command | Action | -|---------|--------| -| `D` | Delete from cursor to end of line | -| `d$` | Delete to end of line (same as `D`) | -| `dd` | Delete entire line | -| `C` | Change from cursor to end of line (delete + insert mode) | - -## Text Objects - -Delete or operate on structured text by type: - -| Command | Action | -|---------|--------| -| `di{` | Delete **inside** `{}` (keeps braces) | -| `da{` | Delete **a** `{}` (removes braces too) | -| `di"` | Delete inside double quotes | -| `da"` | Delete a double-quoted section | -| `di(` | Delete inside parentheses | -| `da(` | Delete a parenthesized section | -| `di[` | Delete inside brackets | -| `da[` | Delete a bracketed section | -| `di<` | Delete inside angle brackets | -| `da<` | Delete an angle-bracketed section | - -**Pattern:** `d` (delete) + `i` (inside) / `a` (around) + `{type}` - -**Also works with:** -- `v` + text object — select (e.g. `vi{` selects inside braces) -- `y` + text object — yank/copy (e.g. `ya{` copies including braces) -- `c` + text object — change (e.g. `ci{` deletes + enters insert mode) diff --git a/docs/screenshot-cheatsheet.md b/docs/screenshot-cheatsheet.md deleted file mode 100644 index 423c3d2..0000000 --- a/docs/screenshot-cheatsheet.md +++ /dev/null @@ -1,102 +0,0 @@ -# Screenshot Cheatsheet — Hyprland + grimblast + satty - -## Quick Reference (German Keyboard Layout) - -| Key Combo | Action | Tool | Pipeline | -|-----------|--------|------|----------| -| `Print` | Select area → save to file + clipboard | grimblast | area → copysave | -| `SUPER + Print` | Active window → save to file + clipboard | grimblast | active window → copysave | -| `SUPER + SHIFT + Print` | Full monitor → save to file + clipboard | grimblast | output → copysave | -| `SUPER + ALT + Print` | Select area → open in satty for annotation | grim+satty | area → satty editor | - -## Test Checklist - -Run through these to verify everything works: - -### Test 1: Area Screenshot (Print) -1. Press `Print` -2. Drag to select a region -3. Expected: Screenshot saved to `~/Pictures/` AND copied to clipboard -4. Verify: Paste clipboard into a test doc - -### Test 2: Current Window (SUPER+Print) -1. Focus any window -2. Press `SUPER+Print` -3. Expected: That window captured, saved + copied - -### Test 3: Full Monitor (SUPER+SHIFT+Print) -1. Press `SUPER+SHIFT+Print` -2. Expected: Current monitor captured, saved + copied - -### Test 4: Annotate in Satty (SUPER+ALT+Print) -1. Press `SUPER+ALT+Print` -2. Drag to select a region -3. Expected: Satty window opens with the screenshot -4. Try these Satty actions: - - Freehand drawing (left toolbar) - - Rectangle/Arrow annotations - - Blur/redact sections - - Copy annotated result to clipboard - - Save annotated result to file -5. Exit Satty with `Esc` or `Ctrl+Q` - -## Manual CLI Commands - -If keybindings fail, test tools directly: - -```bash -# Capture area and save to specific file -grim -g "$(slurp)" ~/Pictures/test-area.png - -# Capture area and pipe to satty for editing -grim -g "$(slurp)" - | satty -f - - -# Capture full screen and pipe to satty -grim - | satty -f - - -# Copy area screenshot to clipboard -grim -g "$(slurp)" - | wl-copy - -# grimblast manual modes -grimblast copysave area # area -grimblast copysave active # current window -grimblast copysave output # current monitor -grimblast save area ~/Pictures/test-grimblast.png # save only -``` - -## Satty Editor Shortcuts - -| Action | Shortcut | -|--------|----------| -| Freehand | `F` | -| Rectangle | `R` | -| Ellipse | `E` | -| Line/Arrow | `L` | -| Text | `T` | -| Blur | `B` | -| Crop | `C` | -| Undo | `Ctrl+Z` | -| Redo | `Ctrl+Shift+Z` | -| Copy to clipboard | `Ctrl+C` | -| Save to file | `Ctrl+S` | -| Save As | `Ctrl+Shift+S` | -| Quit | `Esc` or `Ctrl+Q` | - -## Dependencies - -| Tool | Purpose | Status | -|------|---------|--------| -| grim | Wayland screenshot capture | Installed | -| slurp | Region/window selection | Installed | -| wl-clipboard | Clipboard support | Installed | -| satty | Annotation editor | Installed | -| grimblast | Hyprland screenshot helper | Installed | -| hyprshot | Alternative screenshot tool | Installed (not used in keybinds) | - -## Troubleshooting - -- **Print key not working**: Verify binding with `hyprctl binds | grep Print` -- **satty won't open**: Check `which satty` and `echo $XDG_SESSION_TYPE` (must be wayland) -- **slurp selector invisible**: Check if `grim` and `slurp` are in PATH -- **Screenshots not saving**: Check `~/Pictures/` directory exists -- **Clipboard empty**: Verify `wl-copy` and `wl-paste` work (`echo test | wl-copy && wl-paste`) diff --git a/docs/yazi-cheatsheet.md b/docs/yazi-cheatsheet.md deleted file mode 100644 index a27f709..0000000 --- a/docs/yazi-cheatsheet.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Yazi v26.5.6 Cheatsheet" -author: "mw-pfeddersheim-workstation" -date: "May 2026" ---- - -# Yazi Cheatsheet - -**Version:** 26.5.6 (Arch Linux 2026-05-10) **Config:** `~/.config/yazi/` - -## Quick Start - -| Key | Action | -|-----|--------| -| `yazi` | Launch Yazi | -| `y` | Shell wrapper (cd persists on exit) | -| `q` | Quit normal (apply cwd) | -| `Q` | Quit without cwd change | -| `F1` | Show help | - -## Navigation - -| Key | Action | -|-----|--------| -| `h` | Parent directory | -| `l` | Enter dir / open file | -| `j` / `k` | Down / Up | -| `H` / `L` | History back / forward | -| `Enter` | Open hovered file | -| `Tab` | Toggle file details | -| `.` | Toggle hidden files | -| `~` | Home directory (DE: Shift+^+Space) | -| `g g` | Go to top | -| `G` | Go to bottom | - -## Search - -| Key | Action | -|-----|--------| -| `/` | Search forward | -| `?` | Search backward | -| `n` / `N` | Next / previous match | -| `f` | Interactive filter (fuzzy) | -| `S` | Search with fd | - -## File Operations - -| Key | Action | -|-----|--------| -| `Space` | Toggle selection | -| `v` | Visual mode range select | -| `Ctrl+A` | Select all | -| `Esc` | Clear selection | -| `y` | Yank (copy) | -| `p` | Paste | -| `X` | Cut | -| `x` | Undo cut | -| `D` | Delete to trash | -| `Shift+D` | Permanent delete | -| `a` | New file | -| `Shift+A` | New directory | -| `R` | Rename | -| `Shift+R` | Bulk rename | -| `O` | "Open with..." menu | - -## Sorting (comma prefix) - -| Key | Action | -|-----|--------| -| `, m` | Modified (newest) | -| `, M` | Modified reverse | -| `, c` | Created (newest) | -| `, C` | Created reverse | -| `, e` | Extension (alpha) | -| `, a` | Alphabetic | -| `, s` | Size (largest) | -| `, S` | Size (smallest, reverse) | - -## Tabs - -| Key | Action | -|-----|--------| -| `t` | New tab | -| `1` ... `9` | Switch to tab | -| `[` / `]` | Prev / next tab | -| `W` | Close tab | - -## Shell & Commands - -| Key | Action | -|-----|--------| -| `!` | Drop into shell here | -| `:` | Command line | -| `Ctrl+S` | Run shell command | - -## Emit Commands (`:` prefix) - -| Command | Action | -|---------|--------| -| `:cd ` | Change directory | -| `:reveal` | Reveal file in parent dir | -| `:tab_create` | Open new tab | -| `:tab_switch N` | Switch to tab N | -| `:quit` | Quit Yazi | -| `:yank` | Yank selected | -| `:paste` | Paste yanked | -| `:remove` | Trash | -| `:rename` | Rename hovered | -| `:shell ` | Run shell command | - -## Power Tricks - -### 1. Shell Wrapper (cd persists) -Use the `y` wrapper instead of raw `yazi` so your shell cds into the directory you navigated to on exit. - -### 2. Clipboard on Yank (Wayland) -Bind `y` in `keymap.toml` to `wl-copy -t text/uri-list` then yank for system clipboard integration. - -### 3. Git Root Jump -Bind `g r` to `ya emit cd "$(git rev-parse --show-toplevel)"` - -### 4. Escape Closes Input -In `keymap.toml` input section: map `Esc` to `close` (skip vim mode). - -### 5. Disable Image Previews -In `yazi.toml` `plugin` section: `preloaders = []` and `previewers = []`. -For network mounts: `url = /remote/** run = noop`. - -### 6. Hostname in Header -In `init.lua`: `Header:children_add` with `user_name()` + `host_name()` spans. - -### 7. Show Symlink Target in Status Bar -In `init.lua`: `Status:children_add` with `h.link_to`. - -## Configuration Files - -| File | Purpose | -|------|---------| -| `keymap.toml` | Custom key bindings | -| `yazi.toml` | Behavior, preview rules, openers | -| `theme.toml` | Colors and UI theme | -| `init.lua` | Lua startup script | -| `plugins/` | Plugin directory | - -## Recommended Plugins - -| Plugin | Purpose | -|--------|---------| -| `smart-enter` | One key: open file or enter dir | -| `smart-paste` | Paste without entering dir | -| `smart-tab` | New tab + enter hovered dir | -| `toggle-pane` | Maximize / hide preview pane | -| `full-border` | Full panel borders | -| `confirm-quit` | Confirm on multi-tab | -| `zoxide` | Zoxide dir jumping | -| `chmod` | Change file permissions | - -## Daily Drill - -| Area | Keys | -|------|------| -| **Nav** | `j/k` move / `l` enter / `h` back | -| **Files** | `Space` select / `y` copy / `p` paste / `X` cut | -| **Delete** | `D` trash / `R` rename / `a` create | -| **Search** | `/` search / `f` filter / `g` top / `G` bottom | -| **Tabs** | `t` new / `1-9` switch / `W` close | -| **Misc** | `!` shell / `q` quit / `F1` help |