返回资讯中心
外部精选
软件工程
#开发者实时流

Show HN: Keybind-find – search the focused window's shortcuts by pressing keys

Press one hotkey and get a searchable list of the keyboard shortcuts that work where you are right now: your

Hacker News 最新Benjmhart2026/10/31 · 今天30 分钟阅读

以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。

Press one hotkey and get a searchable list of the keyboard shortcuts that work where you are right now: your window manager's, the focused app's (nvim, tmux, herdr, alacritty, a web app) and your espanso snippets. Pick one and keybind-find presses those keys for you, so it works as a command palette that also shows you the key you could have pressed instead.

The lists are read from the programs' real configuration, your own bindings included, so nothing is kept up by hand.

Where What is read Setup

xmonad your keymap, with each binding's name, and xmonad's stock keys a few lines in xmonad.hs, incl. ewmh: docs/xmonad.md

sway your bindsym lines (following include and set $var), and the focused window from sway's tree none

Hyprland its binds from the running compositor (hyprctl -j binds), with each bind's description, and the focused window from hyprctl none (below)

KDE Plasma its global shortcuts (kglobalshortcutsrc) and the launch shortcuts of .desktop files, and the focused window (on Wayland from kdotool) on Wayland, kdotool; picks there are not sent (below)

i3 the bindings of the config i3 has loaded (i3-msg -t get_config; from 4.20, includes followed and variables replaced by i3) none (below)

Xfce xfwm4's window shortcuts and your application shortcuts, from xfconf-query (X11) xfconf-query (below)

GNOME its window, shell, mutter and media-key shortcuts, your custom shortcuts and the overlay key, from gsettings; on X11 also the focused window gsettings; on Wayland picks are not sent and the list opens in fzf (below)

any other X11 window manager the focused window, so every app below works; not the window manager's own keys an EWMH window manager (it sets _NET_ACTIVE_WINDOW)

other Wayland compositors (niri) espanso only: the focused window isn't read, so no app below untested

alacritty its keys: alacritty's defaults merged with your [[keyboard.bindings]] none

Ghostty its keys from ghostty +list-keybinds, as your config sets them none (below)

kitty its default shortcuts for its version (0.49.2 built in) with your kitty.conf maps on top none; the program in a tab needs remote control (below)

foot its default key, search and URL bindings for its version (1.28.0 built in) with your foot.ini on top, and its text bindings none (below)

Xfce Terminal its menu and scrolling shortcuts: xfce4-terminal's defaults for its version (1.2.0 built in) with your accels.scm on top none (below)

GNOME Terminal its keyboard shortcuts as its preferences set them, from gsettings (not on GNOME under Wayland, where the window isn't read) gsettings (below)

nvim your maps from a headless nvim with your config, with each map's desc none

Emacs the keys active in the buffer you are in, from the running Emacs over its server, with its major mode and evil state; with no server, the global map (and evil's) of your init file from emacs --batch server-start in your init, or emacs --daemon, for the live read (below)

vim your maps (:map, :map!, :tmap, :lmap): asked of the running vim when it has a server (with its buffer's maps, mode and filetype), else from a headless vim with your vimrc; not vim's built-in keys none; without a server it runs your vimrc (below)

nano its main-menu keys: nano's defaults for its version (7.2, 8.4 and 9.2 built in) with your nanorc's bind/unbind on top none (below)

micro its keys: micro's defaults for its version (2.0.11, 2.0.14 and 2.0.15 built in) with your bindings.json on top none (below)

Midnight Commander its keys by section (file manager, panel, editor, viewer, …): mc's compiled-in defaults (4.8.33's built in) with the system and your keymap on top none (below)

yazi its keys: yazi's default keymap for its version (25.4.8, 25.5.31 and 26.9.1 built in) with your keymap.toml merged in none (below)

ranger its file-browser keys: ranger's default rc.conf (1.9.4's built in, the same since 1.9.3) with /etc/ranger/rc.conf and yours on top none (below)

helix its keys in normal, select and insert mode: helix's default keymap for its version (25.01.1 and 25.07.1 built in) with your config.toml keys merged in none (below)

ncmpcpp its keys: ncmpcpp's defaults (0.10.1's built in, the same since 0.9.2) with your bindings files on top none (below)

herdr herdr's defaults for its version, your config.toml and plugin commands none

tmux the running server's list-keys, so your prefix and bindings, with each key's note none

GNU screen its default command keys for its version (4.9 and 5.0 built in) with /etc/screenrc and your screenrc's bind, bind -c and escape on top none (below)

bash, zsh, fish the prompt's line-editing keys from the shell itself: bash's bind -p/-s/-X (with your .inputrc), zsh's bindkey -L, fish's bind (every mode) none; it runs your rc files: below

less its keys from less --help, with your lesskey file's #command binds on top; also under man, git log, systemctl status none; your keys need less 582+ and the lesskey source file (below)

mpv the bindings of a headless mpv started with your config: built-ins, your input.conf and keys your scripts bind at load, with each one's comment none; it starts mpv on every Super+/ (below)

zathura its keys: zathura's defaults for its version (0.5.2, 0.5.11 and 2026.10.23 built in) with your zathurarc's map/unmap on top none (below)

