Skip to content

Handle line breaks in bash highlighting - #1217

Merged
amadeus merged 3 commits into
pierrecomputer:mainfrom
pifantastic:fix/bash-line-continuation
Oct 23, 2026
Merged

amadeus merged 3 commits into
pierrecomputer:mainfrom
pifantastic:fix/bash-line-continuation

Conversation

@pifantastic

Copy link
Copy Markdown
Contributor

Description

I was playing around with migrating https://increase.com/documentation/api/overview from shiki to hightlights. I noticed our bash examples were a little off:

shiki:
api-curl-prod

highlights:
api-curl-local

I had Opus 5.5 take a look and it uncovered the issue:

In the bash lexer, an unquoted \ before a line break fell through to the
catch-all branch, which emitted a single byte. The line break then landed in
the next whitespace gap, and the gap handler reset the lexer to command
position. So the first word of every continued line was highlighted as a
command name, e.g. --rm and ubuntu in:

docker run \
  --rm \
  ubuntu bash

A continued line starting with a word like done even got a keyword color.

Changes in packages/highlights/src/langs/bash.wat:

  • A \ directly before LF or CRLF is emitted as punctuation.special and the
    break is consumed as a gap, so $cmd carries over to the joined line. This
    matches how the Dockerfile and Makefile lexers emit their line joins.
  • A \ before any other byte is a string.escape, so \$HOME no longer
    highlights $HOME as a variable.
  • A # heading a joined line still opens a comment, tracked by a new
    $joined local that clears at the next token or real line break.
  • Command position is now computed before the stream checkpoint, so streamed
    and live-edited chunks restore the position the previous line ended in.
    Without this the line-by-line streaming path reintroduced the bug at every
    chunk boundary.
  • A pending heredoc opener keeps its current behavior: the break is left for
    the heredoc body.

packages/highlights/package.json has the regenerated wasm size in meta.

Motivation & Context

Any multi-line bash command using \ continuations rendered wrong: each
continued line's first argument took the command color, and some arguments
took keyword colors. Line continuations are common in shell snippets in docs,
so this showed up in ordinary usage.

Type of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactoring (non-breaking change)
  • New feature (non-breaking change which adds functionality). You must have
    first discussed with the dev team and they should be aware that this PR is
    being opened
  • Breaking change (fix or feature that would change existing functionality).
    You must have first discussed with the dev team and they should be aware
    that this PR is being opened
  • Documentation update

Checklist

  • I have read the
    contributing guidelines
  • My code follows the code style of the project (moon run root:lint)
  • My code is formatted properly (moon run root:format)
  • I have updated the documentation accordingly (if applicable)
  • I have added tests to cover my changes (if applicable)
  • All new and existing tests pass (moonx highlights:test, 2028 tests)

Added bash: a backslash line join keeps the command open in
packages/highlights/test/bash_test.ts. It covers multi-line joins, CRLF, an
assignment prefix before the join, a comment heading a joined line, a blank
line ending the command, and \$ escapes. Each case also asserts whole-input
and line-fed streaming parity via assertLineFedParity.

How was AI used in generating this PR

The fix in bash.wat and the regression test were
written by Claude Code (Claude Opus 5.5) under my direction. I reviewed the
diff and ran the verification baseline locally (format, lint, typecheck, and
the full highlights suite).

Related issues

@vercel

vercel Bot commented Oct 22, 2026

Copy link
Copy Markdown

@pifantastic is attempting to deploy a commit to the Pierre Computer Company Team on Vercel.

A member of the Team first needs to authorize it.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-10-22T21:32:11.818513Z f4639d4 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@vercel

vercel Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pierre-diffshub Ready Ready Preview Oct 23, 2026 6:37pm UTC
pierre-docs-diffs Ready Ready Preview Oct 23, 2026 6:37pm UTC
pierre-docs-trees Ready Ready Preview Oct 23, 2026 6:37pm UTC
pierrejs-diff-demo Ready Ready Preview Oct 23, 2026 6:37pm UTC

Request Review

@amadeus amadeus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thanks for submitting!

@amadeus amadeus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One regression found; details inline.

Comment thread packages/highlights/src/langs/bash.wat Outdated
pifantastic and others added 3 commits October 23, 2026 09:23
A bare backslash fell through to the catch-all branch, so the line break
after it reset the lexer to command position and the first word of every
continued line was highlighted as a command name.

An unquoted `\` before LF or CRLF now joins the next line: it is emitted
as punctuation.special, the break is consumed as a gap, and $cmd carries
over. A `#` heading the joined line still opens a comment. Before any
other byte the `\` is a string.escape. Command position is computed
before the stream checkpoint so streamed and live chunks restore it.
- `\rm` bypasses an alias and still runs `rm`: a `\` before a letter now
  starts a word instead of escaping one byte, so the word stays whole and
  takes command highlighting. `\if` misses the keyword table, and `\VAR=x`
  is not an assignment.
- A `\` as the last byte of the range reads as a line join, matching the
  same `\` before a line break.
- `a\` + `#b` joins into the word `a#b`, so a `#` heading a joined line
  only comments when a blank or command position came before the `\`.
- Correct the comment on a join with a pending heredoc: bash finds the
  body after the joined line, but the lexer still starts it one line early.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A second `\` join cleared $joined and recomputed it from the blank before
that `\`, which a `\` heading its own line never has. A `#` after the run
then lexed as a word, and an apostrophe in it opened a string that
swallowed the rest of the input. $joined now holds through a run of joins
and clears at any other token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amadeus
amadeus merged commit 2204ed3 into pierrecomputer:main Oct 23, 2026
8 checks passed
@amadeus

amadeus commented Oct 23, 2026

Copy link
Copy Markdown
Member

Thanks for submitting the PR and being responsive to the feedback!

This branch was successfully deployed

4 active deployments
Preview – pierre-docs-diffs — bf599741 Deployed Oct 23, 2026 by vercel[bot]
Preview – pierre-docs-trees — bf599741 Deployed Oct 23, 2026 by vercel[bot]
Preview – pierre-diffshub — bf599741 Deployed Oct 23, 2026 by vercel[bot]
Preview – pierrejs-diff-demo — bf599741 Deployed Oct 23, 2026 by vercel[bot]
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.

2 participants