Editor: cleaner transform-scaffold insertion

Insert the empty transform array inline (transform: []) instead of a multi-line
block, and pass adjustWhitespace:false to Monaco's snippet engine so it stops
re-basing the explicit indentation. The multi-line form left the closing bracket
under-indented and a stray blank line; the inline form lands cleanly indented as
the view's first property, with the first step filling it in place.
This commit is contained in:
2026-07-01 16:00:49 +03:00
parent 87b1b98c12
commit c5e4c4c76d
+14 -15
View File
@@ -54,14 +54,16 @@ const COMMON_STEP_IDS = ['filter', 'aggregate', 'calculate', 'bin', 'timeUnit']
/** Monaco's snippet contribution — the public entry to insert a `${n:…}` template with tab stops. */ /** Monaco's snippet contribution — the public entry to insert a `${n:…}` template with tab stops. */
interface SnippetInserter extends monaco.editor.IEditorContribution { interface SnippetInserter extends monaco.editor.IEditorContribution {
insert(template: string): void; insert(template: string, opts?: { adjustWhitespace?: boolean }): void;
} }
/** /**
* Insert a snippet template at `offset` through Monaco's snippet engine, so its * Insert a snippet template at `offset` through Monaco's snippet engine, so its
* `${n:default}` tab stops become a live, Tab-through session. Places the cursor * `${n:default}` tab stops become a live, Tab-through session. Places the cursor
* first (the controller inserts at the selection). No-op if the contribution is * first (the controller inserts at the selection). `adjustWhitespace: false` keeps
* absent (it ships in `edcore.main`, so this is just defensive). * the engine from re-basing our explicit indentation to the insertion line's — it
* otherwise leaves a multi-line block's closing bracket under-indented. No-op if the
* contribution is absent (it ships in `edcore.main`, so this is just defensive).
*/ */
function insertSnippetAt( function insertSnippetAt(
editor: monaco.editor.IStandaloneCodeEditor, editor: monaco.editor.IStandaloneCodeEditor,
@@ -72,7 +74,9 @@ function insertSnippetAt(
if (!model) return; if (!model) return;
editor.setPosition(model.getPositionAt(offset)); editor.setPosition(model.getPositionAt(offset));
editor.focus(); editor.focus();
editor.getContribution<SnippetInserter>('snippetController2')?.insert(template); editor.getContribution<SnippetInserter>('snippetController2')?.insert(template, {
adjustWhitespace: false,
});
} }
let registered = false; let registered = false;
@@ -156,11 +160,11 @@ function runAddStep(
/** /**
* Insert an empty `transform: []` as the view's first property and drop the cursor * Insert an empty `transform: []` as the view's first property and drop the cursor
* inside it (a `$0` tab stop), so the per-step lenses appear next. Indented off the * between its brackets (`$0`), so the per-step lenses appear next and the first step
* view line's own nesting, and separated from the next property with a comma only * fills the array in place. The array is written **inline** — no interior newlines for
* when one follows — a view with no other key (a bare `{}`) takes none, so the result * the snippet engine to re-base — so it lands cleanly indented off the view line's own
* stays valid JSON. The snippet engine precludes a reformat, so the indent is a best * nesting. Separated from the following property with a comma only when one follows (a
* effort the next document format tidies. * view with no other key takes none), so the result stays valid JSON.
*/ */
function runAddTransform(editor: monaco.editor.IStandaloneCodeEditor, viewOffset: number): void { function runAddTransform(editor: monaco.editor.IStandaloneCodeEditor, viewOffset: number): void {
const model = editor.getModel(); const model = editor.getModel();
@@ -176,13 +180,8 @@ function runAddTransform(editor: monaco.editor.IStandaloneCodeEditor, viewOffset
const braceLine = model.getPositionAt(brace).lineNumber; const braceLine = model.getPositionAt(brace).lineNumber;
const baseIndent = /^\s*/.exec(model.getLineContent(braceLine))?.[0].length ?? 0; const baseIndent = /^\s*/.exec(model.getLineContent(braceLine))?.[0].length ?? 0;
const indent = ' '.repeat(baseIndent + tab); const indent = ' '.repeat(baseIndent + tab);
const inner = ' '.repeat(tab);
const trail = neighbour(text, brace + 1, 1) === '}' ? '' : ','; const trail = neighbour(text, brace + 1, 1) === '}' ? '' : ',';
insertSnippetAt( insertSnippetAt(editor, brace + 1, `\n${indent}"transform": [$0]${trail}`);
editor,
brace + 1,
`\n${indent}"transform": [\n${indent}${inner}$0\n${indent}]${trail}`,
);
} }
/** /**