Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f21a6a4
Tests: add LSP helpers that check a language server really formats
thomasjm Oct 8, 2026
718ff14
Bash: declare shfmt as the formatter, and test that formatting works
thomasjm Oct 8, 2026
1d78f01
C++: declare clang-format as the formatter, and test that formatting …
thomasjm Oct 8, 2026
cb1e274
Clojure: declare cljfmt as the formatter, and test that formatting works
thomasjm Oct 8, 2026
d67c0d5
Go: add a setting to pick between gofmt and gofumpt, both of which go…
thomasjm Oct 8, 2026
f5561b0
Haskell: add a setting to pick the haskell-language-server formatting…
thomasjm Oct 8, 2026
39f7d04
JavaScript and TypeScript: declare tsserver as the formatter, and tes…
thomasjm Oct 8, 2026
ed62db1
Julia: declare JuliaFormatter as the formatter, and test that formatt…
thomasjm Oct 8, 2026
d125855
Python: add a formatter setting for python-lsp-server, which ships wi…
thomasjm Oct 8, 2026
d56013d
R: declare styler as the formatter
thomasjm Oct 8, 2026
39a2d12
Ruby: turn on Solargraph's rubocop formatting, which it ships with bu…
thomasjm Oct 8, 2026
6649774
Rust: put rustfmt on rust-analyzer's PATH so formatting requests stop…
thomasjm Oct 8, 2026
211c18e
Typst: add a setting to pick between typstyle and typstfmt, both vend…
thomasjm Oct 8, 2026
8b01b66
Feature matrix: make the Formatting cell name the formatter behind it
thomasjm Oct 8, 2026
0438049
Regenerate the feature matrix, LSP capabilities and options docs
thomasjm Oct 8, 2026
dca86fa
Tests: give the sandbox a /bin/sh and grep, and keep newlines out of …
thomasjm Oct 9, 2026
62f4256
R: the language server starts now; note what still keeps its formatti…
thomasjm Oct 9, 2026
22e3ed6
Rust: point the pending formatting test at the upstream rnls fix
thomasjm Oct 9, 2026
60aeb8f
Update Typst formatter description
thomasjm Oct 9, 2026
9ca17ef
Simplify gopls formatter description noci
thomasjm Oct 9, 2026
e4e96e7
Simplify description for Haskell formatter option noci
thomasjm Oct 9, 2026
c27a283
Simplify description for python-lsp-server formatter
thomasjm Oct 9, 2026
55b5aac
Remove description for rubocop formatting option
thomasjm Oct 9, 2026
e2c9fb6
Feature matrix: keep the Formatting column as plain check marks
thomasjm Oct 9, 2026
7dcff81
Regenerate the options docs after the description edits
thomasjm Oct 9, 2026
6c93215
Tests: move the formatting helpers into TestLib.LSP.Formatting
thomasjm Oct 9, 2026
df161e2
Write up what it would take to format notebook cells through the proxies
thomasjm Oct 9, 2026
565a493
R: record what actually causes the formatting test to hang
thomasjm Oct 9, 2026
1d1025f
R: unpend the formatting test now that the lsp-test teardown deadlock…
thomasjm Oct 9, 2026
9c1116f
Rust: bump rust-notebook-language-server to 0.2.5.0 and unpend the fo…
thomasjm Oct 9, 2026
fa9bc2f
R: build languageserver from our fork of master, with the shutdown re…
thomasjm Oct 9, 2026
b8494fa
Move the lsp pin back to upgrade-monads-newest-jan2026 now that the t…
thomasjm Oct 9, 2026
a1b1e3e
Move the lsp-test-helpers pin to main now that the /bin/sh change is …
thomasjm Oct 9, 2026
f3c0ced
Test formatting in notebooks, not just raw files
thomasjm Oct 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 71 additions & 3 deletions FEATURE-MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Which languages support which notebook and editor features. The graphic version
| Coq | ✅ | ✅ | – | – | ✅ |
| Go | ✅ | ✅ | – | – | ✅ |
| Haskell | ✅ | ✅ | – | – | ✅ |
| JavaScript | ✅ | ✅ | – | – | ✅ |
| Julia | ✅ | ✅ | ✅ | – | ✅ |
| Octave | ✅ | ✅ | ✅ | – | ✅ |
| PostgreSQL | ✅ | ✅ | – | – | ✅ |
Expand All @@ -26,6 +27,7 @@ Which languages support which notebook and editor features. The graphic version
| R (Ark) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Ruby | ✅ | ✅ | ✅ | – | ✅ |
| Rust | ✅ | ✅ | ✅ | – | ✅ |
| TypeScript | ✅ | ✅ | – | – | ✅ |

