feat(editor): add configurable line comment shortcut
This commit is contained in:
1 parent
184e235999
commit
5a9ab5c036
13 files changed
+109
-11
No files matched your search
@@ -3,7 +3,7 @@ import { ref, watch, shallowRef, computed, onMounted, onUnmounted, nextTick } fr
|
||||
import type { Ref } from "vue";
|
||||
import type { EditorView as EditorViewType } from "@codemirror/view";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { AlertTriangle, CheckCircle2, CircleHelp, Cloud, Copy, Download, ExternalLink, GripVertical, Loader2, Moon, PackageSearch, Pencil, Plus, RefreshCw, RotateCcw, Settings, Sun, SunMoon, Terminal, Trash2, Upload, X } from "@lucide/vue";
|
||||
import { AlertTriangle, CheckCircle2, CircleHelp, Cloud, Copy, Download, ExternalLink, GripVertical, Loader2, Moon, PackageSearch, Pencil, Plus, RefreshCw, RotateCcw, Search, Settings, Sun, SunMoon, Terminal, Trash2, Upload, X } from "@lucide/vue";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
@@ -617,8 +617,10 @@ const shortcutConflicts = computed(() =>
|
||||
return conflict ? [definition.id] : [];
|
||||
}),
|
||||
);
|
||||
const shortcutSearchQuery = ref("");
|
||||
const formatterEditorShortcutIds: ShortcutActionId[] = [
|
||||
"formatSql",
|
||||
"toggleLineComment",
|
||||
"find",
|
||||
"replace",
|
||||
"saveSql",
|
||||
@@ -638,6 +640,15 @@ const formatterEditorShortcutIds: ShortcutActionId[] = [
|
||||
"lowercaseSelection",
|
||||
];
|
||||
const formatterEditorShortcutDefinitions = computed(() => formatterEditorShortcutIds.map((id) => SHORTCUT_DEFINITIONS.find((definition) => definition.id === id)).filter((definition): definition is (typeof SHORTCUT_DEFINITIONS)[number] => !!definition));
|
||||
const filteredShortcutDefinitions = computed(() => {
|
||||
const query = shortcutSearchQuery.value.trim().toLowerCase();
|
||||
if (!query) return SHORTCUT_DEFINITIONS;
|
||||
return SHORTCUT_DEFINITIONS.filter((definition) => {
|
||||
const scope = t(`settings.shortcutScope${definition.scope[0].toUpperCase()}${definition.scope.slice(1)}`);
|
||||
const shortcut = formatShortcutPill(editShortcuts.value[definition.id]);
|
||||
return [definition.id, t(definition.labelKey), scope, shortcut].some((value) => value.toLowerCase().includes(query));
|
||||
});
|
||||
});
|
||||
const hasShortcutConflicts = computed(() => shortcutConflicts.value.length > 0);
|
||||
const shortcutsChanged = computed(() => JSON.stringify(editShortcuts.value) !== JSON.stringify(settingsStore.editorSettings.shortcuts));
|
||||
const duckDbWorkerSettingsRequireRestart = computed(() => editDuckDbWorkerProcessIsolation.value !== startupDuckDbWorkerProcessIsolation.value || normalizeDuckDbWorkerMaxProcesses(editDuckDbWorkerMaxProcesses.value) !== startupDuckDbWorkerMaxProcesses.value);
|
||||
@@ -3407,8 +3418,15 @@ onUnmounted(cleanupPreviewEditor);
|
||||
</section>
|
||||
|
||||
<section v-else-if="activeSettingsTab === 'shortcuts'" class="flex flex-col gap-2 py-2">
|
||||
<div class="relative">
|
||||
<Search class="pointer-events-none absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input v-model="shortcutSearchQuery" autocomplete="off" :placeholder="t('settings.shortcutSearchPlaceholder')" class="h-9 pl-9 text-sm" />
|
||||
</div>
|
||||
<div class="overflow-hidden rounded-md border border-border/70 bg-background">
|
||||
<div v-for="definition in SHORTCUT_DEFINITIONS" :key="definition.id" class="group -mt-px grid gap-2 border-t border-border/70 px-3 py-2 transition-colors first:mt-0 first:border-t-0 hover:bg-muted/40 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-center">
|
||||
<div v-if="filteredShortcutDefinitions.length === 0" class="px-3 py-8 text-center text-sm text-muted-foreground">
|
||||
{{ t("settings.shortcutSearchNoResults") }}
|
||||
</div>
|
||||
<div v-for="definition in filteredShortcutDefinitions" :key="definition.id" class="group -mt-px grid gap-2 border-t border-border/70 px-3 py-2 transition-colors first:mt-0 first:border-t-0 hover:bg-muted/40 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-center">
|
||||
<div class="min-w-0">
|
||||
<div class="flex min-w-0 items-center gap-2">
|
||||
<Label class="min-w-0 truncate leading-none">{{ t(definition.labelKey) }}</Label>
|
||||
|
||||
@@ -231,6 +231,7 @@ let codeMirrorUndo: typeof import("@codemirror/commands").undo | null = null;
|
||||
let codeMirrorRedo: typeof import("@codemirror/commands").redo | null = null;
|
||||
let codeMirrorSelectAll: typeof import("@codemirror/commands").selectAll | null = null;
|
||||
let codeMirrorInsertNewlineKeepIndent: typeof import("@codemirror/commands").insertNewlineKeepIndent | null = null;
|
||||
let codeMirrorToggleLineComment: typeof import("@codemirror/commands").toggleLineComment | null = null;
|
||||
let setSqlDiagnosticsEffect: import("@codemirror/state").StateEffectType<SqlSemanticDiagnostic[]> | null = null;
|
||||
let setPreviewRangeEffect: import("@codemirror/state").StateEffectType<{ from: number; to: number } | null> | null = null;
|
||||
let previewRangeComp: import("@codemirror/state").Compartment | null = null;
|
||||
@@ -932,6 +933,7 @@ function runKeymapExtension(codeMirrorKeymap: (typeof import("@codemirror/view")
|
||||
...binding(shortcuts.selectAll, (view) => codeMirrorSelectAll?.(view) ?? false),
|
||||
...binding(shortcuts.uppercaseSelection, () => convertSelectedSqlCase("upper")),
|
||||
...binding(shortcuts.lowercaseSelection, () => convertSelectedSqlCase("lower")),
|
||||
...binding(shortcuts.toggleLineComment, (view) => codeMirrorToggleLineComment?.(view) ?? false),
|
||||
...binding(shortcuts.exPasteSqlInCondition, () => {
|
||||
if (!supportsSqlInListPaste(props.databaseType)) return false;
|
||||
void pasteClipboardAsSqlInCondition();
|
||||
@@ -2464,7 +2466,7 @@ onMounted(async () => {
|
||||
{ EditorState, EditorSelection, Compartment, Prec, StateEffect, StateField },
|
||||
langSql,
|
||||
{ autocompletion, startCompletion, acceptCompletion, closeBrackets, closeBracketsKeymap, snippetCompletion, completionStatus, completionKeymap, insertCompletionText, nextSnippetField },
|
||||
{ copyLineDown, copyLineUp, deleteLine, indentLess, indentMore, insertNewlineKeepIndent, moveLineDown, moveLineUp, redo, selectAll, undo, history, defaultKeymap, historyKeymap },
|
||||
{ copyLineDown, copyLineUp, deleteLine, indentLess, indentMore, insertNewlineKeepIndent, moveLineDown, moveLineUp, redo, selectAll, undo, toggleLineComment, history, defaultKeymap, historyKeymap },
|
||||
{ bracketMatching, foldGutter, indentOnInput, indentUnit, syntaxHighlighting, defaultHighlightStyle, foldKeymap },
|
||||
{ searchKeymap },
|
||||
] = await Promise.all([import("@codemirror/view"), import("@codemirror/state"), import("@codemirror/lang-sql"), import("@codemirror/autocomplete"), import("@codemirror/commands"), import("@codemirror/language"), import("@codemirror/search")]);
|
||||
@@ -2500,6 +2502,7 @@ onMounted(async () => {
|
||||
codeMirrorRedo = redo;
|
||||
codeMirrorSelectAll = selectAll;
|
||||
codeMirrorInsertNewlineKeepIndent = insertNewlineKeepIndent;
|
||||
codeMirrorToggleLineComment = toggleLineComment;
|
||||
codeMirrorIndentUnit = indentUnit;
|
||||
window.addEventListener("keyup", clearTableNavigationHoverOnModifierRelease);
|
||||
window.addEventListener("blur", clearTableNavigationHover);
|
||||
@@ -2725,6 +2728,7 @@ onMounted(async () => {
|
||||
dropCursor(),
|
||||
EditorView.dragMovesSelection.of((event) => !event.ctrlKey && !event.metaKey),
|
||||
EditorState.allowMultipleSelections.of(true),
|
||||
EditorView.clickAddsSelectionRange.of((event) => event.altKey && event.button === 0),
|
||||
indentOnInput(),
|
||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||
crosshairCursor(),
|
||||
|
||||
Reference in new issue
Block a user