fix(editor): skip right quote on repeated single-quote input

Co-authored-by: zipg <4047349+zipg@users.noreply.github.com>
This commit is contained in:
zipgandzipg authored and GitHub committed 2026-07-09 18:25:27 +08:00
1 parent 5dfefbc0f5
commit 24370135eb
3 files changed
+59 -6

No files matched your search

@@ -15,6 +15,7 @@ import { executableStatementRangeAtCursor, executableStatementRangeCacheForDoc,
import { currentStatementFrameRangeTo, visualSqlColumns } from "@/lib/sql/currentStatementFrame";
import { formatSqlText, type SqlFormatDialect } from "@/lib/sql/sqlFormatter";
import { buildSqlInConditionFromPasteSource, insertTextForSqlInCondition } from "@/lib/sql/sqlInListPaste";
import { resolveSqlSingleQuoteKeyAction } from "@/lib/sql/sqlQuoteCaret";
import { formatMongoShellText } from "@/lib/mongo/mongoFormatter";
import { useConnectionStore, COMPLETION_METADATA_CONCURRENCY } from "@/stores/connectionStore";
import { useSettingsStore } from "@/stores/settingsStore";
@@ -432,14 +433,28 @@ function requestExecuteFromView(currentView: EditorViewType, cursorPos: number,
return true;
}
function sqlSingleQuoteKeyActionAt(state: EditorViewType["state"], position: number) {
return resolveSqlSingleQuoteKeyAction({
previousChar: position > 0 ? state.doc.sliceString(position - 1, position) : "",
nextChar: position < state.doc.length ? state.doc.sliceString(position, position + 1) : "",
autoCloseBrackets: settingsStore.editorSettings.autoCloseBrackets,
});
}
function handleSqlSingleQuote(view: EditorViewType): boolean {
const { state } = view;
if (state.readOnly) return false;
if (state.selection.ranges.some((range) => !range.empty || range.from === 0 || state.doc.sliceString(range.from - 1, range.from) !== "'")) return false;
const transaction = state.changeByRange((range) => ({
changes: { from: range.from, insert: "'" },
range,
}));
const EditorSelection = codeMirrorEditorSelection;
if (state.readOnly || !EditorSelection) return false;
if (state.selection.ranges.some((range) => !range.empty)) return false;
if (state.selection.ranges.some((range) => sqlSingleQuoteKeyActionAt(state, range.from) === "pass")) return false;
const transaction = state.changeByRange((range) => {
const nextRange = EditorSelection.cursor(range.from + 1);
if (sqlSingleQuoteKeyActionAt(state, range.from) !== "insertEscapedQuote") return { range: nextRange };
return {
changes: { from: range.from, insert: "'" },
range: nextRange,
};
});
view.dispatch(transaction, { userEvent: "input.type" });
return true;
}