Skip to content

Commit 8762a7b

Browse files
committed
Factor the YAML indent-region skeleton into one emitIndentRegion helper
The block-scalar (`bsKey`, `bsKey-seq`) and plain-fold (`plain-continuation`, `plain-bare-fold`) regions each open-coded the same shape: capture the line's leading indent with `^([ \t]*)` into `\1`, then `while: \G(?=…)` continue while a line is blank or matches a `\1`-relative condition. That shape is the depth-bearing "indent region" — a rule-stack frame remembering one nesting level's indent — so name it once: `emitIndentRegion({ lookahead, cont, blankFirst?, beginCaptures?, patterns })`. The four regions become four-line calls; `blankFirst` keeps the two families' arm order (block scalars list `cont` first, the plain folds list blank first), so the emitted regex is unchanged. The document-root block scalar uses a doc-marker bound, not a `\1`-indent bound, so it stays inline. Pure source dedup: the generated yaml.tmLanguage.json is BYTE-IDENTICAL (git diff empty) and the other six grammars are unchanged; yaml-issue12-regressions 6 pass / 4 known-bug / 0 regression; agnostic 9/9; sanity 15/15; RedCMD Onigmo diagnostics clean; tsc clean.
1 parent 5a8f82b commit 8762a7b

1 file changed

Lines changed: 38 additions & 16 deletions

File tree

src/gen-tm.ts

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,26 @@ function escapeForCharClass(s: string): string {
6868
return s.replace(/[\[\]\\^-]/g, '\\$&');
6969
}
7070

