feat(editor): add whitespace display toggle for SQL editor

This commit is contained in:
Melody Ruch authored and GitHub committed 2026-09-20 00:50:44 +08:00
1 parent fff07eff00
commit fa3925ca52
18 files changed
+184

No files matched your search

@@ -584,6 +584,7 @@ const completionTriggerModeDescription = computed(() => {
return t(key, { shortcut: formatShortcutDisplay(editShortcuts.value.triggerCompletion) });
});
const editWordWrap = ref(settingsStore.editorSettings.wordWrap);
const editShowWhitespace = ref(settingsStore.editorSettings.showWhitespace);
const editVimModeEnabled = ref(settingsStore.editorSettings.vimModeEnabled);
const editAutoCloseBrackets = ref(settingsStore.editorSettings.autoCloseBrackets);
const editSqlSemanticDiagnosticsMode = ref<SqlSemanticDiagnosticsMode>(settingsStore.editorSettings.sqlSemanticDiagnosticsMode);
@@ -913,6 +914,7 @@ function currentEditorSettingsDraft(): EditorSettingsDraft {
selectFirstCompletionOnOpen: editSelectFirstCompletionOnOpen.value,
completionTriggerMode: editCompletionTriggerMode.value,
wordWrap: editWordWrap.value,
showWhitespace: editShowWhitespace.value,
vimModeEnabled: editVimModeEnabled.value,
autoCloseBrackets: editAutoCloseBrackets.value,
sqlSemanticDiagnosticsMode: editSqlSemanticDiagnosticsMode.value,
@@ -1551,6 +1553,7 @@ function syncEditorSettingsDraftFromStore() {
editSelectFirstCompletionOnOpen.value = settingsStore.editorSettings.selectFirstCompletionOnOpen;
editCompletionTriggerMode.value = settingsStore.editorSettings.completionTriggerMode;
editWordWrap.value = settingsStore.editorSettings.wordWrap;
editShowWhitespace.value = settingsStore.editorSettings.showWhitespace;
editVimModeEnabled.value = settingsStore.editorSettings.vimModeEnabled;
editAutoCloseBrackets.value = settingsStore.editorSettings.autoCloseBrackets;
editSqlSemanticDiagnosticsMode.value = settingsStore.editorSettings.sqlSemanticDiagnosticsMode;
@@ -1681,6 +1684,7 @@ const editorSettingsDraftRefs: EditorSettingsDraftRefMap = {
sortCompletionColumnsAlphabetically: editSortCompletionColumnsAlphabetically,
selectFirstCompletionOnOpen: editSelectFirstCompletionOnOpen,
wordWrap: editWordWrap,
showWhitespace: editShowWhitespace,
vimModeEnabled: editVimModeEnabled,
autoCloseBrackets: editAutoCloseBrackets,
sqlSemanticDiagnosticsMode: editSqlSemanticDiagnosticsMode,
@@ -2126,6 +2130,7 @@ function resetDefaultsForTab(tab: SettingsCategory) {
editSelectFirstCompletionOnOpen.value = DEFAULT_EDITOR_SETTINGS.selectFirstCompletionOnOpen;
editCompletionTriggerMode.value = DEFAULT_EDITOR_SETTINGS.completionTriggerMode;
editWordWrap.value = DEFAULT_EDITOR_SETTINGS.wordWrap;
editShowWhitespace.value = DEFAULT_EDITOR_SETTINGS.showWhitespace;
editVimModeEnabled.value = DEFAULT_EDITOR_SETTINGS.vimModeEnabled;
editAutoCloseBrackets.value = DEFAULT_EDITOR_SETTINGS.autoCloseBrackets;
editSqlSemanticDiagnosticsMode.value = DEFAULT_EDITOR_SETTINGS.sqlSemanticDiagnosticsMode;
@@ -2271,6 +2276,7 @@ function resetAllDefaults() {
editSortCompletionColumnsAlphabetically.value = DEFAULT_EDITOR_SETTINGS.sortCompletionColumnsAlphabetically;
editSelectFirstCompletionOnOpen.value = DEFAULT_EDITOR_SETTINGS.selectFirstCompletionOnOpen;
editWordWrap.value = DEFAULT_EDITOR_SETTINGS.wordWrap;
editShowWhitespace.value = DEFAULT_EDITOR_SETTINGS.showWhitespace;
editVimModeEnabled.value = DEFAULT_EDITOR_SETTINGS.vimModeEnabled;
editAutoCloseBrackets.value = DEFAULT_EDITOR_SETTINGS.autoCloseBrackets;
editSqlSemanticDiagnosticsMode.value = DEFAULT_EDITOR_SETTINGS.sqlSemanticDiagnosticsMode;
@@ -6099,6 +6105,16 @@ onUnmounted(() => {
<Switch id="editor-show-insert-value-hints" v-model="editShowInsertValueHints" class="mt-0.5" />
</div>
<div class="settings-item 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-show-whitespace">{{ t("settings.showWhitespace") }}</Label>
<p class="text-xs text-muted-foreground">
{{ t("settings.showWhitespaceDescription") }}
</p>
</div>
<Switch id="editor-show-whitespace" v-model="editShowWhitespace" class="mt-0.5" />
</div>
<div class="settings-item 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-word-wrap">{{ t("settings.wordWrap") }}</Label>
@@ -163,6 +163,7 @@ import { createQueryEditorEscapeHandler } from "@/lib/editor/queryEditorEscape";
import { buildQueryEditorLineNumbersExtension, createQueryEditorLineNumberAlignmentExtension } from "@/lib/editor/queryEditorLineNumbers";
import { searchKeymapWithoutModD } from "@/lib/editor/codemirrorSearchKeymap";
import { defaultKeymapForGlobalShortcuts } from "@/lib/editor/codemirrorDefaultKeymap";
import { createShowWhitespaceExtension } from "@/lib/editor/codemirrorShowWhitespace";
import { appendSqlCompletionSpace } from "@/lib/editor/sqlCompletionInsertion";
import { batchColumnSelectionColumnList, batchColumnSelectionInsertReplacement, batchColumnSelectionReplaceTo, completionReplacementTo, isBatchColumnSelectionCompletionActive, shouldResolveSqlColumnCompletion } from "@/lib/editor/batchColumnSelection";
import { compareSqlCompletions, completionLabelPresentation } from "@/lib/editor/sqlCompletionPresentation";
@@ -701,6 +702,7 @@ let hoverCloseEffect: StateEffect<unknown> | null = null;
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 showWhitespaceComp: import("@codemirror/state").Compartment | null = null;
let lineNumbersComp: import("@codemirror/state").Compartment | null = null;
let vimModeComp: import("@codemirror/state").Compartment | null = null;
let closeBracketsComp: import("@codemirror/state").Compartment | null = null;
@@ -1022,6 +1024,7 @@ const queryEditorAppearanceSettings = computed(() => {
customThemes: settings.customThemes,
activeCustomThemeId: settings.activeCustomThemeId,
wordWrap: settings.wordWrap,
showWhitespace: settings.showWhitespace,
vimModeEnabled: settings.vimModeEnabled,
autoCloseBrackets: settings.autoCloseBrackets,
showLineNumbers: settings.showLineNumbers,
@@ -2782,6 +2785,11 @@ function wordWrapExtension() {
return props.forceWordWrap || settingsStore.editorSettings.wordWrap ? editorViewModule.EditorView.lineWrapping : [];
}
function showWhitespaceExtension(enabled = settingsStore.editorSettings.showWhitespace) {
if (!editorViewModule) return [];
return createShowWhitespaceExtension(editorViewModule, enabled);
}
function lineNumbersExtension(enabled = settingsStore.editorSettings.showLineNumbers) {
return buildQueryEditorLineNumbersExtension(codeMirrorLineNumbers, enabled, {
domEventHandlers: {
@@ -6307,6 +6315,8 @@ onMounted(async () => {
lineNumbers,
highlightActiveLineGutter,
highlightSpecialChars,
highlightWhitespace,
WidgetType,
drawSelection,
dropCursor,
crosshairCursor,
@@ -6343,6 +6353,10 @@ onMounted(async () => {
EditorView,
keymap,
rectangularSelection,
highlightWhitespace,
WidgetType,
Decoration,
ViewPlugin,
} as typeof import("@codemirror/view");
hoverCloseEffect = closeHoverTooltips;
codeMirrorLineNumbers = lineNumbers;
@@ -6352,6 +6366,7 @@ onMounted(async () => {
fontThemeComp = new Compartment();
codeMirrorTheme = new Compartment();
wordWrapComp = new Compartment();
showWhitespaceComp = new Compartment();
lineNumbersComp = new Compartment();
vimModeComp = new Compartment();
closeBracketsComp = new Compartment();
@@ -7083,6 +7098,7 @@ onMounted(async () => {
}),
),
wordWrapComp.of(props.forceWordWrap || initialSettings.wordWrap ? EditorView.lineWrapping : []),
showWhitespaceComp.of(showWhitespaceExtension(initialSettings.showWhitespace)),
readOnlyComp.of([EditorState.readOnly.of(!!props.readOnly), EditorView.editable.of(!props.readOnly)]),
indentComp.of(indentExtension()),
// Alt+drag belongs exclusively to rectangular selection. Registering the
@@ -7885,6 +7901,7 @@ async function applyEditorAppearance() {
effects: [
codeMirrorTheme.reconfigure(themeExt),
wordWrapComp.reconfigure(props.forceWordWrap || ss.wordWrap ? editorViewModule.EditorView.lineWrapping : []),
...(showWhitespaceComp ? [showWhitespaceComp.reconfigure(showWhitespaceExtension(ss.showWhitespace))] : []),
lineNumbersComp.reconfigure(lineNumbersExtension(ss.showLineNumbers)),
vimModeComp.reconfigure(vimModeExtension(settingsStore.editorSettings.vimModeEnabled)),
closeBracketsComp.reconfigure(closeBracketsExtension(settingsStore.editorSettings.autoCloseBrackets)),
+2
View File
@@ -7415,6 +7415,8 @@ export default withEnglishFallback({
previewStatementRunButton: "Əmri işlətmə düyməsinə önbaxış",
wordWrap: "Sətirləri bük",
wordWrapDescription: "Uzun sətirləri redaktorun eninə uyğun bük",
showWhitespace: "Boşluq simvollarını göstər",
showWhitespaceDescription: "SQL redaktorunda boşluqları ·, tabulyasiyaları → kimi göstərir. Yalnız görünüş dəyişir, SQL mətni dəyişmir.",
vimMode: "Vim rejimi",
vimModeDescription: "SQL redaktorunda Vim üslublu modal redaktədən istifadə et",
autoCloseBrackets: "Mötərizələri avtomatik bağla",
+2
View File
@@ -7649,6 +7649,8 @@ export default {
previewStatementRunButton: "Preview statement run button",
wordWrap: "Word wrap",
wordWrapDescription: "Wrap long lines within the editor width",
showWhitespace: "Show whitespace",
showWhitespaceDescription: "Show spaces as · and tabs as → in the SQL editor. Only the display changes, not the SQL text.",
vimMode: "Vim mode",
vimModeDescription: "Use Vim-style modal editing in the SQL editor",
autoCloseBrackets: "Auto-close brackets",
+2
View File
@@ -7165,6 +7165,8 @@ export default withEnglishFallback({
previewStatementRunButton: "Botón de ejecución de sentencia en vista previa",
wordWrap: "Ajuste de línea",
wordWrapDescription: "Ajustar las líneas largas al ancho del editor",
showWhitespace: "Mostrar espacios en blanco",
showWhitespaceDescription: "Mostrar espacios como · y tabulaciones como → en el editor SQL. Solo cambia la visualización, no el texto SQL.",
vimMode: "Modo Vim",
vimModeDescription: "Usar edición modal estilo Vim en el editor SQL",
autoCloseBrackets: "Cerrar paréntesis automáticamente",
+2
View File
@@ -7165,6 +7165,8 @@ export default withEnglishFallback({
previewStatementRunButton: "Pulsante di esecuzione istruzione in anteprima",
wordWrap: "A capo automatico",
wordWrapDescription: "Manda a capo le righe lunghe entro la larghezza dell'editor",
showWhitespace: "Mostra spazi bianchi",
showWhitespaceDescription: "Mostra gli spazi come · e le tabulazioni come → nell'editor SQL. Cambia solo la visualizzazione, non il testo SQL.",
vimMode: "Modalita Vim",
vimModeDescription: "Usa la modifica modale in stile Vim nell'editor SQL",
autoCloseBrackets: "Chiusura automatica parentesi",
+2
View File
@@ -7189,6 +7189,8 @@ export default withEnglishFallback({
previewStatementRunButton: "文の実行ボタンのプレビュー",
wordWrap: "折り返し",
wordWrapDescription: "長い行をエディタ幅内で折り返します",
showWhitespace: "空白文字を表示",
showWhitespaceDescription: "SQL エディタでスペースを ·、タブを → で表示します。表示のみ変わり、SQL テキストは変わりません。",
vimMode: "Vimモード",
vimModeDescription: "SQLエディタでVim形式のモーダル編集を使用します",
autoCloseBrackets: "自動括弧補完",
+2
View File
@@ -6941,6 +6941,8 @@ export default withEnglishFallback({
previewStatementRunButton: "구문 실행 버튼 미리보기",
wordWrap: "자동 줄바꿈",
wordWrapDescription: "편집기 너비 내에서 긴 줄을 줄바꿈합니다",
showWhitespace: "공백 문자 표시",
showWhitespaceDescription: "SQL 편집기에서 공백을 ·, 탭을 →로 표시합니다. 표시만 바뀌며 SQL 텍스트는 변경되지 않습니다.",
vimMode: "Vim 모드",
vimModeDescription: "SQL 편집기에서 Vim 스타일의 모달 편집을 사용합니다",
autoCloseBrackets: "괄호 자동 닫기",
+2
View File
@@ -7167,6 +7167,8 @@ export default withEnglishFallback({
previewStatementRunButton: "Botão de execução de instrução na prévia",
wordWrap: "Quebra de linha",
wordWrapDescription: "Quebrar linhas longas dentro da largura do editor",
showWhitespace: "Mostrar espaços em branco",
showWhitespaceDescription: "Mostrar espaços como · e tabulações como → no editor SQL. Altera apenas a exibição, não o texto SQL.",
vimMode: "Modo Vim",
vimModeDescription: "Usar edição modal no estilo Vim no editor SQL",
autoCloseBrackets: "Fechar parênteses automaticamente",
+2
View File
@@ -7296,6 +7296,8 @@ export default withEnglishFallback({
previewStatementRunButton: "İfade çalıştırma düğmesini önizle",
wordWrap: "Sözcük kaydırma",
wordWrapDescription: "Uzun satırları düzenleyici genişliğinde kaydır",
showWhitespace: "Boşluk karakterlerini göster",
showWhitespaceDescription: "SQL düzenleyicide boşlukları ·, sekmeleri → olarak gösterir. Yalnızca görünüm değişir, SQL metni değişmez.",
vimMode: "Vim modu",
vimModeDescription: "SQL düzenleyicisinde Vim biçemli kipli düzenleme kullan",
autoCloseBrackets: "Parantezleri otomatik kapat",
+2
View File
@@ -7620,6 +7620,8 @@ export default withEnglishFallback({
previewStatementRunButton: "预览语句执行按钮",
wordWrap: "自动换行",
wordWrapDescription: "长内容在编辑器宽度内自动折行显示",
showWhitespace: "显示空白字符",
showWhitespaceDescription: "在 SQL 编辑器中将空格显示为 ·,制表符显示为 →。仅影响显示,不改变 SQL 文本。",
vimMode: "Vim 模式",
vimModeDescription: "在 SQL 编辑器中使用 Vim 风格的模态编辑",
autoCloseBrackets: "自动成对补全",
+2
View File
@@ -6489,6 +6489,8 @@ export default withEnglishFallback({
previewStatementRunButton: "預覽語句執行按鈕",
wordWrap: "自動換行",
wordWrapDescription: "長內容在編輯器寬度內自動折行顯示",
showWhitespace: "顯示空白字元",
showWhitespaceDescription: "在 SQL 編輯器中將空格顯示為 ·,定位字元顯示為 →。僅影響顯示,不改變 SQL 文字。",
vimMode: "Vim 模式",
vimModeDescription: "在 SQL 編輯器中使用 Vim 風格的模態編輯",
autoCloseBrackets: "自動成對補全",
@@ -0,0 +1,52 @@
// @vitest-environment happy-dom
import { EditorState } from "@codemirror/state";
import * as viewModule from "@codemirror/view";
import { EditorView } from "@codemirror/view";
import { afterEach, describe, expect, it } from "vitest";
import { NEWLINE_MARKER, NEWLINE_MARKER_CLASS, createShowWhitespaceExtension } from "@/lib/editor/codemirrorShowWhitespace";
let view: EditorView | null = null;
function mount(doc: string, enabled: boolean) {
const parent = document.createElement("div");
document.body.appendChild(parent);
view = new EditorView({ parent, state: EditorState.create({ doc, extensions: [createShowWhitespaceExtension(viewModule, enabled)] }) });
return view;
}
afterEach(() => {
view?.destroy();
view = null;
document.body.innerHTML = "";
});
describe("createShowWhitespaceExtension", () => {
it("adds nothing when disabled", () => {
expect(createShowWhitespaceExtension(viewModule, false)).toEqual([]);
const v = mount("select 1\n\tfrom t", false);
expect(v.dom.querySelectorAll(`.${NEWLINE_MARKER_CLASS}`)).toHaveLength(0);
expect(v.dom.querySelector(".cm-highlightSpace, .cm-highlightTab")).toBeNull();
});
it("marks a line break after every line except the last", () => {
const v = mount("select 1\n\tfrom t\nwhere x", true);
const markers = v.dom.querySelectorAll(`.${NEWLINE_MARKER_CLASS}`);
expect(markers).toHaveLength(2);
expect(markers[0]!.textContent).toBe(NEWLINE_MARKER);
});
it("marks spaces and tabs and never changes the document text", () => {
const doc = "select 1\n\tfrom t";
const v = mount(doc, true);
expect(v.dom.querySelector(".cm-highlightSpace")).not.toBeNull();
expect(v.dom.querySelector(".cm-highlightTab")).not.toBeNull();
expect(v.state.doc.toString()).toBe(doc);
});
it("keeps marking empty lines and follows edits", () => {
const v = mount("a\n\nb", true);
expect(v.dom.querySelectorAll(`.${NEWLINE_MARKER_CLASS}`)).toHaveLength(2);
v.dispatch({ changes: { from: v.state.doc.length, insert: "\nc" } });
expect(v.dom.querySelectorAll(`.${NEWLINE_MARKER_CLASS}`)).toHaveLength(3);
});
});
@@ -0,0 +1,71 @@
import type { Extension } from "@codemirror/state";
type ViewModule = typeof import("@codemirror/view");
type EditorViewType = import("@codemirror/view").EditorView;
type DecorationSet = import("@codemirror/view").DecorationSet;
export const NEWLINE_MARKER = "↵";
export const NEWLINE_MARKER_CLASS = "cm-dbx-newline-marker";
/**
* Display-only whitespace markers for the SQL editor: spaces as "·", tabs as "→"
* (CodeMirror's highlightWhitespace) plus a "↵" at every line end that is followed
* by a line break. The document text itself is never touched.
*/
export function createShowWhitespaceExtension(view: Pick<ViewModule, "highlightWhitespace" | "ViewPlugin" | "Decoration" | "WidgetType" | "EditorView">, enabled: boolean): Extension {
if (!enabled) return [];
const { highlightWhitespace, ViewPlugin, Decoration, WidgetType, EditorView } = view;
class NewlineMarkerWidget extends WidgetType {
eq(): boolean {
return true;
}
toDOM(): HTMLElement {
const el = document.createElement("span");
el.className = NEWLINE_MARKER_CLASS;
el.setAttribute("aria-hidden", "true");
el.textContent = NEWLINE_MARKER;
return el;
}
ignoreEvent(): boolean {
return true;
}
}
const marker = Decoration.widget({ widget: new NewlineMarkerWidget(), side: 1 });
function buildDecorations(editorView: EditorViewType): DecorationSet {
const doc = editorView.state.doc;
const ranges = [];
let lastLine = -1;
for (const { from, to } of editorView.visibleRanges) {
for (let pos = from; pos <= to; ) {
const line = doc.lineAt(pos);
if (line.number !== lastLine) {
lastLine = line.number;
if (line.number < doc.lines) ranges.push(marker.range(line.to));
}
pos = line.to + 1;
}
}
return Decoration.set(ranges);
}
const newlinePlugin = ViewPlugin.fromClass(
class {
decorations: DecorationSet;
constructor(editorView: EditorViewType) {
this.decorations = buildDecorations(editorView);
}
update(update: import("@codemirror/view").ViewUpdate) {
if (update.docChanged || update.viewportChanged) this.decorations = buildDecorations(update.view);
}
},
{ decorations: (plugin) => plugin.decorations },
);
const markerTheme = EditorView.baseTheme({
[`.${NEWLINE_MARKER_CLASS}`]: { opacity: "0.35", pointerEvents: "none", userSelect: "none" },
});
return [highlightWhitespace(), newlinePlugin, markerTheme];
}
@@ -30,6 +30,7 @@ export const EDITOR_SETTINGS_DRAFT_KEYS = [
"sortCompletionColumnsAlphabetically",
"selectFirstCompletionOnOpen",
"wordWrap",
"showWhitespace",
"vimModeEnabled",
"autoCloseBrackets",
"sqlSemanticDiagnosticsMode",
@@ -128,6 +128,7 @@ export const SETTINGS_SEARCH_DEFINITIONS: readonly SettingsSearchDefinition[] =
{ id: "editor-line-numbers", category: "editor", titleKey: "settings.showLineNumbers", descriptionKey: "settings.showLineNumbersDescription", targetId: "editor" },
{ id: "editor-statement-frame", category: "editor", titleKey: "settings.showCurrentStatementFrame", descriptionKey: "settings.showCurrentStatementFrameDescription", targetId: "editor" },
{ id: "editor-value-hints", category: "editor", titleKey: "settings.showInsertValueHints", descriptionKey: "settings.showInsertValueHintsDescription", targetId: "editor" },
{ id: "editor-show-whitespace", category: "editor", titleKey: "settings.showWhitespace", descriptionKey: "settings.showWhitespaceDescription", targetId: "editor" },
{ id: "editor-word-wrap", category: "editor", titleKey: "settings.wordWrap", descriptionKey: "settings.wordWrapDescription", targetId: "editor" },
{ id: "editor-vim", category: "editor", titleKey: "settings.vimMode", descriptionKey: "settings.vimModeDescription", targetId: "editor" },
{ id: "editor-brackets", category: "editor", titleKey: "settings.autoCloseBrackets", descriptionKey: "settings.autoCloseBracketsDescription", targetId: "editor" },
@@ -88,6 +88,7 @@ const SETTINGS_TRANSFER_CATEGORY_KEYS: Record<SettingsTransferCategoryId, readon
"selectFirstCompletionOnOpen",
"completionTriggerMode",
"wordWrap",
"showWhitespace",
"vimModeEnabled",
"autoCloseBrackets",
"sqlSemanticDiagnosticsMode",
@@ -255,6 +256,7 @@ const EXPECTED_JSON_KINDS = new Map<string, string>(EDITOR_SETTINGS_DRAFT_KEYS.m
*/
const PASS_THROUGH_BOOLEAN_KEYS = [
"wordWrap",
"showWhitespace",
"showExecutionTargetPicker",
"autoAliasTables",
"confirmDangerousSqlExecution",
+4
View File
@@ -775,6 +775,7 @@ export interface EditorSettings {
sortCompletionColumnsAlphabetically: boolean;
selectFirstCompletionOnOpen: boolean;
wordWrap: boolean;
showWhitespace: boolean;
tableDdlWordWrap: boolean;
refreshDdlOnOpen: boolean;
excludeDdlStorage: boolean;
@@ -1033,6 +1034,7 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
sortCompletionColumnsAlphabetically: true,
selectFirstCompletionOnOpen: true,
wordWrap: false,
showWhitespace: false,
tableDdlWordWrap: true,
refreshDdlOnOpen: false,
excludeDdlStorage: true,
@@ -1538,6 +1540,7 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
sortCompletionColumnsAlphabetically: typeof settings.sortCompletionColumnsAlphabetically === "boolean" ? settings.sortCompletionColumnsAlphabetically : DEFAULT_EDITOR_SETTINGS.sortCompletionColumnsAlphabetically,
selectFirstCompletionOnOpen: typeof settings.selectFirstCompletionOnOpen === "boolean" ? settings.selectFirstCompletionOnOpen : DEFAULT_EDITOR_SETTINGS.selectFirstCompletionOnOpen,
wordWrap: settings.wordWrap ?? DEFAULT_EDITOR_SETTINGS.wordWrap,
showWhitespace: typeof settings.showWhitespace === "boolean" ? settings.showWhitespace : DEFAULT_EDITOR_SETTINGS.showWhitespace,
tableDdlWordWrap: typeof settings.tableDdlWordWrap === "boolean" ? settings.tableDdlWordWrap : DEFAULT_EDITOR_SETTINGS.tableDdlWordWrap,
excludeDdlStorage: typeof settings.excludeDdlStorage === "boolean" ? settings.excludeDdlStorage : DEFAULT_EDITOR_SETTINGS.excludeDdlStorage,
refreshDdlOnOpen: typeof settings.refreshDdlOnOpen === "boolean" ? settings.refreshDdlOnOpen : DEFAULT_EDITOR_SETTINGS.refreshDdlOnOpen,
@@ -2315,6 +2318,7 @@ export const useSettingsStore = defineStore("settings", () => {
if (partial.sortCompletionColumnsAlphabetically !== undefined) editorSettings.value.sortCompletionColumnsAlphabetically = partial.sortCompletionColumnsAlphabetically === true;
if (partial.selectFirstCompletionOnOpen !== undefined) editorSettings.value.selectFirstCompletionOnOpen = partial.selectFirstCompletionOnOpen === true;
if (partial.wordWrap !== undefined) editorSettings.value.wordWrap = partial.wordWrap;
if (partial.showWhitespace !== undefined) editorSettings.value.showWhitespace = partial.showWhitespace === true;
if (partial.tableDdlWordWrap !== undefined) editorSettings.value.tableDdlWordWrap = partial.tableDdlWordWrap === true;
if (partial.excludeDdlStorage !== undefined) editorSettings.value.excludeDdlStorage = partial.excludeDdlStorage === true;
if (partial.refreshDdlOnOpen !== undefined) editorSettings.value.refreshDdlOnOpen = partial.refreshDdlOnOpen === true;