### Code intelligence

Expand All @@ -35,8 +37,9 @@ Which languages support which notebook and editor features. The graphic version
| C++ 23 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Clojure | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | – |
| Coq | – | – | – | – | – | – | – |
| Go | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Go | ✅ | ✅ | ✅ | ✅ | ✅ | – | ✅ |
| Haskell | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| JavaScript | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Julia | ✅ | ✅ | ✅ | ✅ | ✅ | – | ✅ |
| Octave | – | – | – | – | – | – | – |
| PostgreSQL | – | – | – | – | – | – | – |
Expand All @@ -46,6 +49,7 @@ Which languages support which notebook and editor features. The graphic version
| R (Ark) | – | – | – | – | – | – | – |
| Ruby | ✅ | ✅ | ✅ | ✅ | ✅ | – | – |
| Rust | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| TypeScript | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |

### Navigation

Expand All @@ -57,6 +61,7 @@ Which languages support which notebook and editor features. The graphic version
| Coq | – | – | – | – | – | – |
| Go | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Haskell | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| JavaScript | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Julia | ✅ | – | ✅ | ✅ | ✅ | ✅ |
| Octave | – | – | – | – | – | – |
| PostgreSQL | – | – | – | – | – | – |
Expand All @@ -66,6 +71,7 @@ Which languages support which notebook and editor features. The graphic version
| R (Ark) | – | – | – | – | – | – |
| Ruby | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Rust | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| TypeScript | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |

### Editing

Expand All @@ -77,15 +83,17 @@ Which languages support which notebook and editor features. The graphic version
| Coq | – | – | – |
| Go | ✅ | ✅ | ✅ |
| Haskell | ✅ | ✅ | ✅ |
| JavaScript | ✅ | ✅ | ✅ |
| Julia | ✅ | ✅ | ✅ |
| Octave | – | – | – |
| PostgreSQL | – | – | – |
| PyPy | – | ✅ | ✅ |
| Python | – | ✅ | ✅ |
| R | ✅ | ✅ | ✅ |
| R (Ark) | – | – | – |
| Ruby | – | ✅ | – |
| Ruby | ✅ | ✅ | – |
| Rust | ✅ | ✅ | ✅ |
| TypeScript | ✅ | ✅ | ✅ |

### Packages

Expand All @@ -97,6 +105,7 @@ Which languages support which notebook and editor features. The graphic version
| Coq | ✅ |
| Go | – |
| Haskell | ✅ |
| JavaScript | ✅ |
| Julia | ✅ |
| Octave | ✅ |
| PostgreSQL | – |
Expand All @@ -106,6 +115,7 @@ Which languages support which notebook and editor features. The graphic version
| R (Ark) | ✅ |
| Ruby | ✅ |
| Rust | ✅ |
| TypeScript | ✅ |

<!-- END FEATURE MATRIX -->

