Skip to content

#| highlighting alternative - #1092

Merged
vezwork merged 8 commits into
mainfrom
hash-pipe-yaml-injection-2
Aug 19, 2026
Merged

#| highlighting alternative#1092
vezwork merged 8 commits into
mainfrom
hash-pipe-yaml-injection-2

Conversation

@vezwork

@vezwork vezwork commented Aug 14, 2026

Copy link
Copy Markdown
Member

Fixes #409

This is an alternative approach to #1084.

This is a duplicate of #1088, which I accidentally merged to main and then reverted. Sorry for confusion.

Screenshot 2026-08-14 at 10 57 15 AM Screenshot 2026-08-14 at 11 01 56 AM

This PR is a very simple change: it adds a yaml injection language for #| comments. This means that our syntax highlighting will delegate to the yaml language highlighter inside of #| comments.

The quarto.tmLanguage change is generated from the build-lang.js script.

IMO this is a more "correct" approach, if you will. We lose control over how the yaml looks, but we shouldn't really have that control anyway (let yaml be yaml)?

Pros

  • very simple
  • uses VSCode's yaml highlighting so it'll match frontmatter (which uses the same injection language approach) and yaml files

Cons

  • yaml highlighting is a little visually intense in default themes (I attempted to address this by setting text opacity to 0.75 using a decoration. I have mild worries about contrast accessibility, perhaps we should add some configuration around this.).
  • possibly has some weird edge cases? I expected multiline yaml stuff to not work well, but it seems to work just fine. I tried using some yaml-feature-test yaml as a hash pipe comment, and it worked well.

Testing note

We could test that the generated tmLanguage delegates #| properly in some examples, in a non-integrated way, by using vscode-textmate and vscode-oniguruma as dependencies in the tests, but that seems a little heavy handed so I didn't do that.

@posit-snyk-bot

posit-snyk-bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

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.

@vezwork vezwork changed the title add #| yaml injection language #| highlighting alternative Aug 14, 2026
This was referenced Aug 14, 2026
@vezwork
vezwork requested a review from juliasilge August 14, 2026 14:59

@juliasilge juliasilge left a comment

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.

I really like this approach, and I prefer it to #1084!

Image

I have some inline comments so we are more consistent about what the special comments are, but I'd also like to ask that we make that background/underline/opacity treatment configurable. Can we add a configuration point similar to quarto.cells.background.color here so that folks can turn this off/on? I think boolean and default on is fine, but I would like to give folks a way to opt out of that visual treatment.

