feat(editor): add auto close brackets setting

This commit is contained in:
gggaiitx authored and GitHub committed 2026-07-09 09:53:01 +08:00
1 parent 1670fac285
commit 2f134585ea
12 files changed
+145 -4

No files matched your search

@@ -247,6 +247,7 @@ const editShowCurrentStatementFrame = ref(settingsStore.editorSettings.showCurre
const editAutoAliasTables = ref(settingsStore.editorSettings.autoAliasTables);
const editWordWrap = ref(settingsStore.editorSettings.wordWrap);
const editVimModeEnabled = ref(settingsStore.editorSettings.vimModeEnabled);
const editAutoCloseBrackets = ref(settingsStore.editorSettings.autoCloseBrackets);
const editSqlSemanticDiagnosticsMode = ref<SqlSemanticDiagnosticsMode>(settingsStore.editorSettings.sqlSemanticDiagnosticsMode);
const editSqlSemanticDiagnosticsEnabled = ref(settingsStore.editorSettings.sqlSemanticDiagnosticsEnabled);
const editConfirmDangerousSqlExecution = ref(settingsStore.editorSettings.confirmDangerousSqlExecution);
@@ -570,6 +571,7 @@ watch(
editAutoAliasTables.value = settingsStore.editorSettings.autoAliasTables;
editWordWrap.value = settingsStore.editorSettings.wordWrap;
editVimModeEnabled.value = settingsStore.editorSettings.vimModeEnabled;
editAutoCloseBrackets.value = settingsStore.editorSettings.autoCloseBrackets;
editSqlSemanticDiagnosticsMode.value = settingsStore.editorSettings.sqlSemanticDiagnosticsMode;
editSqlSemanticDiagnosticsEnabled.value = settingsStore.editorSettings.sqlSemanticDiagnosticsEnabled;
editConfirmDangerousSqlExecution.value = settingsStore.editorSettings.confirmDangerousSqlExecution;
@@ -675,6 +677,7 @@ function hasChanges(): boolean {
editAutoAliasTables.value !== settingsStore.editorSettings.autoAliasTables ||
editWordWrap.value !== settingsStore.editorSettings.wordWrap ||
editVimModeEnabled.value !== settingsStore.editorSettings.vimModeEnabled ||
editAutoCloseBrackets.value !== settingsStore.editorSettings.autoCloseBrackets ||
editSqlSemanticDiagnosticsMode.value !== settingsStore.editorSettings.sqlSemanticDiagnosticsMode ||
editSqlSemanticDiagnosticsEnabled.value !== settingsStore.editorSettings.sqlSemanticDiagnosticsEnabled ||
editConfirmDangerousSqlExecution.value !== settingsStore.editorSettings.confirmDangerousSqlExecution ||
@@ -736,6 +739,7 @@ async function persistSettings() {
autoAliasTables: editAutoAliasTables.value,
wordWrap: editWordWrap.value,
vimModeEnabled: editVimModeEnabled.value,
autoCloseBrackets: editAutoCloseBrackets.value,
sqlSemanticDiagnosticsMode: editSqlSemanticDiagnosticsMode.value,
confirmDangerousSqlExecution: editConfirmDangerousSqlExecution.value,
confirmUnsavedSqlClose: editConfirmUnsavedSqlClose.value,
@@ -820,6 +824,7 @@ function resetDefaultsForTab(tab: SettingsCategory) {
editAutoAliasTables.value = DEFAULT_EDITOR_SETTINGS.autoAliasTables;
editWordWrap.value = DEFAULT_EDITOR_SETTINGS.wordWrap;
editVimModeEnabled.value = DEFAULT_EDITOR_SETTINGS.vimModeEnabled;
editAutoCloseBrackets.value = DEFAULT_EDITOR_SETTINGS.autoCloseBrackets;
editSqlSemanticDiagnosticsMode.value = DEFAULT_EDITOR_SETTINGS.sqlSemanticDiagnosticsMode;
editSqlSemanticDiagnosticsEnabled.value = DEFAULT_EDITOR_SETTINGS.sqlSemanticDiagnosticsEnabled;
editConfirmDangerousSqlExecution.value = DEFAULT_EDITOR_SETTINGS.confirmDangerousSqlExecution;
@@ -891,6 +896,7 @@ function resetAllDefaults() {
editAutoAliasTables.value = DEFAULT_EDITOR_SETTINGS.autoAliasTables;
editWordWrap.value = DEFAULT_EDITOR_SETTINGS.wordWrap;
editVimModeEnabled.value = DEFAULT_EDITOR_SETTINGS.vimModeEnabled;
editAutoCloseBrackets.value = DEFAULT_EDITOR_SETTINGS.autoCloseBrackets;
editSqlSemanticDiagnosticsMode.value = DEFAULT_EDITOR_SETTINGS.sqlSemanticDiagnosticsMode;
editSqlSemanticDiagnosticsEnabled.value = DEFAULT_EDITOR_SETTINGS.sqlSemanticDiagnosticsEnabled;
editConfirmDangerousSqlExecution.value = DEFAULT_EDITOR_SETTINGS.confirmDangerousSqlExecution;
@@ -2590,6 +2596,14 @@ onUnmounted(cleanupPreviewEditor);
<Switch id="editor-vim-mode" v-model="editVimModeEnabled" class="mt-0.5" />
</div>
<div class="flex items-center justify-between gap-4 rounded-md border bg-muted/20 px-3 py-2">
<div class="space-y-1">
<Label for="editor-auto-close-brackets">{{ t("settings.autoCloseBrackets") }}</Label>
<p class="text-xs text-muted-foreground">{{ t("settings.autoCloseBracketsDescription") }}</p>
</div>
<Switch id="editor-auto-close-brackets" v-model="editAutoCloseBrackets" class="mt-0.5" />
</div>
<div class="flex items-center justify-between gap-4 rounded-md border bg-muted/20 px-3 py-2">
<div class="space-y-1">
<Label for="editor-auto-alias-tables">{{ t("settings.autoAliasTables") }}</Label>
@@ -202,6 +202,9 @@ let fontThemeComp: import("@codemirror/state").Compartment | null = null;
let codeMirrorTheme: import("@codemirror/state").Compartment | null = null;
let wordWrapComp: import("@codemirror/state").Compartment | null = null;
let vimModeComp: import("@codemirror/state").Compartment | null = null;
let closeBracketsComp: import("@codemirror/state").Compartment | null = null;
let codeMirrorCloseBrackets: typeof import("@codemirror/autocomplete").closeBrackets | null = null;
let codeMirrorCloseBracketsKeymap: readonly import("@codemirror/view").KeyBinding[] | null = null;
let readOnlyComp: import("@codemirror/state").Compartment | null = null;
let runGutterComp: import("@codemirror/state").Compartment | null = null;
let runKeymapComp: import("@codemirror/state").Compartment | null = null;
@@ -287,6 +290,7 @@ const queryEditorAppearanceSettings = computed(() => {
activeCustomThemeId: settings.activeCustomThemeId,
wordWrap: settings.wordWrap,
vimModeEnabled: settings.vimModeEnabled,
autoCloseBrackets: settings.autoCloseBrackets,
showCurrentStatementFrame: settings.showCurrentStatementFrame,
shortcuts: settings.shortcuts,
showStatementRunButtons: settings.showStatementRunButtons,
@@ -965,6 +969,15 @@ function wordWrapExtension() {
return props.forceWordWrap || settingsStore.editorSettings.wordWrap ? editorViewModule.EditorView.lineWrapping : [];
}
function closeBracketsExtension(enabled = settingsStore.editorSettings.autoCloseBrackets) {
if (!enabled || !codeMirrorCloseBrackets) return [];
const exts: import("@codemirror/state").Extension[] = [codeMirrorCloseBrackets()];
if (codeMirrorCloseBracketsKeymap?.length && codeMirrorPrec && editorViewModule) {
exts.push(codeMirrorPrec.highest(editorViewModule.keymap.of([...codeMirrorCloseBracketsKeymap])));
}
return exts;
}
function vimModeExtension(enabled = settingsStore.editorSettings.vimModeEnabled) {
if (!codeMirrorVim || !enabled) return [];
const vimExtension = codeMirrorVim({ status: true });
@@ -2492,6 +2505,9 @@ onMounted(async () => {
codeMirrorTheme = new Compartment();
wordWrapComp = new Compartment();
vimModeComp = new Compartment();
closeBracketsComp = new Compartment();
codeMirrorCloseBrackets = closeBrackets;
codeMirrorCloseBracketsKeymap = closeBracketsKeymap;
readOnlyComp = new Compartment();
runGutterComp = new Compartment();
runKeymapComp = new Compartment();
@@ -2755,7 +2771,7 @@ onMounted(async () => {
completionComp.of(buildSqlCompletionExtension()),
sqlCompletionTheme(EditorView),
codeMirrorTheme.of(theme),
closeBrackets(),
closeBracketsComp.of(closeBracketsExtension(initialSettings.autoCloseBrackets)),
bracketMatching(),
hoverTooltip((currentView, pos) => resolveSqlHoverTooltip(currentView, pos)),
buildSqlSignatureExtension(),
@@ -2764,7 +2780,6 @@ onMounted(async () => {
Prec.highest(
keymap.of([
{ key: "'", run: handleSqlSingleQuote },
...closeBracketsKeymap,
{ key: "Tab", run: handleTab },
{
key: "Escape",
@@ -3100,7 +3115,7 @@ function getCurrentCustomThemeColors() {
watch(
[queryEditorAppearanceSettings, () => isDark.value, () => themePalette.value],
async ([ss]) => {
if (!view.value || !codeMirrorTheme || !fontThemeComp || !wordWrapComp || !vimModeComp || !runGutterComp || !runKeymapComp || !editorViewModule) {
if (!view.value || !codeMirrorTheme || !fontThemeComp || !wordWrapComp || !vimModeComp || !closeBracketsComp || !runGutterComp || !runKeymapComp || !editorViewModule) {
return;
}
if (!isGestureZooming.value && !zoomCommitScheduler.hasPendingCommit() && liveFontSize.value !== ss.fontSize) {
@@ -3109,7 +3124,7 @@ watch(
syncEditorFontCssVars(liveFontSize.value, ss.fontFamily);
const themeColors = getCurrentCustomThemeColors();
const [themeExt] = await Promise.all([loadEditorTheme(ss.theme, editorThemeAppearance(), themeColors, themePalette.value), ss.vimModeEnabled ? ensureCodeMirrorVim() : Promise.resolve(false)]);
if (!view.value || !codeMirrorTheme || !wordWrapComp || !vimModeComp || !runGutterComp || !runKeymapComp || !editorViewModule) {
if (!view.value || !codeMirrorTheme || !wordWrapComp || !vimModeComp || !closeBracketsComp || !runGutterComp || !runKeymapComp || !editorViewModule) {
return;
}
view.value.dispatch({
@@ -3117,6 +3132,7 @@ watch(
codeMirrorTheme.reconfigure(themeExt),
wordWrapComp.reconfigure(props.forceWordWrap || ss.wordWrap ? editorViewModule.EditorView.lineWrapping : []),
vimModeComp.reconfigure(vimModeExtension(settingsStore.editorSettings.vimModeEnabled)),
closeBracketsComp.reconfigure(closeBracketsExtension(settingsStore.editorSettings.autoCloseBrackets)),
runGutterComp.reconfigure(props.hideExecutionControls ? [] : (buildRunStatementGutterExtension?.() ?? [])),
runKeymapComp.reconfigure(runKeymapExtension(editorViewModule.keymap)),
],
+2
View File
@@ -3088,6 +3088,8 @@ export default {
wordWrapDescription: "Wrap long SQL lines within the editor width",
vimMode: "Vim mode",
vimModeDescription: "Use Vim-style modal editing in the SQL editor",
autoCloseBrackets: "Auto-close brackets",
autoCloseBracketsDescription: "Automatically insert closing brackets and quotes when typing an opening one",
sqlSemanticDiagnosticsEnabled: "SQL semantic diagnostics",
sqlSemanticDiagnosticsEnabledDescription: "When enabled, the editor reports semantic issues such as unknown tables and columns. Disable it to reduce parsing and metadata checks for large SQL.",
confirmDangerousSqlExecution: "Confirm before dangerous SQL",
+2
View File
@@ -2989,6 +2989,8 @@ export default withEnglishFallback({
wordWrapDescription: "Ajustar las líneas largas de SQL al ancho del editor",
vimMode: "Modo Vim",
vimModeDescription: "Usar edición modal estilo Vim en el editor SQL",
autoCloseBrackets: "Cerrar paréntesis automáticamente",
autoCloseBracketsDescription: "Insertar automáticamente paréntesis y comillas de cierre al escribir los de apertura",
sqlSemanticDiagnosticsEnabled: "Diagnóstico semántico de SQL",
sqlSemanticDiagnosticsEnabledDescription: "Al activarse, el editor informa de problemas semánticos como tablas y columnas desconocidas. Desactívalo para reducir el análisis y las comprobaciones de metadatos en SQL grandes.",
confirmDangerousSqlExecution: "Confirmar antes de SQL peligroso",
+2
View File
@@ -2987,6 +2987,8 @@ export default withEnglishFallback({
wordWrapDescription: "Incolonna le righe SQL lunghe entro la larghezza dell'editor",
vimMode: "Modalita Vim",
vimModeDescription: "Usa la modifica modale in stile Vim nell'editor SQL",
autoCloseBrackets: "Chiusura automatica parentesi",
autoCloseBracketsDescription: "Inserisci automaticamente parentesi e virgolette di chiusura quando digiti quelle di apertura",
sqlSemanticDiagnosticsEnabled: "Diagnostica semantica SQL",
sqlSemanticDiagnosticsEnabledDescription: "Se abilitata, l'editor segnala problemi semantici come tabelle e colonne sconosciute. Disabilitala per ridurre l'analisi e i controlli dei metadati per file SQL di grandi dimensioni.",
confirmDangerousSqlExecution: "Conferma prima di SQL pericoloso",
+2
View File
@@ -2978,6 +2978,8 @@ export default withEnglishFallback({
wordWrapDescription: "長いSQL行をエディタ幅内で折り返します",
vimMode: "Vimモード",
vimModeDescription: "SQLエディタでVim形式のモーダル編集を使用します",
autoCloseBrackets: "自動括弧補完",
autoCloseBracketsDescription: "左括弧や左引用符を入力すると、対応する右括弧や右引用符を自動的に挿入します",
sqlSemanticDiagnosticsEnabled: "SQLセマンティック診断",
sqlSemanticDiagnosticsEnabledDescription: "有効時、エディタは不明なテーブルや列などの意味的な問題を表示します。大きなSQLの解析とメタデータ確認の負荷を減らすには無効にします。",
confirmDangerousSqlExecution: "危険なSQLの前に確認",
+2
View File
@@ -2988,6 +2988,8 @@ export default withEnglishFallback({
wordWrapDescription: "Quebrar linhas SQL longas dentro da largura do editor",
vimMode: "Modo Vim",
vimModeDescription: "Usar edição modal no estilo Vim no editor SQL",
autoCloseBrackets: "Fechar parênteses automaticamente",
autoCloseBracketsDescription: "Inserir automaticamente parênteses e aspas de fechamento ao digitar os de abertura",
sqlSemanticDiagnosticsEnabled: "Diagnóstico semântico de SQL",
sqlSemanticDiagnosticsEnabledDescription: "Quando ativado, o editor relata problemas semânticos como tabelas e colunas desconhecidas. Desative para reduzir a análise e verificações de metadados em SQL grande.",
confirmDangerousSqlExecution: "Confirmar antes de SQL perigoso",
+2
View File
@@ -3088,6 +3088,8 @@ export default withEnglishFallback({
wordWrapDescription: "长 SQL 在编辑器宽度内自动折行显示",
vimMode: "Vim 模式",
vimModeDescription: "在 SQL 编辑器中使用 Vim 风格的模态编辑",
autoCloseBrackets: "自动成对补全",
autoCloseBracketsDescription: "输入左括号或左引号时自动补全对应的右括号或右引号",
sqlSemanticDiagnosticsEnabled: "SQL 语义诊断",
sqlSemanticDiagnosticsEnabledDescription: "开启后,编辑器会提示未知表、字段等语义问题;关闭可减少 SQL 解析和元数据检查的性能开销。",
confirmDangerousSqlExecution: "执行危险 SQL 前弹出确认",
+2
View File
@@ -2838,6 +2838,8 @@ export default withEnglishFallback({
wordWrapDescription: "長 SQL 在編輯器寬度內自動折行顯示",
vimMode: "Vim 模式",
vimModeDescription: "在 SQL 編輯器中使用 Vim 風格的模態編輯",
autoCloseBrackets: "自動成對補全",
autoCloseBracketsDescription: "輸入左括號或左引號時自動補全對應的右括號或右引號",
sqlSemanticDiagnosticsEnabled: "SQL 語意診斷",
sqlSemanticDiagnosticsEnabledDescription: "開啟後,編輯器會提示未知資料表、欄位等語意問題;關閉可減少 SQL 解析和中繼資料檢查的效能負擔。",
confirmDangerousSqlExecution: "執行危險 SQL 前彈出確認",
+4
View File
@@ -375,6 +375,7 @@ export interface EditorSettings {
autoAliasTables: boolean;
wordWrap: boolean;
vimModeEnabled: boolean;
autoCloseBrackets: boolean;
sqlSemanticDiagnosticsMode: SqlSemanticDiagnosticsMode;
sqlSemanticDiagnosticsEnabled: boolean;
confirmDangerousSqlExecution: boolean;
@@ -503,6 +504,7 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
autoAliasTables: true,
wordWrap: false,
vimModeEnabled: false,
autoCloseBrackets: true,
sqlSemanticDiagnosticsMode: "auto",
sqlSemanticDiagnosticsEnabled: SQL_SEMANTIC_DIAGNOSTICS_AUTO_ENABLED,
confirmDangerousSqlExecution: true,
@@ -728,6 +730,7 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
autoAliasTables: settings.autoAliasTables ?? DEFAULT_EDITOR_SETTINGS.autoAliasTables,
wordWrap: settings.wordWrap ?? DEFAULT_EDITOR_SETTINGS.wordWrap,
vimModeEnabled: typeof settings.vimModeEnabled === "boolean" ? settings.vimModeEnabled : DEFAULT_EDITOR_SETTINGS.vimModeEnabled,
autoCloseBrackets: typeof settings.autoCloseBrackets === "boolean" ? settings.autoCloseBrackets : DEFAULT_EDITOR_SETTINGS.autoCloseBrackets,
sqlSemanticDiagnosticsMode,
sqlSemanticDiagnosticsEnabled: sqlSemanticDiagnosticsEnabledForMode(sqlSemanticDiagnosticsMode),
confirmDangerousSqlExecution: settings.confirmDangerousSqlExecution ?? DEFAULT_EDITOR_SETTINGS.confirmDangerousSqlExecution,
@@ -963,6 +966,7 @@ export const useSettingsStore = defineStore("settings", () => {
if (partial.autoAliasTables !== undefined) editorSettings.value.autoAliasTables = partial.autoAliasTables;
if (partial.wordWrap !== undefined) editorSettings.value.wordWrap = partial.wordWrap;
if (partial.vimModeEnabled !== undefined) editorSettings.value.vimModeEnabled = partial.vimModeEnabled === true;
if (partial.autoCloseBrackets !== undefined) editorSettings.value.autoCloseBrackets = partial.autoCloseBrackets === true;
if (partial.sqlSemanticDiagnosticsMode !== undefined || partial.sqlSemanticDiagnosticsEnabled !== undefined) {
const nextMode = normalizeSqlSemanticDiagnosticsMode(partial.sqlSemanticDiagnosticsMode, partial.sqlSemanticDiagnosticsEnabled);
editorSettings.value.sqlSemanticDiagnosticsMode = nextMode;