diff --git a/src/app/(windows)/QueryWindow.tsx b/src/app/(windows)/QueryWindow.tsx index 265d6564..d0da2c6e 100644 --- a/src/app/(windows)/QueryWindow.tsx +++ b/src/app/(windows)/QueryWindow.tsx @@ -15,6 +15,7 @@ import { useAutoComplete } from "@/context/AutoCompleteProvider"; import { MultipleQueryProgress, multipleQuery } from "@/lib/multiple-query"; import QueryProgressLog from "../(components)/QueryProgressLog"; import OptimizeTableState from "../(components)/OptimizeTable/OptimizeTableState"; +import { KEY_BINDING } from "@/lib/key-matcher"; export default function QueryWindow() { const { schema } = useAutoComplete(); @@ -44,19 +45,34 @@ export default function QueryWindow() { .catch(console.error); }; + console.log(KEY_BINDING.run.toCodeMirrorKey()); + return (
- + { + if (KEY_BINDING.run.match(e)) { + onRunClicked(); + e.preventDefault(); + } + }} + />
-
+
diff --git a/src/components/SqlEditor.tsx b/src/components/SqlEditor.tsx index fa576c77..8fe153e7 100644 --- a/src/components/SqlEditor.tsx +++ b/src/components/SqlEditor.tsx @@ -2,6 +2,11 @@ import { tags as t } from "@lezer/highlight"; import { createTheme } from "@uiw/codemirror-themes"; import CodeMirror from "@uiw/react-codemirror"; import { sql, SQLite } from "@codemirror/lang-sql"; +import { KeyboardEventHandler, useMemo } from "react"; + +import { defaultKeymap } from "@codemirror/commands"; +import { keymap } from "@codemirror/view"; +import { KEY_BINDING } from "@/lib/key-matcher"; const theme = createTheme({ theme: "light", @@ -39,12 +44,34 @@ interface SqlEditorProps { value: string; onChange: (value: string) => void; schema?: Record; + onKeyDown?: KeyboardEventHandler; } -export default function SqlEditor({ value, onChange, schema }: SqlEditorProps) { +export default function SqlEditor({ + value, + onChange, + schema, + onKeyDown, +}: SqlEditorProps) { + const keyExtensions = useMemo(() => { + return keymap.of([ + { + key: KEY_BINDING.run.toCodeMirrorKey(), + preventDefault: true, + run: () => true, + }, + ...defaultKeymap, + ]); + }, []); + return ( ) { + let isMatched = true; + const isCtrlKey = e.ctrlKey || e.metaKey; + + if (this.key.ctrl && !isCtrlKey) { + isMatched = false; + } + + if (this.key.key && e.key !== this.key.key) { + isMatched = false; + } + + if (this.key.shift && !e.shiftKey) { + isMatched = false; + } + + return isMatched; + } + + toJson(): KeyMatcherProps { + return { ...this.key }; + } + + toString() { + const isMac = navigator.userAgent.toLowerCase().indexOf("mac") > -1; + return [ + this.key.ctrl ? (isMac ? "⌘" : "Ctrl") : undefined, + this.key.shift ? "Shift" : undefined, + this.key?.key?.toUpperCase(), + ] + .filter(Boolean) + .join(" + "); + } + + toCodeMirrorKey() { + const isMac = navigator.userAgent.toLowerCase().indexOf("mac") > -1; + return [ + this.key.ctrl ? (isMac ? "Cmd" : "Ctrl") : undefined, + this.key.shift ? "Shift" : undefined, + this.key?.key, + ] + .filter(Boolean) + .join("-"); + } +} + +export const KEY_BINDING = { + run: new KeyMatcher({ ctrl: true, key: "Enter" }), +};