feat: vim p/P paste from system clipboard

Vim's default p/P pastes from its internal unnamed register, which
is useless when the text to translate lives in another app's
clipboard. Override both in normal mode to read navigator.clipboard
.readText() and insert at (after) or before the cursor.

Caveats: requires browser clipboard permission (prompted on first
use), HTTPS or localhost. Both already satisfied — finrod is served
over the wildcard TLS cert.
This commit is contained in:
João Pedro Battistella Nadas
2026-06-09 16:41:52 +02:00
parent 876014a7b7
commit a058665b5b
2 changed files with 24 additions and 1 deletions

View File

@@ -513,12 +513,34 @@
// Override vim's H/L (normally "viewport top/bottom") so they exit the
// editor to the previous/next control, matching the same Shift-H/L
// contract the document handler uses elsewhere.
// contract the document handler uses elsewhere. Also override p/P in
// normal mode to paste from the system clipboard (vim's default p
// pastes from its internal register — useless when the source text
// comes from another app).
if (!isCoarsePointer) {
Vim.defineAction("finrodFocusPrev", () => moveFocus(-1));
Vim.defineAction("finrodFocusNext", () => moveFocus(1));
Vim.mapCommand("H", "action", "finrodFocusPrev", {}, { context: "normal" });
Vim.mapCommand("L", "action", "finrodFocusNext", {}, { context: "normal" });
async function pasteFromClipboard(after) {
try {
const text = await navigator.clipboard.readText();
if (!text) return;
const sel = editor.state.selection.main;
const pos = after ? sel.to : sel.from;
editor.dispatch({
changes: { from: pos, insert: text },
selection: { anchor: pos + text.length },
});
} catch (e) {
console.warn("Clipboard read failed:", e);
}
}
Vim.defineAction("finrodPasteAfter", () => pasteFromClipboard(true));
Vim.defineAction("finrodPasteBefore", () => pasteFromClipboard(false));
Vim.mapCommand("p", "action", "finrodPasteAfter", {}, { context: "normal" });
Vim.mapCommand("P", "action", "finrodPasteBefore", {}, { context: "normal" });
}
fillLangs();