feat(editor): add configurable line comment shortcut
This commit is contained in:
parent
184e235999
commit
5a9ab5c036
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -3041,6 +3041,7 @@ export default {
|
|||
shortcutSaveSql: "Save SQL",
|
||||
shortcutAcceptCompletion: "Accept completion",
|
||||
shortcutFormatSql: "Format SQL",
|
||||
shortcutToggleLineComment: "Toggle line comment",
|
||||
shortcutIndentMore: "Indent more",
|
||||
shortcutIndentLess: "Indent less",
|
||||
shortcutDuplicateLine: "Duplicate current line",
|
||||
|
|
@ -3086,6 +3087,8 @@ export default {
|
|||
shortcutScopeSearch: "Search fields",
|
||||
shortcutScopeSidebar: "Sidebar",
|
||||
shortcutPressShortcut: "Press shortcut",
|
||||
shortcutSearchPlaceholder: "Search shortcuts",
|
||||
shortcutSearchNoResults: "No shortcuts match your search.",
|
||||
shortcutConflict: "This shortcut conflicts with another action in the same scope.",
|
||||
shortcutClear: "Clear shortcut",
|
||||
preview: "Live Preview",
|
||||
|
|
|
|||
|
|
@ -2952,6 +2952,7 @@ export default withEnglishFallback({
|
|||
shortcutSaveSql: "Guardar SQL",
|
||||
shortcutAcceptCompletion: "Aceptar completado",
|
||||
shortcutFormatSql: "Formatear SQL",
|
||||
shortcutToggleLineComment: "Alternar comentario de línea",
|
||||
shortcutIndentMore: "Aumentar sangría",
|
||||
shortcutIndentLess: "Reducir sangría",
|
||||
shortcutDuplicateLine: "Duplicar línea actual",
|
||||
|
|
@ -2997,6 +2998,8 @@ export default withEnglishFallback({
|
|||
shortcutScopeSearch: "Campos de búsqueda",
|
||||
shortcutScopeSidebar: "Barra lateral",
|
||||
shortcutPressShortcut: "Presiona un atajo",
|
||||
shortcutSearchPlaceholder: "Buscar atajos",
|
||||
shortcutSearchNoResults: "Ningún atajo coincide con la búsqueda.",
|
||||
shortcutConflict: "Este atajo entra en conflicto con otra acción del mismo ámbito.",
|
||||
shortcutClear: "Borrar atajo",
|
||||
preview: "Vista previa en tiempo real",
|
||||
|
|
|
|||
|
|
@ -2950,6 +2950,7 @@ export default withEnglishFallback({
|
|||
shortcutSaveSql: "Salva SQL",
|
||||
shortcutAcceptCompletion: "Accetta completamento",
|
||||
shortcutFormatSql: "Formatta SQL",
|
||||
shortcutToggleLineComment: "Attiva/disattiva commento di riga",
|
||||
shortcutIndentMore: "Aumenta rientro",
|
||||
shortcutIndentLess: "Riduci rientro",
|
||||
shortcutDuplicateLine: "Duplica riga corrente",
|
||||
|
|
@ -2995,6 +2996,8 @@ export default withEnglishFallback({
|
|||
shortcutScopeSearch: "Cerca campi",
|
||||
shortcutScopeSidebar: "Barra laterale",
|
||||
shortcutPressShortcut: "Premi scorciatoia",
|
||||
shortcutSearchPlaceholder: "Cerca scorciatoie",
|
||||
shortcutSearchNoResults: "Nessuna scorciatoia corrisponde alla ricerca.",
|
||||
shortcutConflict: "Questa scorciatoia è in conflitto con un'altra azione nello stesso ambito.",
|
||||
shortcutClear: "Cancella scorciatoia",
|
||||
preview: "Anteprima in tempo reale",
|
||||
|
|
|
|||
|
|
@ -2934,6 +2934,7 @@ export default withEnglishFallback({
|
|||
shortcutSaveSql: "SQLを保存",
|
||||
shortcutAcceptCompletion: "補完を受け入れる",
|
||||
shortcutFormatSql: "SQLをフォーマット",
|
||||
shortcutToggleLineComment: "行コメントを切り替え",
|
||||
shortcutIndentMore: "インデントを増やす",
|
||||
shortcutIndentLess: "インデントを減らす",
|
||||
shortcutDuplicateLine: "現在行を複製",
|
||||
|
|
@ -2979,6 +2980,8 @@ export default withEnglishFallback({
|
|||
shortcutScopeSearch: "フィールド検索",
|
||||
shortcutScopeSidebar: "サイドバー",
|
||||
shortcutPressShortcut: "ショートカットを押してください",
|
||||
shortcutSearchPlaceholder: "ショートカットを検索",
|
||||
shortcutSearchNoResults: "一致するショートカットはありません。",
|
||||
shortcutConflict: "このショートカットは同じスコープ内の別のアクションと競合しています。",
|
||||
shortcutClear: "ショートカットをクリア",
|
||||
preview: "ライブプレビュー",
|
||||
|
|
|
|||
|
|
@ -2951,6 +2951,7 @@ export default withEnglishFallback({
|
|||
shortcutSaveSql: "Salvar SQL",
|
||||
shortcutAcceptCompletion: "Aceitar autocompletar",
|
||||
shortcutFormatSql: "Formatar SQL",
|
||||
shortcutToggleLineComment: "Alternar comentário de linha",
|
||||
shortcutIndentMore: "Aumentar recuo",
|
||||
shortcutIndentLess: "Reduzir recuo",
|
||||
shortcutDuplicateLine: "Duplicar linha atual",
|
||||
|
|
@ -2996,6 +2997,8 @@ export default withEnglishFallback({
|
|||
shortcutScopeSearch: "Campos de pesquisa",
|
||||
shortcutScopeSidebar: "Barra lateral",
|
||||
shortcutPressShortcut: "Pressione o atalho",
|
||||
shortcutSearchPlaceholder: "Pesquisar atalhos",
|
||||
shortcutSearchNoResults: "Nenhum atalho corresponde à pesquisa.",
|
||||
shortcutConflict: "Este atalho conflita com outra ação no mesmo escopo.",
|
||||
shortcutClear: "Limpar atalho",
|
||||
preview: "Pré-visualização ao vivo",
|
||||
|
|
|
|||
|
|
@ -3041,6 +3041,7 @@ export default withEnglishFallback({
|
|||
shortcutSaveSql: "保存 SQL",
|
||||
shortcutAcceptCompletion: "接受补全",
|
||||
shortcutFormatSql: "格式化 SQL",
|
||||
shortcutToggleLineComment: "切换行注释",
|
||||
shortcutIndentMore: "增加缩进",
|
||||
shortcutIndentLess: "减少缩进",
|
||||
shortcutDuplicateLine: "复制当前行",
|
||||
|
|
@ -3089,6 +3090,8 @@ export default withEnglishFallback({
|
|||
shortcutScopeSearch: "搜索框",
|
||||
shortcutScopeSidebar: "侧边栏",
|
||||
shortcutPressShortcut: "按下快捷键",
|
||||
shortcutSearchPlaceholder: "搜索快捷键",
|
||||
shortcutSearchNoResults: "没有匹配的快捷键。",
|
||||
shortcutConflict: "这个快捷键与同一作用域内的其他操作冲突。",
|
||||
shortcutClear: "清除快捷键",
|
||||
preview: "实时预览",
|
||||
|
|
|
|||
|
|
@ -2838,6 +2838,7 @@ export default withEnglishFallback({
|
|||
shortcutSaveSql: "儲存 SQL",
|
||||
shortcutAcceptCompletion: "接受補全",
|
||||
shortcutFormatSql: "格式化 SQL",
|
||||
shortcutToggleLineComment: "切換行註解",
|
||||
shortcutIndentMore: "增加縮排",
|
||||
shortcutIndentLess: "減少縮排",
|
||||
shortcutDuplicateLine: "複製目前行",
|
||||
|
|
@ -2883,6 +2884,8 @@ export default withEnglishFallback({
|
|||
shortcutScopeSearch: "搜尋框",
|
||||
shortcutScopeSidebar: "側邊欄",
|
||||
shortcutPressShortcut: "按下快速鍵",
|
||||
shortcutSearchPlaceholder: "搜尋快速鍵",
|
||||
shortcutSearchNoResults: "沒有符合的快速鍵。",
|
||||
shortcutConflict: "這個快速鍵與同一作用域內的其他操作衝突。",
|
||||
shortcutClear: "清除快速鍵",
|
||||
preview: "即時預覽",
|
||||
|
|
|
|||
|
|
@ -34,4 +34,8 @@ describe("shortcut display", () => {
|
|||
expect(formatShortcutDisplay("Mod+Plus", "Win32")).toBe("Ctrl + +");
|
||||
expect(formatShortcutDisplay("Shift+Mod++", "Win32")).toBe("Ctrl + Shift + +");
|
||||
});
|
||||
|
||||
it("displays multi-stroke shortcuts", () => {
|
||||
expect(formatShortcutDisplay("Ctrl+K Ctrl+C", "Win32")).toBe("Ctrl + K, Ctrl + C");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,24 @@ import { describe, expect, it } from "vitest";
|
|||
import { DEFAULT_SHORTCUT_SETTINGS, SHORTCUT_DEFINITIONS, findShortcutConflict, formatShortcut, normalizeShortcutSettings, shortcutToCodeMirrorKey, type ShortcutActionId } from "@/lib/editor/shortcutRegistry";
|
||||
|
||||
describe("shortcutRegistry editor actions", () => {
|
||||
const formatterEditorActionIds: ShortcutActionId[] = ["formatSql", "indentMore", "indentLess", "duplicateLine", "deleteLine", "moveLineUp", "moveLineDown", "copyLineUp", "copyLineDown", "undo", "redo", "selectAll", "uppercaseSelection", "lowercaseSelection", "exPasteSqlInCondition"];
|
||||
const formatterEditorActionIds: ShortcutActionId[] = [
|
||||
"formatSql",
|
||||
"toggleLineComment",
|
||||
"indentMore",
|
||||
"indentLess",
|
||||
"duplicateLine",
|
||||
"deleteLine",
|
||||
"moveLineUp",
|
||||
"moveLineDown",
|
||||
"copyLineUp",
|
||||
"copyLineDown",
|
||||
"undo",
|
||||
"redo",
|
||||
"selectAll",
|
||||
"uppercaseSelection",
|
||||
"lowercaseSelection",
|
||||
"exPasteSqlInCondition",
|
||||
];
|
||||
const sidebarShortcutActionIds: ShortcutActionId[] = ["copySidebarSelection", "pasteSidebarSelection", "editSidebarConnection"];
|
||||
|
||||
it("registers formatter editor shortcuts in the generic editor scope", () => {
|
||||
|
|
@ -19,6 +36,7 @@ describe("shortcutRegistry editor actions", () => {
|
|||
|
||||
expect(shortcuts.executeSql).toBe("Mod+Shift+Enter");
|
||||
expect(shortcuts.formatSql).toBe("Shift+Mod+F");
|
||||
expect(shortcuts.toggleLineComment).toBe("Mod+/");
|
||||
expect(shortcuts.indentMore).toBe("");
|
||||
expect(shortcuts.indentLess).toBe("Shift+Tab");
|
||||
expect(shortcuts.duplicateLine).toBe("Mod+D");
|
||||
|
|
@ -71,4 +89,12 @@ describe("shortcutRegistry editor actions", () => {
|
|||
expect(shortcutToCodeMirrorKey("Mod+Plus")).toBe("Mod-+");
|
||||
expect(shortcutToCodeMirrorKey("Shift+Mod++")).toBe("Shift-Mod-+");
|
||||
});
|
||||
|
||||
it("converts slash shortcuts for CodeMirror keymaps", () => {
|
||||
expect(shortcutToCodeMirrorKey("Mod+/")).toBe("Mod-/");
|
||||
});
|
||||
|
||||
it("converts multi-stroke shortcuts for CodeMirror keymaps", () => {
|
||||
expect(shortcutToCodeMirrorKey("Ctrl+K Ctrl+C")).toBe("Ctrl-k Ctrl-c");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ export function parseShortcutParts(shortcut?: string): string[] {
|
|||
return shortcut.split("+").filter(Boolean);
|
||||
}
|
||||
|
||||
export function parseShortcutStrokes(shortcut?: string): string[][] {
|
||||
if (!shortcut) return [];
|
||||
return shortcut.trim().split(/\s+/).filter(Boolean).map(parseShortcutParts);
|
||||
}
|
||||
|
||||
function shortcutDisplayOrder(parts: string[], platform = globalThis.navigator?.platform || ""): string[] {
|
||||
if (parts.length <= 2 || isMacShortcutPlatform(platform)) return parts;
|
||||
|
||||
|
|
@ -43,6 +48,10 @@ export function shortcutDisplayParts(shortcut?: string, platform = globalThis.na
|
|||
return shortcutDisplayOrder(parseShortcutParts(shortcut), platform);
|
||||
}
|
||||
|
||||
export function shortcutDisplayStrokes(shortcut?: string, platform = globalThis.navigator?.platform || ""): string[][] {
|
||||
return parseShortcutStrokes(shortcut).map((parts) => shortcutDisplayOrder(parts, platform));
|
||||
}
|
||||
|
||||
export function shortcutKeyLabel(part: string, platform = globalThis.navigator?.platform || ""): string {
|
||||
const isMac = isMacShortcutPlatform(platform);
|
||||
if (part === "Mod") return isMac ? "⌘" : "Ctrl";
|
||||
|
|
@ -65,10 +74,15 @@ export function shortcutKeyLabel(part: string, platform = globalThis.navigator?.
|
|||
}
|
||||
|
||||
export function shortcutDisplayKeys(shortcut?: string, platform = globalThis.navigator?.platform || ""): string[] {
|
||||
return shortcutDisplayParts(shortcut, platform).map((part) => shortcutKeyLabel(part, platform));
|
||||
return shortcutDisplayStrokes(shortcut, platform)
|
||||
.flat()
|
||||
.map((part) => shortcutKeyLabel(part, platform));
|
||||
}
|
||||
|
||||
export function formatShortcutDisplay(shortcut: string, platform = globalThis.navigator?.platform || ""): string {
|
||||
if (!shortcut) return "—";
|
||||
return shortcutDisplayKeys(shortcut, platform).join(isMacShortcutPlatform(platform) ? " " : " + ");
|
||||
const keySeparator = isMacShortcutPlatform(platform) ? " " : " + ";
|
||||
return shortcutDisplayStrokes(shortcut, platform)
|
||||
.map((parts) => parts.map((part) => shortcutKeyLabel(part, platform)).join(keySeparator))
|
||||
.join(", ");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { parseShortcutParts, shortcutDisplayParts } from "@/lib/editor/shortcutDisplay";
|
||||
import { parseShortcutStrokes, shortcutDisplayParts } from "@/lib/editor/shortcutDisplay";
|
||||
|
||||
export type ShortcutActionId =
|
||||
| "executeSql"
|
||||
| "formatSql"
|
||||
| "toggleLineComment"
|
||||
| "saveSql"
|
||||
| "acceptCompletion"
|
||||
| "indentMore"
|
||||
|
|
@ -74,6 +75,12 @@ export const SHORTCUT_DEFINITIONS: ShortcutDefinition[] = [
|
|||
scope: "editor",
|
||||
defaultShortcut: "Shift+Mod+F",
|
||||
},
|
||||
{
|
||||
id: "toggleLineComment",
|
||||
labelKey: "settings.shortcutToggleLineComment",
|
||||
scope: "editor",
|
||||
defaultShortcut: "Mod+/",
|
||||
},
|
||||
{
|
||||
id: "saveSql",
|
||||
labelKey: "settings.shortcutSaveSql",
|
||||
|
|
@ -359,10 +366,14 @@ export function normalizeShortcutSettings(settings?: Partial<ShortcutSettings>):
|
|||
}
|
||||
|
||||
export function shortcutToCodeMirrorKey(shortcut: string): string {
|
||||
return parseShortcutParts(shortcut)
|
||||
.map((part) => (part.length === 1 ? part.toLowerCase() : part))
|
||||
.map((part) => (part === "Plus" ? "+" : part))
|
||||
.join("-");
|
||||
return parseShortcutStrokes(shortcut)
|
||||
.map((parts) =>
|
||||
parts
|
||||
.map((part) => (part.length === 1 ? part.toLowerCase() : part))
|
||||
.map((part) => (part === "Plus" ? "+" : part))
|
||||
.join("-"),
|
||||
)
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
export function formatShortcut(shortcut: string, platform = globalThis.navigator?.platform || ""): string {
|
||||
|
|
|
|||
Loading…
Reference in New Issue