mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Editor: CodeLens + completion to scaffold Vega-Lite params; shared snippet core
This commit is contained in:
@@ -294,6 +294,19 @@ logic is pure `src/core/`; the Monaco glue is thin app-layer services.
|
||||
calculate, aggregate, bin, timeUnit, window, joinaggregate, fold, lookup); each builder takes the
|
||||
columns in scope and seeds each `${n:default}` tab stop with a type-appropriate one. A test
|
||||
round-trips every snippet through `snippetToPlain` to assert it's valid JSON.
|
||||
- `spec-params` — the parameter counterpart: `paramSiteAt` resolves both homes a parameter can take
|
||||
(the **root** spec for a variable widget, the **nearest enclosing unit** for a selection —
|
||||
grammar-confirmed against the bundled schema: a nested unit's `params[]` takes selections only),
|
||||
and `paramPlacementAt` classifies a `params[]` slot (root → both families, nested → selections only)
|
||||
for the completion. `PARAMS` is the catalog (slider, dropdown, radio, checkbox; point, interval); a
|
||||
slider's bounds seed from the numeric field's `numericExtent`, a point selection's field from a
|
||||
categorical column. A test validates every seeded entry against the bundled Vega-Lite schema.
|
||||
- `spec-snippet` — the snippet-insertion text math both scaffolds share: `snippetToPlain`
|
||||
(tab stops → default text, so catalogs and edits round-trip through `JSON.parse` in tests),
|
||||
`arrayAffixes`/`appendEntryEdit` (the comma affixing that keeps a spliced array valid), and
|
||||
`createArrayPropertyEdit` (the inline `"key": [ … ]` first-property insertion and its indent
|
||||
math). Pure `(text, site) → { offset, snippet }` — a bug here writes invalid JSON into the
|
||||
user's editor, so the edits are table-tested applied-and-reparsed, off the Monaco glue.
|
||||
- `spec-data` — the Vega-Lite data model: classify a `data` block (`classifyData`, mirroring
|
||||
`isNamedData`), the library reference name (`libraryRefName`), and the data binding in scope
|
||||
at a cursor path (`dataBindingAtPath`, honoring a view's data inheritance from its parent).
|
||||
@@ -344,7 +357,8 @@ logic is pure `src/core/`; the Monaco glue is thin app-layer services.
|
||||
|
||||
**Services (app, store-aware via `getState`):** `spec-transform-actions` (the
|
||||
wrap/simplify/add-view operations and their surfaces), `spec-transform-scaffold` (the
|
||||
data-transform scaffold — a CodeLens plus a completion), `spec-dataset-hints` (data-column completion, hover,
|
||||
data-transform scaffold — a CodeLens plus a completion), `spec-param-scaffold` (the parameter
|
||||
scaffold — likewise a CodeLens plus a completion), `spec-dataset-hints` (data-column completion, hover,
|
||||
inlay providers), `spec-expression-hints` (expression completion, signature help, hover, and
|
||||
the diagnostic markers), `active-dataset` (`dataInfoAt(text, offset)` — the columns/types/stats
|
||||
plus derived fields the draft sees at the cursor). `SpecEditor` does the wiring.
|
||||
@@ -356,6 +370,14 @@ Decision rules:
|
||||
schema and formatter; per-editor registration would duplicate them on remount. Pieces that
|
||||
need the editor handle — the `addAction` context/F1 commands, and the CodeLens whose command
|
||||
runs `executeEdits` — are installed **per editor** and disposed with it.
|
||||
- **Cursor-aware CodeLenses share one skeleton.** The composition lens
|
||||
(`spec-transform-actions`), the transform scaffold, and the parameter scaffold are the same
|
||||
per-editor shape: a draft-gated provider that re-resolves the site under the cursor and refreshes
|
||||
only when a keyed summary of it changes. That skeleton is `installCursorLens(editor, { resolve,
|
||||
keyOf, lensesOf })` (`services/editor-cursor-lens`) — a new cursor lens supplies those three and its
|
||||
own commands, nothing else. The tab-through snippet splice and the completion-slot plumbing both
|
||||
scaffolds perform are shared the same way via `editor-snippet` — the Monaco glue over
|
||||
`core/spec-snippet`'s tested edit math.
|
||||
- **Transform scope.** A transform targets, in order: an explicit selection → the view the
|
||||
cursor sits in (`findViewRange`) → the whole document. A "view" is a composition-array
|
||||
element or a facet/repeat `spec` child; a flat unit spec has no inner view, so it scopes to
|
||||
@@ -434,6 +456,17 @@ Decision rules:
|
||||
the same catalog. A step's `scope` (`shared` when the array is on a composition parent, so it
|
||||
feeds every child) is surfaced so the placement is not a surprise, and comma affixing keeps the
|
||||
array valid whether the slot is empty, between elements, or appended after one without a trailing comma.
|
||||
- **Parameter scaffolding splits by family, because `params` has two homes.** Unlike a `transform`
|
||||
(on every view node), a **variable** widget (slider/dropdown/radio/checkbox, bound via `bind`) is only
|
||||
legal in the **root** `params[]` — a document-global input any view's `filter` can read — while a
|
||||
**selection** (point/interval, via `select`) attaches to the **unit** whose marks it reads. So the
|
||||
scaffold does not reuse `transformSiteAt`: `paramSiteAt` resolves both homes, and the CodeLens is
|
||||
cursor-scoped to match — variable widgets show at the top level (or a single-view spec, where the
|
||||
root _is_ the unit, so both families land on one line), selections on the unit the cursor is in, and a
|
||||
nested unit hides the variable widgets it cannot hold. The completion offers both families in the root
|
||||
array, selections only in a nested unit's. Defaults are data-seeded where the data allows (a slider's
|
||||
`min`/`max` from the numeric field's extent, a point's `fields` from a categorical column) and
|
||||
structured placeholders otherwise (a dropdown's options).
|
||||
- **Code-action menu icons are kind-derived** (a wrench for the `refactor.*` kinds) — Monaco's
|
||||
`CodeAction` carries no icon field. Custom iconography lives only where it is supported:
|
||||
CodeLens titles (`$(codicon)`), completion-item kinds, and glyph-margin decorations.
|
||||
|
||||
@@ -13,6 +13,13 @@ The editor presents the active snippet's spec as formatted JSON with full code-e
|
||||
- The editor's appearance and behavior — font size, editor theme, minimap visibility, word wrap, line numbers, and tab size — are configurable and read from _Settings_; this section does not redefine their defaults.
|
||||
- The editor always edits a single active snippet. Selecting a different snippet in the _Snippet Library_, or toggling the Draft/Published view, replaces the editor content with the corresponding spec.
|
||||
|
||||
### Scaffolding assistance
|
||||
|
||||
Beyond the schema's own suggestions, the editor scaffolds common Vega-Lite structures as ready-to-fill skeletons, seeded from the data actually in scope at the cursor. An inserted skeleton arrives with editable placeholders (Tab moves between them), pre-filled with type-appropriate values where the data allows and descriptive names otherwise. Scaffolding acts on the draft only — the published view is a read-only reference and offers none of it.
|
||||
|
||||
- **Data transforms.** With the cursor in a view, inline actions above the code offer the pipeline: _Add transform_ when the view has none, the common steps (filter, aggregate, calculate, bin, timeUnit) on an existing `transform` array. Inside a `transform[]` element slot, typing offers the full step catalog as completions, each seeded with a matching column (a numeric field for aggregate, a temporal one for timeUnit). A step added on a composition parent notes that it applies to every child view below it.
|
||||
- **Parameters.** The same affordance for `params`, split by where Vega-Lite allows each family: **variable** widgets (slider, dropdown — an input control bound to a name the spec can reference) are offered at the spec's top level, the only place they are legal; **selection** parameters (point, interval — interaction on the chart's marks) on the unit view the cursor is in; in a single-view spec, where the top level is the unit, both appear together. Inside a `params[]` element slot, completions offer the catalog — both families in the top-level array, selections only in a nested view's. Defaults are data-seeded where possible: a slider's min/max/step from the numeric field's actual range, a point selection's field from a categorical column.
|
||||
|
||||
## B. Auto-Save of the Draft
|
||||
|
||||
Edits persist automatically so the user never loses work and never needs an explicit "save" action for ordinary editing.
|
||||
|
||||
Reference in New Issue
Block a user