From 93a6a65707997359d1d3e41acb9b968c5ddd04c9 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Fri, 19 Jun 2026 02:06:12 +0800 Subject: [PATCH] feat(editor): toggle SQL keyword case --- apps/desktop/src/App.vue | 12 +++ .../src/components/editor/QueryEditor.vue | 4 + .../src/components/layout/EditorToolbar.vue | 19 +++++ apps/desktop/src/i18n/locales/en.ts | 2 + apps/desktop/src/i18n/locales/es.ts | 2 + apps/desktop/src/i18n/locales/it.ts | 2 + apps/desktop/src/i18n/locales/ja.ts | 2 + apps/desktop/src/i18n/locales/pt-BR.ts | 2 + apps/desktop/src/i18n/locales/zh-CN.ts | 2 + apps/desktop/src/i18n/locales/zh-TW.ts | 2 + apps/desktop/src/lib/sqlCompletion.ts | 85 +++++++++++++------ packages/app-tests/sqlCompletion.test.ts | 77 +++++++++++++++-- 12 files changed, 178 insertions(+), 33 deletions(-) diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index c2f6b9ece6..6a08634326 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -395,6 +395,16 @@ function formatActiveSql() { }; } +function toggleSqlKeywordCase() { + const sqlFormatter = settingsStore.editorSettings.sqlFormatter; + settingsStore.updateEditorSettings({ + sqlFormatter: { + ...sqlFormatter, + keywordCase: sqlFormatter.keywordCase === "lower" ? "upper" : "lower", + }, + }); +} + function defaultSavedSqlName(title: string) { const trimmed = title.trim() || "query"; const normalized = trimmed.replace(/\s+/g, "_"); @@ -1237,12 +1247,14 @@ onUnmounted(() => { :executable-sql="executableSql" :explain-mode="explainMode" :block-dangerous-redis-commands="blockDangerousRedisCommands" + :sql-keyword-case="settingsStore.editorSettings.sqlFormatter.keywordCase" @update:explain-mode="(m: 'explain' | 'autotrace') => (explainMode = m)" @update:block-dangerous-redis-commands="(v: boolean) => (blockDangerousRedisCommands = v)" @execute="tryExecute($event)" @cancel="cancelActiveExecution()" @explain="tryExplain()" @format-sql="formatActiveSql" + @toggle-sql-keyword-case="toggleSqlKeywordCase" @save-sql="void openSaveSqlDialog()" @open-sql="openSqlFile" @import-result-archive="importResultArchive" diff --git a/apps/desktop/src/components/editor/QueryEditor.vue b/apps/desktop/src/components/editor/QueryEditor.vue index f033cab04c..b159b5c633 100644 --- a/apps/desktop/src/components/editor/QueryEditor.vue +++ b/apps/desktop/src/components/editor/QueryEditor.vue @@ -1062,6 +1062,7 @@ async function provideSqlCompletions(currentState: import("@codemirror/state").E snippets: settingsStore.editorSettings.snippets, dialect: props.dialect, databaseType: props.databaseType, + keywordCase: settingsStore.editorSettings.sqlFormatter.keywordCase, }); return buildCompletionResult(items, position - completionContext.prefix.length, getSqlCompletionResultValidFor(fullDoc, position)); } @@ -1079,6 +1080,7 @@ async function provideSqlCompletions(currentState: import("@codemirror/state").E snippets: settingsStore.editorSettings.snippets, dialect: props.dialect, databaseType: props.databaseType, + keywordCase: settingsStore.editorSettings.sqlFormatter.keywordCase, }); return buildCompletionResult(items, position - completionContext.prefix.length, getSqlCompletionResultValidFor(fullDoc, position)); } @@ -1222,6 +1224,7 @@ function buildLocalSqlCompletionResult(completionContext: ReturnType(); const emit = defineEmits<{ @@ -32,6 +33,7 @@ const emit = defineEmits<{ explain: []; "update:explainMode": [mode: "explain" | "autotrace"]; formatSql: []; + toggleSqlKeywordCase: []; saveSql: []; openSql: []; importResultArchive: []; @@ -65,6 +67,8 @@ const isSingleDb = computed(() => isSingleDatabase(props.activeConnection?.db_ty const hasDefaultDatabaseOption = computed(() => activeDatabaseOptions.value.includes("")); const schemaDatabaseKey = computed(() => props.activeTab.database || (isSingleDb.value ? "_" : "")); const saveTooltip = computed(() => (props.activeTab.objectSource ? t("objects.saveSource") : t("toolbar.saveSql"))); +const keywordCaseIsLower = computed(() => props.sqlKeywordCase === "lower"); +const keywordCaseToggleTooltip = computed(() => (keywordCaseIsLower.value ? t("toolbar.keywordCaseUpper") : t("toolbar.keywordCaseLower"))); const showSchemaSelector = computed(() => { const connection = props.activeConnection; @@ -162,6 +166,21 @@ function connectionById(connectionId: string): ConnectionConfig | undefined { {{ t("toolbar.formatSql") }} + + + + + {{ keywordCaseToggleTooltip }} +