VS Code, VSCodium, Code - OSS the default keys (1.143.1's built in), your installed extensions' and your keybindings.json on top, each tagged with where it works; the file's language guessed from the title none (below)

Zed its default keymaps (1.25.3's built in) for your base keymap and vim or helix mode, with your keymap.json on top, each tagged with its context; the file's extension guessed from the title none (below)

Obsidian its default hotkeys (1.14.5's built in) with your vault's .obsidian/hotkeys.json on top, the vault picked by window title none (below)

st, surf, tabbed, dwm their stock keys from config.def.h at st 0.9.3, surf 2.1, tabbed 0.9 and dwm 6.8 (dwm's in a dwm session, whatever window has focus); a patched config.h isn't read: replace the sheet with your own of the same name none (below)

browsers built-in sheets for Gmail, YouTube and GitHub; any web app you write a sheet for none; GitHub's needs a URL-in-title extension (docs/sheets.md)

Firefox / Chromium keys the browser's own shortcuts (tabs, navigation, find, dev tools) in Firefox, LibreWolf, Zen, Chromium, Chrome, Brave and Edge, from built-in sheets none (below)

Vimium Vimium's defaults for its version, and your remaps from a saved backup none; remaps need the backup (docs/vimium.md)

espanso espanso match list; picking a match types its trigger none

anything else a sheet you write, or a script that prints one docs/sheets.md

nvim, vim, Emacs (and emacsclient -t), nano, micro, mc (and mcedit, mcview, mcdiff), yazi, ncmpcpp, ranger, helix, herdr, tmux, screen, the shells and less are read when they are the program in the focused terminal window: alacritty, kitty, foot, WezTerm, st, xterm/uxterm, Ghostty, GNOME Terminal, Konsole, Xfce Terminal, urxvt or Terminator (by window class, or sway app_id, Hyprland class); nvim also inside a herdr or tmux pane or a screen window. When one terminal process runs several shells (tabs, splits, or several windows from one process: alacritty's daemon mode, foot --server, urxvtd; by default GNOME Terminal, Xfce Terminal, WezTerm, Ghostty and Terminator), keybind-find finds the focused one on X11 when the terminal puts the window's id in each shell's environment (WINDOWID: Xfce Terminal, kitty, urxvt, alacritty), every window of that process runs one shell, and each of those windows still exists (xdotool search --pid: a tab dragged to another window keeps its old id; after tabs are swapped between two windows whose other tabs then close, each window still names the other's program, and a tab held open after its command exits has no shell to count, so its window gets its other tab's program); otherwise (tabs anywhere in that process, or a Wayland window) it prints a one-line warning and shows the list without the program inside (the terminal's own keys, alacritty's, Ghostty's, kitty's, foot's, GNOME Terminal's or Xfce Terminal's, are still listed). kitty can say which tab has focus when its remote control is on (below). espanso's word: true matches (they wait for a space or punctuation after the trigger) and regex matches (no literal trigger) can't be typed, picks do nothing while the espanso service is stopped, and matches limited by filter_exec aren't listed.

Over a shell prompt, keybind-find starts your shell as bash -ic, zsh -ic or fish -ic on every Super+/, so your rc files run each time (.bashrc, .zshrc, config.fish): whatever they start, they start again. The shell gets 3 seconds; an rc file that takes longer, or execs another program (exec tmux), is killed and the shell is left out with a one-line warning. keybind-find sets KEYBIND_FIND=1 for it, so you can skip slow or noisy parts:

[ -n "$KEYBIND_FIND" ] && return # bash or zsh: put it after your binds, before the slow part

fish: wrap the slow part in if not set -q KEYBIND_FIND; ...; end

For fish it also sends the fish_prompt event (fish loads its bindings on the first prompt), so your prompt's event handlers run too.

What it can't see: binds you made by hand in the running shell, binds a plugin adds later (zsh plugins that bind in a hook or on first use), and an INPUTRC or bind set only in a login profile. For bash and zsh it shows the keymap in force when the rc files are done: in vi mode that is insert mode (viins, bash's vi-insert), not command mode. The shell it starts is the one on keybind-find's PATH (your window manager's), which may not be the one in the terminal if you installed another. A script running in the terminal (bash build.sh) looks like a shell, so the prompt's keys show then too.

less is shown whenever it is any program in the terminal's foreground job, so it shows under man, git log and systemctl status too, as well as the program that started it when keybind-find reads that one (a shell running a script that pipes into less). Your keys are read from the lesskey source file less reads: $LESSKEYIN, else $XDG_CONFIG_HOME/lesskey, ~/.config/lesskey or ~/.lesskey. Only its #command section is used; #version lines are ignored. Before less 582, lesskey compiled your keys into a binary /.less; a compiled file (/.less or $LESSKEY) is never read, on any version: you get less's defaults and a one-line note. Debian's man runs less as pager, which is recognised too. LESSKEYIN and XDG_CONFIG_HOME come from keybind-find's environment (your window manager's), not the shell's, so a value set only in an rc file isn't seen.

mpv is shown when its window is focused (window class mpv, or the Flatpak's io.mpv.Mpv), not when mpv plays inside a terminal. On every Super+/ keybind-find starts mpv headless (--vo=null --ao=null --idle=once: no window, no sound, no file) with your config, so your scripts load each time, as at any mpv start, and a heavy config makes the list slower; mpv gets 3 seconds. It never takes over your player's input-ipc-server socket or log-file. The bindings are those of an idle mpv: keys a script binds later, while a file plays (uosc and similar), exist only in the running player and aren't listed. Mouse and wheel bindings and keys bound to ignore are left out. A Flatpak-only mpv isn't run (keybind-find needs mpv on PATH), but when mpv finds no config directory of its own ($XDG_CONFIG_HOME/mpv or ~/.config/mpv, or /.mpv), the Flatpak's (/.var/app/io.mpv.Mpv/config/mpv) is used.

In a zathura window, keybind-find lists zathura's keys by mode (normal, index, presentation, fullscreen, insert): the defaults of your zathura's version (from zathura --version; 0.5.2, 0.5.11 and 2026.10.23 are built in, generated from zathura's and girara's source at each tag; another version uses the nearest of the same major version, else the nearest older, and says so), with the map and unmap lines o

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →