Skip to content

Add setting and command to show/hide cells in outline#974

Open
vezwork wants to merge 7 commits into
mainfrom
feat/toggle-code-cells-in-outline
Open

Add setting and command to show/hide cells in outline#974
vezwork wants to merge 7 commits into
mainfrom
feat/toggle-code-cells-in-outline

Conversation

@vezwork
Copy link
Copy Markdown
Member

@vezwork vezwork commented May 8, 2026

Fixes #647

Kapture.2026-05-08.at.12.51.44.mp4
  • Adds a symbols.showCodeCellsInOutline setting to the Quarto configuration,
  • Adds a quarto.toggleCodeCellsInOutline command to toggle that setting.

Note: I attempted to add tests but for some reason in the tests the outline / document symbols refuse to change. I tried many things including waiting longer during the test after calling quarto.toggleCodeCellsInOutline, programmatically getting document symbols with vscode.executeDocumentSymbolProvider, looking with my own eyes at the outline during the test. I'm not sure why it doesn't work in the test environment!

@vezwork vezwork requested a review from juliasilge May 8, 2026 16:57
@posit-snyk-bot
Copy link
Copy Markdown
Contributor

posit-snyk-bot commented May 8, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Copy link
Copy Markdown
Collaborator

@juliasilge juliasilge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setting right now is only read when we start the app, so the experience is that the user changes the setting but doesn't observe the behavior change. I think we need to either:

  • add a listener for config change for this setting, OR
  • add a note to the setting description like "Restart to apply" or similar

Comment thread apps/vscode/src/providers/symbols.ts Outdated
Co-authored-by: Julia Silge <julia.silge@gmail.com>
@vezwork
Copy link
Copy Markdown
Member Author

vezwork commented May 14, 2026

This setting right now is only read when we start the app, so the experience is that the user changes the setting but doesn't observe the behavior change.

In my testing in both VSCode and Positron, when I use the "Quarto: Toggle Code Cells in Outline" command the change in the outline is instantly reflected. Are you not experiencing that in your testing? Or do you mean if the user changes the setting manually we should notify them to restart?

@juliasilge
Copy link
Copy Markdown
Collaborator

Or do you mean if the user changes the setting manually we should notify them to restart?

Yep, that's right. Right now, if the user changes the setting, nothing happens until the next time they close/open the app or reload the window. I think the best choice is to use vscode.workspace.onDidChangeConfiguration and a listener like if (event.affectsConfiguration("quarto.symbols.showCodeCellsInOutline")). A less good option that would still be acceptable is to put a note on the setting description that the user will need to restart VS Code/Positron to see the change in behavior.

It also would be worth re-examining the no-op edit hack and seeing if we can either:

  • have the client send a workspace/didChangeConfiguration to the LSP to retrigger the outline generation, OR
  • in the config listener, call vscode.commands.executeCommand("vscode.executeDocumentSymbolProvider", uri) on the active doc, so the toggle command just flips the setting, and the listener owns the refresh

@vezwork
Copy link
Copy Markdown
Member Author

vezwork commented May 19, 2026

@juliasilge I tried both the methods you mentioned and more, but was not able to get the outline to refresh without using the no-op edit hack (VSCode seems to have an outline cache that we can't bust without making an edit to the document?).

I've pulled out the no-op edit hack into onDidChangeConfiguration with if (event.affectsConfiguration("quarto.symbols.showCodeCellsInOutline")) like you suggested, so that we try to refresh the outline no matter how the config was changed.

I tested and this method of refreshing the outline seems to work well.

Kapture.2026-05-19.at.12.16.08.mp4

@juliasilge what do you think? Too hacky and we should tell the user to refresh or make an edit themselves? It seems to work well, so I think I would lean towards using the hack.

@vezwork vezwork requested a review from juliasilge May 19, 2026 16:22
@juliasilge
Copy link
Copy Markdown
Collaborator

@vezwork I pushed 338c145 on top of your work that takes a different swing at the no-op edit hack, plus fixes a related cold-start bug that has been contributing to bad behavior in this area. We can revert that commit if we don't think this is a good way to go but I'd love to pitch you on this different approach! 😅

Part of the bad experience around the outline and why you were needing that no-op edit hack is that reloading the window (or opening VS Code with a previously-open .qmd restored) leaves the outline empty until you close and reopen the file. This was due to the same root cause as why your hack was needed in the first place:

apps/lsp/src/index.ts registers onDocumentSymbol in onInitialize, but mdLs isn't created until partway through onInitialized, after several awaits. Between those events, VS Code sends textDocument/documentSymbol, the handler returns mdLs?.getDocumentSymbols(...) || [] (empty), and VS Code caches that empty response. Without a document change to bust the cache, the outline stays empty until you close/reopen.

There are four main things to keep track of in my commit there:

  1. Dynamic registration of the document symbol provider in onInitialized once mdLs exists, dropping the static documentSymbolProvider: true. Matches the pattern diagnostics.ts already uses. The capability simply isn't visible to VS Code until we can serve it, so the cold-start problem goes away.

  2. Re-register on configManager.onDidChangeConfiguration to bust the client's symbol cache when the setting changes. The LSP spec has no workspace/documentSymbol/refresh, but re-registration is the spec-shaped equivalent. No more synthetic text edit firing onDidChangeTextDocument to every extension watching.

  3. outline.expand after the re-query settles, in a new registerOutlineConfigListener in apps/vscode/src/main.ts. Re-registration causes VS Code to rebuild the tree collapsed (its heuristic when symbol shape changes), and outline.expand restores the visual state. The listener also handles the Settings UI path, too; if you change the setting while a non-Quarto tab is focused like the Settings tab, the expand waits until you switch back to a Quarto editor.

  4. mdLsReady promise that onDocumentSymbol and onFoldingRanges await. Not strictly required for symbols anymore (dynamic registration handles it), but folding ranges has the same race so the gate is useful there too.

There are some tradeoffs compared to what you had in this PR. Your no-op edit hack approach preserved outline expansion state natively; mine loses it on re-registration and we have to explicitly restore it with outline.expand. I do think avoiding the no-op edit is better because the synthetic edit fires onDidChangeTextDocument to every extension watching the doc, and re-registration is the LSP-spec way to invalidate a symbol cache. There is a little remaining quirk still; when the user toggles "show cells", headers that were previously collapsed get expanded too. Probably fine since toggling is rare and most people doing it want to see the cells.

Take a look and see what you think! I'd love to get a better, less risky approach here.

Comment thread apps/vscode/CHANGELOG.md

## 1.133.0

- Add setting and command to show/hide cells in outline (<https://github.com/quarto-dev/quarto/pull/974>)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Add setting and command to show/hide cells in outline (<https://github.com/quarto-dev/quarto/pull/974>)
- Added setting and command to show/hide cells in outline (<https://github.com/quarto-dev/quarto/pull/974>)

For consistency with the rest of this file

@juliasilge
Copy link
Copy Markdown
Collaborator

I was also able to add tests for this in dc5b7cb.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Toggle to show/hide code cells in Outline

3 participants