Comment thread apps/vscode/src/providers/background.ts Outdated
const lines: number[] = [];
const lastLine = Math.min(blockRange.end.line, document.lineCount - 1);
for (let i = blockRange.start.line + 1; i <= lastLine; i++) {
if (!/^\s*# ?\|/.test(document.lineAt(i).text)) {

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.

This regex does not match the same lines as Quarto's own option parser. That parser uses optionCommentPattern in cell/options.ts, which expands to /^#\s*\| ?/ for # languages and accepts any whitespace between # and |.

format.ts already imports optionCommentPattern from cell/options.ts so that its code path cannot drift from the option parser. Can we import it here too, instead of making a third copy of this pattern?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmmm. I see what you are saying but I am a bit confused: I played around with quarto render and the preview, and it seems that neither rendering nor previewing respect hash-pipe comments with spaces between i.e. # |. I was trying out:

# | echo: false

1 + 1

which still echoes the cell, v.s.

#| echo: false

1 + 1

which does not echo.

Am I missing something? Or is it the case that we should modify optionCommentPattern to be consistent with how preview and render work?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ok I looked into it a bit more and I now understand that knitr doesn't respect a space between (# |) but otherwise Quarto does. I guess I will not modify optionCommentPattern.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We are now reusing optionCommentPattern in background and build-lang.

Comment thread apps/vscode/syntaxes/build-lang.js Outdated
while: (^|\\G)(?!\\s*([\`~]{3,})\\s*$)
contentName: ${contentName}
patterns:
- begin: ^(\\s*)(#\\|)

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.

This rule matches only #|, but the engine also accepts interior spaces (optionCommentPattern expands to /^#\s*\| ?/), and the decoration in background.ts accepts # |. A line like # | echo: false gets the darker background but no YAML colors. Can we make this pattern match the same lines as optionCommentPattern?

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.

Also, this rule is stamped into every embedded language, but #| is only the option prefix for # comment languages. Cells in other languages use --| (sql, lua), //| (js, ojs, cpp), or %| (matlab) and get no YAML highlighting. The reverse also happens: a literal #| line in a css, json, or yaml block is mis-scoped as active YAML. The generator already emits one definition per language, so we can take the prefix per language (see kLangCommentChars in packages/core/src/jupyter/options.ts).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We now use optionCommentPattern which addressed both of these

Comment thread apps/vscode/syntaxes/build-lang.js Outdated
contentName: ${contentName}
patterns:
- begin: ^(\\s*)(#\\|)
while: ^(\\s*)(#\\|)

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.

This rule fires on any #| run in the cell body, not only the leading run, but Quarto only reads options from the leading run, and the new decoration in background.ts stops at the first non-option line. Is it possible for us to handle this the same way Quarto itself does?

```python
x = 1
#| eval: false
```

Maybe not with the declarative TextMate approach, in which case let's just document it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There's a way with TextMate! We now have a rule that captures option comments until there's a line that doesn't, and then all the rest of the lines get captured by another a separate regex.


function clearEditorHighlightDecorations(editor: vscode.TextEditor) {
editor.setDecorations(highlightingConfig.backgroundDecoration(), []);
editor.setDecorations(cellOptionsBackgroundDecoration, []);

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.

This clears the block decoration and both new cell option decorations, but not highlightingConfig.inlineBackgroundDecoration(). When the document's language mode changes, the inline backgrounds for `r ...` code stay behind on the non-Quarto document. That omission existed before this PR, but since we are adding clear calls here anyway, can we fix it? Just one line to do so, I believe.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

done

Comment thread apps/vscode/src/providers/background.ts Outdated
// to generalize to all languages (//| for js, --| for sql, /*| ... */
// for c, etc.), derive the prefix from the block's language using
// kLangCommentChars/optionCommentPattern in packages/core/src/jupyter/options.ts
function hashPipeLines(

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.

Building on the optionCommentPattern comment I added, the note at lines 256-259 defers //| and --| support, but the pieces already exist and we can bring them in a pretty straightforward way. The block token carries the language (languageNameFromBlock, exported from quarto-core), and kLangCommentChars in cell/options.ts maps each language to its comment prefix. It is private now, so it needs an export. With those two, this function works for js, sql, lua, and ojs cells too, and this third copy of "what is an option line" goes away.

@vezwork vezwork Aug 18, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

same as other comments, done by using optionCommentPattern!

@vezwork

vezwork commented Aug 18, 2026

Copy link
Copy Markdown
Member Author

@juliasilge thanks for the great comments. I have addressed them. I have also added a setting to turn on and off the background/underline/opacity.

I have tested various .qmd files in both VSCode and Positron. I've also tested turning the setting on and off in both.

I think the PR is in a good spot!

@vezwork
vezwork requested a review from juliasilge August 18, 2026 19:15

@juliasilge juliasilge left a comment

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.

This is really nice now! 🤩

I have two comments that it would be great to incorporate before merging, but no need for me to review again unless something comes up.

Comment thread apps/vscode/package.json Outdated
Comment thread apps/vscode/package.json
"markdownDescription": "Millisecond delay between background color updates."
},
"quarto.cells.options.background": {
"order": 23,

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.

order: 23 is already taken by quarto.cells.hoverHelp.enabled (line 998). Every other quarto.cells.* setting has a unique order. With the tie, this one interleaves with the hover-help group in the Settings UI instead of the background settings.

The background group runs 19 to 22, so 23 is the right slot for this setting. Can we shift the other ones:

  • hoverHelp.enabled 23 → 24
  • signatureHelp.enabled 24 → 25
  • diagnostics.enabled 25 → 26
  • diagnostics.debounceDelay 26 → 27
  • useReticulate 27 → 28

@vezwork
vezwork merged commit 2fb57fd into main Aug 19, 2026
5 of 7 checks passed
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.

Add VS Code support to distinguish hash pipe comments from regular comments

3 participants