feat(query): show result source ranges

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-07-13 18:52:14 +08:00
1 parent d1cce3ed1e
commit 6f5dffb279
5 files changed
+248 -26

No files matched your search

@@ -249,8 +249,10 @@ let codeMirrorInsertNewlineKeepIndent: typeof import("@codemirror/commands").ins
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 setResultSourceRangeEffect: import("@codemirror/state").StateEffectType<{ from: number; to: number } | null> | null = null;
let previewRangeComp: import("@codemirror/state").Compartment | null = null;
let buildPreviewRangeExtension: (() => import("@codemirror/state").Extension) | null = null;
let buildResultSourceRangeExtension: (() => import("@codemirror/state").Extension) | null = null;
let buildRunStatementGutterExtension: (() => import("@codemirror/state").Extension) | null = null;
let indentComp: import("@codemirror/state").Compartment | null = null;
let codeMirrorIndentUnit: typeof import("@codemirror/language").indentUnit | null = null;
@@ -491,6 +493,33 @@ function setPreviewRange(range: { from: number; to: number } | null) {
});
}
function setResultSourceRange(range: { from: number; to: number } | null) {
if (!view.value || !setResultSourceRangeEffect) return;
view.value.dispatch({
effects: setResultSourceRangeEffect.of(range),
});
}
function previewStatementRange(range: { from: number; to: number } | null) {
const currentView = view.value;
if (!range || !currentView || !editorViewModule || !setResultSourceRangeEffect) {
setResultSourceRange(null);
return;
}
const from = Math.max(0, Math.min(range.from, currentView.state.doc.length));
const to = Math.max(from, Math.min(range.to, currentView.state.doc.length));
if (from === to) {
setResultSourceRange(null);
return;
}
currentView.dispatch({
selection: { anchor: from },
effects: [setResultSourceRangeEffect.of({ from, to }), editorViewModule.EditorView.scrollIntoView(from, { y: "center" })],
});
}
function onPickerActiveIndexChange(index: number) {
pickerActiveIndex.value = index;
const candidate = pickerCandidates.value[index];
@@ -2574,8 +2603,8 @@ onMounted(async () => {
if (!editorRef.value) return;
const [
{ EditorView, keymap, rectangularSelection, hoverTooltip, showTooltip, Decoration, tooltips, gutter, GutterMarker, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, crosshairCursor, ViewPlugin },
{ EditorState, EditorSelection, Compartment, Prec, StateEffect, StateField },
{ EditorView, keymap, rectangularSelection, hoverTooltip, showTooltip, Decoration, tooltips, gutter, GutterMarker, lineNumberMarkers, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, crosshairCursor, ViewPlugin },
{ EditorState, EditorSelection, Compartment, Prec, RangeSet, StateEffect, StateField },
langSql,
{ autocompletion, startCompletion, acceptCompletion, closeBrackets, closeBracketsKeymap, snippetCompletion, completionStatus, completionKeymap, insertCompletionText, nextSnippetField },
{ copyLineDown, copyLineUp, deleteLine, indentLess, indentMore, insertNewlineKeepIndent, moveLineDown, moveLineUp, redo, selectAll, undo, toggleLineComment, history, defaultKeymap, historyKeymap },
@@ -2681,6 +2710,7 @@ onMounted(async () => {
return Decoration.set([Decoration.mark({ class: "cm-db-execution-preview" }).range(range.from, range.to)]);
}
}
if (transaction.docChanged || transaction.selection) return Decoration.none;
return decorations;
},
provide: (f) => EditorView.decorations.from(f),
@@ -2688,6 +2718,41 @@ onMounted(async () => {
return field;
};
class ResultSourceLineNumberMarker extends GutterMarker {
elementClass = "cm-db-result-source-line-number";
}
const resultSourceLineNumberMarker = new ResultSourceLineNumberMarker();
setResultSourceRangeEffect = StateEffect.define<{ from: number; to: number } | null>();
buildResultSourceRangeExtension = () => {
const effectType = setResultSourceRangeEffect!;
const markersForRange = (state: import("@codemirror/state").EditorState, range: { from: number; to: number }) => {
const from = Math.max(0, Math.min(range.from, state.doc.length));
const to = Math.max(from, Math.min(range.to, state.doc.length));
const startLine = state.doc.lineAt(from);
const endLine = state.doc.lineAt(Math.max(from, to - 1));
const markers = Array.from({ length: endLine.number - startLine.number + 1 }, (_, index) => resultSourceLineNumberMarker.range(state.doc.line(startLine.number + index).from));
return RangeSet.of(markers);
};
const field = StateField.define({
create() {
return RangeSet.empty;
},
update(markers, transaction) {
for (const effect of transaction.effects) {
if (effect.is(effectType)) {
return effect.value ? markersForRange(transaction.state, effect.value) : RangeSet.empty;
}
}
if (transaction.docChanged || transaction.selection) return RangeSet.empty;
return markers;
},
provide: (field) => lineNumberMarkers.from(field),
});
return field;
};
buildSqlSignatureExtension = () =>
showTooltip.compute(["doc", "selection"], (currentState) => {
const signature = getSqlFunctionSignatureHelp(currentState.doc.toString(), currentState.selection.main.head);
@@ -2878,6 +2943,7 @@ onMounted(async () => {
requestTableColumns: requestInsertValueHintTableColumns,
}),
previewRangeComp.of(buildPreviewRangeExtension()),
buildResultSourceRangeExtension(),
Prec.highest(
keymap.of([
{ key: "'", run: handleSqlSingleQuote },
@@ -3462,7 +3528,7 @@ function scrollCursorIntoView() {
});
}
defineExpose({ openSearch, openReplace, scrollCursorIntoView, requestExecute, pasteClipboardAsSqlInCondition });
defineExpose({ openSearch, openReplace, scrollCursorIntoView, requestExecute, pasteClipboardAsSqlInCondition, previewStatementRange });
</script>
<template>
@@ -3495,6 +3561,15 @@ defineExpose({ openSearch, openReplace, scrollCursorIntoView, requestExecute, pa
background: var(--dbx-editor-selection-background, rgba(59, 130, 246, 0.35));
}
:deep(.cm-lineNumbers .cm-db-result-source-line-number) {
color: rgb(126 34 206) !important;
font-weight: 700;
}
:global(.dark) :deep(.cm-lineNumbers .cm-db-result-source-line-number) {
color: rgb(216 180 254) !important;
}
:deep(.cm-db-current-statement-line) {
position: relative;
}