Expand All @@ -122,6 +132,7 @@ The matrix is derived from the repo, not maintained by hand:
builds a single-kernel environment per language, starts each language server, performs the
LSP `initialize` handshake, and records the advertised capabilities into
`nix/lsp-capabilities.json`.
- The Formatting column needs both halves — see [Formatting](#formatting) below.
- `scripts/render-feature-matrix.py` turns the resulting JSON into the SVG in the README and
the Markdown tables above.

Expand Down Expand Up @@ -158,7 +169,64 @@ by anything that wants to render this data elsewhere. Its shape:
```

`level` is `full`, `none`, or `unknown` (nothing probed that kernel yet), and `detail` says
which language server or REPL is behind it.
which language server or REPL is behind it — for `formatting`, the formatter. The SVG shows
`detail` in a cell's tooltip.

## Formatting

Formatting is the one column that can't be read off the `initialize` response alone. A server
will happily advertise `documentFormattingProvider` and then fail every request because the
tool behind it isn't installed — bash-language-server did exactly that until shfmt was added
to its wrapper. So the column is the conjunction of two things: the server advertises
formatting, *and* the kernel names the formatter behind it in `passthru.formatters` (declared
next to each language server's config and aggregated in the kernel's `default.nix`). That name
is what the table below records, and what the SVG shows in the cell's tooltip.

| Language | Formatter | Comes from | Setting |
| --- | --- | --- | --- |
| Bash | shfmt | separate binary on bash-language-server's PATH | — |
| C++ | clang-format | built into clangd | — |
| Clojure | cljfmt | built into clojure-lsp | — |
| Go | gofmt, gofumpt | both vendored into gopls | `kernels.go.lsp.gopls.formatter` |
| Haskell | ormolu, fourmolu, stylish-haskell | all compiled into haskell-language-server | `kernels.haskell.lsp.haskell-language-server.formattingProvider` |
| JavaScript / TypeScript | tsserver | built into typescript-language-server | — |
| Julia | JuliaFormatter | dependency of LanguageServer.jl | a `.JuliaFormatter.toml` in the workspace |
| Python | autopep8, yapf, black, ruff | none ship with python-lsp-server | `kernels.python3.lsp.python-lsp-server.formatter` |
| R | styler | already an R dependency of languageserver | — |
| Ruby | rubocop | already a gem dependency of solargraph | `kernels.ruby.lsp.solargraph.formatting` |
| Rust | rustfmt | separate binary on rust-analyzer's PATH | — |
| Typst | typstyle, typstfmt | both vendored into tinymist | `exporters.typst.lsp.tinymist.formatter` |

Where one formatter is listed and there's no setting, it costs nothing to ship (already in the
server's closure, or a small binary) and is on unconditionally. Where several are listed, the
setting picks between them; they're all built into the server, so the choice doesn't change
what gets built — except for Python, where python-lsp-server ships with no formatter at all and
the setting decides which one is added to the environment.

Each of these has a test that formats a deliberately misformatted document over LSP and checks
what comes back (`itFormatsAs` in `tests/src/TestLib/LSP.hs`), because advertising the
capability proves nothing.

Caveats the table above can't show:

- Python's default language server is Jedi, which has no formatting support of any kind. The
`formatter` setting only applies when `python-lsp-server` is also enabled, which it isn't by
default — so Python's Formatting cell is empty.
- Typst is an exporter rather than a kernel, so tinymist isn't probed and Typst has no row in
the matrix. tinymist already formatted with typstyle by default; the setting exists to pick
typstfmt or turn formatting off.
- Rust formats correctly when rust-analyzer is driven directly, but
rust-notebook-language-server forwarded `textDocument/formatting` with the notebook's URI
instead of the shadow file's, so rust-analyzer answered "file not found".
[rust-notebook-language-server#2](https://github.com/codedownio/rust-notebook-language-server/pull/2)
fixes it; the Rust formatting test stays pending until that's released and the pinned
version here moves up.
- R formatted correctly all along, but the test used to hang. Three things stacked up:
languageserver answers `shutdown` with `"result": []` where the spec says `null`; lsp-test's
reader thread died decoding that, so the response went unread; and the shutdown wait ran
under `uninterruptibleMask` (unliftio runs `finally` cleanups that way), so no timeout could
fire. Fixed in codedownio/lsp#1, plus a `postPatch` here making languageserver's shutdown
response conformant.

## Known gaps

Expand Down
Loading
Loading