71+
// An INDENT-BOUNDED region: capture the line's leading indent into `\1`, then stay open while each
72+
// following line is BLANK or matches a `\1`-relative continuation condition (`cont`), releasing at a
73+
// sibling/dedent. This is the shared shape of every YAML block-scalar and plain-fold region — the
74+
// depth-bearing "indent region" (a TextMate rule-stack frame that remembers ONE nesting level's indent
75+
// via the `\1` backref). The `^([ \t]*)` capture and the blank-line arm are standard; the caller passes
76+
// the begin `lookahead` (+ optional `beginCaptures`), the `\1`-relative `cont` arm, and the `patterns`.
77+
// `blankFirst` chooses the order of the blank vs `cont` arms in the `while` (block scalars list `cont`
78+
// first; the plain folds list blank first) — kept as a knob so the emitted regex stays byte-identical
79+
// to the prior hand-written regions. (The document-root block scalar uses a doc-marker bound, not a
80+
// `\1`-indent bound, so it is NOT built through this helper.)
81+
function emitIndentRegion(o: { lookahead: string; cont: string; blankFirst?: boolean; beginCaptures?: Record<string, TmCapture>; patterns: (TmPattern | { include: string })[] }): TmPattern {
82+
const blank = '[ \\t]*$';
83+
return {
84+
begin: `^([ \\t]*)${o.lookahead}`,
85+
...(o.beginCaptures ? { beginCaptures: o.beginCaptures } : {}),
86+
while: `\\G(?=${o.blankFirst ? `${blank}|${o.cont}` : `${o.cont}|${blank}`})`,
87+
patterns: o.patterns,
88+
};
89+
}
90+
7191
/**
7292
* Emit the shared "bracket-pair → begin/end region" skeleton.
7393
*
@@ -4799,11 +4819,11 @@ export function generateTmLanguage(grammar: CstGrammar, langName: string): TmGra
47994819
bsHeaderIncludes = bsHeaderIncs;
48004820
bsIndicatorScope = bsIndicator;
48014821
bsContentScope = bsContent;
4802-
repository[bsKey] = {
4803-
begin: `^([ \\t]*)(?=${bsVp}${intro}[\\t ]*(?:#|$))`,
4804-
while: '\\G(?=\\1[ \\t]|[ \\t]*$)',
4822+
repository[bsKey] = emitIndentRegion({
4823+
lookahead: `(?=${bsVp}${intro}[\\t ]*(?:#|$))`,
4824+
cont: '\\1[ \\t]',
48054825
patterns: [bsIntroRule(bsIndicator, bsContent), ...bsHeaderIncs],
4806-
};
4826+
});
48074827
// DOCUMENT-ROOT block scalar (`--- |` / bare `|` at column 0, NO mapping key / sequence dash
48084828
// before it). Such a node sits at the document level, whose indentation is "-1", so its body may
48094829
// begin at COLUMN 0 (W4TN `--- |` / M7A3 bare `|`, both valid YAML). The node-indent–bounded
@@ -4836,12 +4856,12 @@ export function generateTmLanguage(grammar: CstGrammar, langName: string): TmGra
48364856
// leading indent `\1` AND the dash + its trailing spaces `\3`, and the bound `\1[ \t]\3[ \t]` is
48374857
// one column past the key. A pure-space backref (`\1`, `\3`) standing in for the dash column keeps
48384858
// it portable (no literal `- ` backref, which would never match space-indented body lines).
4839-
repository[`${bsKey}-seq`] = {
4840-
begin: `^([ \\t]*)(-)([ \\t]+)(?=(?:[-?][\\t ]+)*[^\\n]*?:[\\t ]+${bsProp}${intro}[\\t ]*(?:#|$))`,
4859+
repository[`${bsKey}-seq`] = emitIndentRegion({
4860+
lookahead: `(-)([ \\t]+)(?=(?:[-?][\\t ]+)*[^\\n]*?:[\\t ]+${bsProp}${intro}[\\t ]*(?:#|$))`,
48414861
beginCaptures: { '2': { name: `punctuation.${langName}` } },
4842-
while: '\\G(?=\\1[ \\t]\\3[ \\t]|[ \\t]*$)',
4862+
cont: '\\1[ \\t]\\3[ \\t]',
48434863
patterns: [bsIntroRule(bsIndicator, bsContent), ...bsHeaderIncs],
4844-
};
4864+
});
48454865
topPatterns.push({ include: `#${bsKey}-seq` });
48464866

48474867
// ── 2a′. Multi-line PLAIN scalar continuation (monogram#12 §6/§7) ──
@@ -4934,11 +4954,12 @@ export function generateTmLanguage(grammar: CstGrammar, langName: string): TmGra
49344954
const continuationRule = { match: '\\G[\\t ]+(?:[^#\\n]|#(?<=[^\\t\\n\\f\\r ]#))*', name: plainContent };
49354955
// Emitted only when the grammar actually has a DEEPER fold (`Indent <leaf> … Dedent`).
49364956
if (fold.hasDeeper) {
4937-
repository['plain-continuation'] = {
4938-
begin: `^([ \\t]*)(?=${plainVp})`,
4939-
while: `\\G(?=[ \\t]*$|\\1[ \\t]+(?!${structAhead}))`,
4957+
repository['plain-continuation'] = emitIndentRegion({
4958+
lookahead: `(?=${plainVp})`,
4959+
cont: `\\1[ \\t]+(?!${structAhead})`,
4960+
blankFirst: true,
49404961
patterns: [continuationRule, ...plainHeaderIncs],
4941-
};
4962+
});
49424963
topPatterns.push({ include: '#plain-continuation' });
49434964
}
49444965

@@ -4972,11 +4993,12 @@ export function generateTmLanguage(grammar: CstGrammar, langName: string): TmGra
49724993
const bareCont = { match: '(?:[^#\\n]|#(?<=[^\\t\\n\\f\\r ]#))+', name: plainContent };
49734994
// Emitted only when the grammar actually has a SAME-COLUMN fold (`Newline <leaf>`).
49744995
if (fold.hasSameColumn) {
4975-
repository['plain-bare-fold'] = {
4976-
begin: `^([ \\t]*)(?=${plainSrc})(?!${structRelease})`,
4977-
while: `\\G(?=[ \\t]*$|\\1(?=[ \\t]*\\S)(?![ \\t]*${structRelease}))`,
4996+
repository['plain-bare-fold'] = emitIndentRegion({
4997+
lookahead: `(?=${plainSrc})(?!${structRelease})`,
4998+
cont: `\\1(?=[ \\t]*\\S)(?![ \\t]*${structRelease})`,
4999+
blankFirst: true,
49785000
patterns: [...plainHeaderIncs, bareCont],
4979-
};
5001+
});
49805002
topPatterns.push({ include: '#plain-bare-fold' });
49815003
}
49825004
}

0 commit comments

Comments
 (0)