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

Open
opened 2026-04-28 23:48:45 +00:00 by spikerj · 0 comments
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).
Sign in to join this conversation.