From 427acc420c6fce10fa77e603f7696f3e89d342d6 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Thu, 22 Oct 2026 01:43:35 +0000 Subject: feat(bundle): add platform-adaptive file, find and comment shortcuts New, Open, Save and Find are Monaco KeyMod.CtrlCmd bindings matched with StandardKeyboardEvent, so they use Cmd on macOS and Ctrl on Windows and Linux, exactly like the editor's own keybindings. Find also works from Input and Output by focusing the editor first. Toggle Line Comment comes from Monaco's comment contribution and the plugin's "//" lineComment. This replaces the Save handler that accepted Ctrl or Cmd with any other modifiers on every platform. Co-Authored-By: Claude Opus 5.5 --- bundle/src/main.js | 60 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'bundle/src/main.js') diff --git a/bundle/src/main.js b/bundle/src/main.js index 56cbff6..b71ed27 100644 --- a/bundle/src/main.js +++ b/bundle/src/main.js @@ -1,6 +1,8 @@ import { invoke, Channel } from '@tauri-apps/api/core'; import { getCurrentWindow } from '@tauri-apps/api/window'; import { open, save, message } from '@tauri-apps/plugin-dialog'; +import { KeyCode, KeyMod } from 'monaco-editor/editor/editor.api.js'; +import { StandardKeyboardEvent } from 'monaco-editor/base/browser/keyboardEvent.js'; import { createEditor } from './editor.js'; import './style.css'; @@ -96,11 +98,37 @@ async function canReplace() { if (answer === 'Cancel') return false; return answer === 'Discard' || await saveFile(); } +async function newFile() { + if (!await canReplace()) return; + path = null; + savedText = ''; + editor.setValue(''); + refreshTitle(); + status.textContent = 'Ready'; +} +async function openFile() { + if (!await canReplace()) return; + const target = await open({ filters, multiple: false }); + if (!target) return; + const text = await invoke('read_file', { path: target }); + path = target; + savedText = text; + editor.setValue(text); + refreshTitle(); + status.textContent = 'Ready'; +} async function action(callback) { if (busy || running) return; busy = true; try { await callback(); } catch (error) { report(error); } finally { busy = false; } } +// CtrlCmd is Cmd on macOS and Ctrl elsewhere, matching Monaco's own keybindings. +const shortcuts = [ + [KeyMod.CtrlCmd | KeyCode.KeyN, () => action(newFile)], + [KeyMod.CtrlCmd | KeyCode.KeyO, () => action(openFile)], + [KeyMod.CtrlCmd | KeyCode.KeyS, () => action(saveFile)], + [KeyMod.CtrlCmd | KeyCode.KeyF, () => { editor.focus(); editor.getAction('actions.find').run(); }] +]; try { editor = await createEditor(document.querySelector('#editor')); @@ -113,30 +141,16 @@ try { } }; document.querySelector('#save').onclick = () => action(saveFile); - document.querySelector('#new').onclick = () => action(async () => { - if (!await canReplace()) return; - path = null; - savedText = ''; - editor.setValue(''); - refreshTitle(); - status.textContent = 'Ready'; - }); - document.querySelector('#open').onclick = () => action(async () => { - if (!await canReplace()) return; - const target = await open({ filters, multiple: false }); - if (!target) return; - const text = await invoke('read_file', { path: target }); - path = target; - savedText = text; - editor.setValue(text); - refreshTitle(); - status.textContent = 'Ready'; - }); + document.querySelector('#new').onclick = () => action(newFile); + document.querySelector('#open').onclick = () => action(openFile); document.addEventListener('keydown', event => { - if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') { - event.preventDefault(); - action(saveFile); - } + // Monaco already handled its own keybindings, such as Find inside the editor. + if (event.defaultPrevented) return; + const key = new StandardKeyboardEvent(event); + const shortcut = shortcuts.find(([binding]) => key.equals(binding)); + if (!shortcut) return; + event.preventDefault(); + shortcut[1](); }); await window.onCloseRequested(async event => { if (closing) return; -- cgit v1.3.1-4-g156e