Skip to content

fix: treat bare parentheses as literals (Fixes #171) - #212

Closed
dyk1454683243-sudo wants to merge 2 commits into
micromatch:masterfrom
dyk1454683243-sudo:cursor/literal-parens-171-9629
Closed

dyk1454683243-sudo wants to merge 2 commits into
micromatch:masterfrom
dyk1454683243-sudo:cursor/literal-parens-171-9629

Conversation

@dyk1454683243-sudo

@dyk1454683243-sudo dyk1454683243-sudo commented Sep 20, 2026 •

Copy link
Copy Markdown

Fixes #171

Problem

Unprefixed parentheses in a glob were compiled as regex capture groups, so a pattern like /foo/(a) matched /foo/a. That happens with or without noextglob: true, because noextglob only disables extglob prefixes (?(, *(, +(, @(, !() and does not change how a bare ( is compiled.

Bash treats bare ( / ) as literals. Expected match is false:

picomatch('/foo/(a)', { noextglob: true })('/foo/a')  // was true, want false
picomatch('/foo/(a)', { noextglob: false })('/foo/a') // was true, want false

Fix

In the parse/compile path, compile bare ( and ) as literal characters unless they form a real grouping construct:

  • extglobs: ?(, *(, +(, @(, !(
  • regex extensions: (?:, lookarounds
  • groups whose body needs grouping (|, wildcards, slashes, escapes)
  • quantified groups such as (a)* and (a)+

Inert wraps such as (a) stay literal, so /foo/(a) matches /foo/(a) and not /foo/a. Existing extglob behavior is unchanged.

Tests

  • Regression coverage for the issue repro (with and without noextglob), plus checks that real extglobs still match
  • Existing assertions that treated a plain (literal) wrap as a no-op capture group were updated to the bash-compatible result
  • npx mocha --reporter spec: 1999 passing
  • npx eslint on the touched files: clean

dyk1454683243-sudo and others added 2 commits September 20, 2026 20:10
Unprefixed `(...)` wraps were compiled as capture groups, so `/foo/(a)`
matched `/foo/a` even with `noextglob: true`. Bash treats bare `(` / `)`
as literals; only extglobs (`?(`, `*(`, `+(`, `@(`, `!(`) and regex
extensions (`(?:`, lookarounds) or groups whose body needs grouping
(`|`, wildcards, slashes) stay special.

Fixes micromatch#171

Co-authored-by: David <dyk1454683243-sudo@users.noreply.github.com>
Keep grouping for extglobs, regex extensions, quantified groups, and
paren bodies that contain `|`, wildcards, slashes, or escapes. Update
assertions that treated a plain `(literal)` wrap as a no-op capture
group so the suite stays green with the micromatch#171 fix.

Co-authored-by: David <dyk1454683243-sudo@users.noreply.github.com>
@dyk1454683243-sudo

Copy link
Copy Markdown
Author

Withdrawing this PR while I clean up a high-volume open-PR backlog. Sorry for the noise — happy to come back later with a focused change if useful.

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.

Parentheses are not treated as literal characters

1 participant