Skip to content

Don't highlight # in interior of heading - #408

Open
jez wants to merge 1 commit into
vim-pandoc:masterfrom
jez:jez-atx-regex
Open

jez wants to merge 1 commit into
vim-pandoc:masterfrom
jez:jez-atx-regex

Conversation

@jez

@jez jez commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

The regex is a bit gnarly, so to break it down, the old regex has two
alternatives:

  • ^#\{1,6}

    Matches 1–6 opening hashes at the start of the line.

  • \\\@<!#\+\(\s*.*$\)\@=

    Matches one or more unescaped hashes when followed by \s*.*$

    It's trying to match the ## at the end of a line, to allow
    highlighting code like this:

    ## Some heading ##

    The problem is that this second condition is effectively always true
    (to see, consider that the regex engine could choose to apply \s
    zero times, then .* until the end of the line).

    That bug causes something like vim-pandoc/vim-pandoc-syntax#404 in
    an ATX heading to treat the # as an additional heading marker.

The new regex fixes that by ensuring that there's at least one space
character before the #, and ensuring that the match highlighting does
not include that required space character (with \zs).

So the full replacement is now:

\(^#\{1,6}\|\s\zs\\\@<!#\+\s*$\)

And its second alternative works like this:

  • \s — whitespace before the closing hashes
  • \zs — begin the highlighted match here, excluding that whitespace
  • \\\@<! — the hash is not escaped
  • #\+ — one or more hashes
  • \s*$ — only optional whitespace may follow before the line ends

The test fixture adds an example, but to my knowledge these are just
used for visual inspection, there's nothing asserting these tests.

Screenshot before: Screenshot after:
Screenshot 2026-09-25 at 11 07 18 AM Screenshot 2026-09-25 at 11 01 44 AM

The regex is a bit gnarly, so to break it down, the old regex has two
alternatives:

- `^#\{1,6}`

  Matches 1–6 opening hashes at the start of the line.

- `\\\@<!#\+\(\s*.*$\)\@=`

  Matches one or more unescaped hashes when followed by `\s*.*$`

  It's trying to match the `##` at the end of a line, to allow
  highlighting code like this:

  ```markdown
  ## Some heading ##
  ```

  The problem is that this second condition is effectively always true
  (to see, consider that the regex engine could choose to apply `\s`
  zero times, then `.*` until the end of the line).

  That bug causes something like `vim-pandoc#404` in
  an ATX heading to treat the `#` as an additional heading marker.

The new regex fixes that by ensuring that there's at least one space
character before the `#`, and ensuring that the match highlighting does
not include that required space character (with `\zs`).

So the full replacement is now:

```vim
\(^#\{1,6}\|\s\zs\\\@<!#\+\s*$\)
```

And its second alternative works like this:

- `\s` — whitespace before the closing hashes
- `\zs` — begin the highlighted match here, excluding that whitespace
- `\\\@<!` — the hash is not escaped
- `#\+` — one or more hashes
- `\s*$` — only optional whitespace may follow before the line ends

The test fixture adds an example, but to my knowledge these are just
used for visual inspection, there's nothing asserting these tests.

Screenshot before:

Screenshot after:
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.

1 participant