[Enhancement] Playground toolbar: Format document (Monaco API, shortcuts, per-language formatter hooks) — platform #35

Closed
opened 2026-04-28 23:48:45 +00:00 by spikerj · 1 comment
Owner

Summary

Add a Format affordance on the playground toolbar once Monaco lands (#24). Monaco wires when formatting runs; we supply what formatting does per language via monaco.languages.registerDocumentFormattingEditProvider (and/or invoking editor.getAction('editor.action.formatDocument').run() when built-ins apply).

Goals — shared platform behavior

  • Toolbar: visible Format button (semi-playground-aware where labels/shortcuts are shared).
  • Shortcuts: target Format document from keyboard (e.g. align with VS Code / platform norms). Note: In Chrome, Ctrl + Shift + I is DevTools — pick a non-conflicting chord (e.g. Shift + Alt + F like Windows VS Code, or preventDefault on editor focus) and document in shortcuts table.
  • Optional polish (separate milestones OK): format on save, format before run/submit (“format on run”) — gated so lesson flows stay predictable.
  • Architecture: thin FormatProvider (or facade) injected per LANGUAGE_RUNNER_CONFIG / Monaco model language id — no duplicated toolbar logic per formatter backend.
  • Disclaimer: Monaco does not ship production-grade formatters for every language — implementations tracked in: #36 (JS/TS Prettier), #37 (Python Black / backend), #38 (C# Roslyn).

Technical notes

  • provideDocumentFormattingEdits: replace full-model range text with formatted output.
  • Errors: surface formatter failures in snackbar or inline without corrupting undo stack when possible (pushEditOperations vs setValue).
  • Teaching: deterministic style acceptable for beginners; avoid surprising mass edits without clear affordance (“Format changed your code”).

Dependency

  • Blocks on Monaco migration for app-language-runner — #24. Child tickets plug real formatters beneath this facade.

Acceptance criteria

  • Format invoked from toolbar + keyboard on happy path.
  • No-op or clear message when no provider registered for current language.
  • Document how per-language hooks register (readme or ADR snippet).
## Summary Add a **Format** affordance on the playground **toolbar** once **Monaco** lands (`#24`). Monaco wires **when** formatting runs; **we** supply **what** formatting does per language via `monaco.languages.registerDocumentFormattingEditProvider` (and/or invoking `editor.getAction('editor.action.formatDocument').run()` when built-ins apply). ## Goals — shared platform behavior - **Toolbar**: visible **Format** button (semi-playground-aware where labels/shortcuts are shared). - **Shortcuts**: target **Format document** from keyboard (e.g. align with VS Code / platform norms). **Note:** In **Chrome**, **`Ctrl + Shift + I`** is **DevTools** — pick a non-conflicting chord (e.g. **`Shift + Alt + F`** like Windows VS Code, or `preventDefault` on editor focus) and document in shortcuts table. - **Optional polish** (separate milestones OK): format on save, format before run/submit (“format on run”) — gated so lesson flows stay predictable. - **Architecture**: thin **FormatProvider** (or facade) injected per **`LANGUAGE_RUNNER_CONFIG` / Monaco model language id** — no duplicated toolbar logic per formatter backend. - **Disclaimer**: Monaco does **not** ship production-grade formatters for every language — **implementations tracked in**: **#36** (JS/TS Prettier), **#37** (Python Black / backend), **#38** (C# Roslyn). ## Technical notes - **`provideDocumentFormattingEdits`**: replace full-model range text with formatted output. - **Errors**: surface formatter failures in snackbar or inline without corrupting undo stack when possible (`pushEditOperations` vs `setValue`). - **Teaching**: deterministic style acceptable for beginners; avoid surprising mass edits without clear affordance (“Format changed your code”). ## Dependency - Blocks on Monaco migration for **`app-language-runner`** — `#24`. Child tickets plug real formatters beneath this facade. ## Acceptance criteria - [ ] Format invoked from toolbar + keyboard on happy path. - [ ] No-op or clear message when no provider registered for current language. - [ ] Document how per-language hooks register (readme or ADR snippet).
Author
Owner

Migrated to spikerj/spikersoft-angular#665 as part of the umbrella-tracker breakup.

Verified 2026-08-07 against spikersoft-angular@8e5a4048: only the JS runner registers a Monaco formatting provider (Prettier, ticket #36); no shared FormatProvider seam, no toolbar button, no shortcut, no other language covered.

Status: partially done — JS/TS Prettier (#36) landed; the shared toolbar/facade/shortcut layer this ticket describes is still missing.

Closing here. Work now lives in the repo that holds the fix, so fixes #<N> in a PR will
auto-close it on merge. The umbrella tracker keeps cross-repo epics only.

— Opus 5 Agent

Migrated to **spikerj/spikersoft-angular#665** as part of the umbrella-tracker breakup. Verified 2026-08-07 against `spikersoft-angular@8e5a4048`: only the JS runner registers a Monaco formatting provider (Prettier, ticket #36); no shared FormatProvider seam, no toolbar button, no shortcut, no other language covered. Status: partially done — JS/TS Prettier (#36) landed; the shared toolbar/facade/shortcut layer this ticket describes is still missing. Closing here. Work now lives in the repo that holds the fix, so `fixes #<N>` in a PR will auto-close it on merge. The umbrella tracker keeps cross-repo epics only. — Opus 5 Agent
Sign in to join this conversation.