v0.2.0: vim bindings, Shift-H/L focus nav, hot-model default #3
@@ -10,6 +10,7 @@ Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
### Added
|
||||
- Vim bindings in the input via CodeMirror 6 + `@replit/codemirror-vim` (loaded from esm.sh, no build step). Supports `i`/`Esc`, `hjkl`, word/line motions, `dd`/`yy`/`p`, undo/redo, `/` search, `:` command line. Auto-disabled on touch devices (detected via `(pointer: coarse)`) where modal editing fights the virtual keyboard.
|
||||
- `Shift-H` / `Shift-L` cycle focus across the page controls (source → target → model → editor → button) like `Shift-Tab` / `Tab`. Also overridden in vim normal mode (replacing vim's viewport-top/bottom default) so the same shortcut works to leave the editor.
|
||||
- `p` / `P` in vim normal mode paste from the system clipboard at / before the cursor (vim's default registers are skipped — the realistic source for a translator is another app, not an in-editor yank).
|
||||
- On page load, the model dropdown defaults to whichever model Ollama already has hot — skips the 5-15 s disk-reload pain on the first translation. After load it follows the user's manual selection.
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user