Skip to content

Commit 42a261f

Browse files
committed
Scope a block scalar in explicit-key position as the key name
A block scalar can be a mapping key (`? |` / `? >`) — and since an implicit key must be single-line, a multi-line block-scalar key is ALWAYS `?`-introduced. Monogram already scopes every other scalar key (plain, double- and single-quoted) as entity.name.tag, but a block-scalar key fell to the §2a value region and was scoped string.unquoted.block — an inconsistency in its own model (a block scalar is a scalar; a scalar in key position is the key name). Emit a key-flavoured block-scalar region gated on the explicit-key indicator + block introducer (same begin/end machinery as §2a, body scoped with the key scope), ranked with #explicit-key so its `?`-anchored begin beats the bare `?` punctuation token and the value-position block scalar. A block scalar in VALUE position (`: |`) has no leading `?`, so it is untouched. Derived from the already -detected explicit-key + block-scalar shapes; gated to YAML. YAML scope-gap 99.75% -> 99.92% (tag.name 436->438); the two fixed tokens are ones the official grammar gets wrong (it emits keyword.control.flow.block-scalar), so Monogram now leads on them. Only the DWX9 leading-blank-indent edge remains. Refs #12
1 parent ead6a3d commit 42a261f

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

src/gen-tm.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4658,6 +4658,33 @@ export function generateTmLanguage(grammar: CstGrammar, langName: string): TmGra
46584658
},
46594659
};
46604660
topPatterns.push({ include: '#explicit-key' });
4661+
4662+
// A block scalar can ALSO be an explicit key (`? |` / `? >`). An implicit key must be a single
4663+
// line, so a multi-line block scalar key is ALWAYS `?`-introduced — and like every other scalar
4664+
// key (plain / quoted, both already `entity.name.tag`) its content is the KEY NAME, not a value
4665+
// string. The §2a region scopes a block body `string.unquoted.block`; here the SAME begin/end
4666+
// machinery is gated on the `?` indicator and scopes the introducer + body with the key scope.
4667+
// Leftmost-match makes the `?`-anchored begin win over the bare §2a block scalar; a block scalar
4668+
// in VALUE position (`: |`) has no leading `?`, so it is untouched.
4669+
if (blockScalar) {
4670+
const introClass = `[${blockScalar.introducers.map(escapeForCharClass).join('')}]`;
4671+
const indicators = '(?:[1-9][-+]?|[-+][1-9]?|[-+])?';
4672+
const commentIncs = commentIncludeKeys.map(k => ({ include: `#${k}` }));
4673+
const keyScope = `${explicitKey.keyScope}.${langName}`;
4674+
repository['blockscalar-key'] = {
4675+
begin: `(${escapeRegex(explicitKey.indicator)})([\\t ]+)(${introClass}${indicators})(?=[\\t ]*(?:#|$))(.*\\n?)`,
4676+
beginCaptures: {
4677+
'1': { name: `punctuation.definition.map.key.${langName}` },
4678+
'3': { name: keyScope },
4679+
'4': { patterns: commentIncs },
4680+
},
4681+
end: '^(?=\\S)|(?!\\G)',
4682+
patterns: [
4683+
{ begin: '^([ \\t]+)(?! )', end: '^(?!\\1|[ \\t]*$)', contentName: keyScope },
4684+
],
4685+
};
4686+
topPatterns.push({ include: '#blockscalar-key' });
4687+
}
46614688
}
46624689

46634690
// ── 2c. Flow collections (`{ … }` mapping / `[ … ]` sequence) as nested begin/end regions ──
@@ -7096,6 +7123,11 @@ export function generateTmLanguage(grammar: CstGrammar, langName: string): TmGra
70967123
// An explicit mapping-key rule (`? key`) is the most specific scalar context — its indicator
70977124
// pins the following scalar as a key — so it must be tried before the bare key/plain scalars.
70987125
if (key === 'explicit-key') return 0.8;
7126+
// A block scalar that is an explicit key (`? |` / `? >`) — its `?`-anchored begin must beat the
7127+
// bare `?` punctuation token AND the value-position block scalar so the body scopes as the key
7128+
// name. Its begin is highly specific (`?` + block introducer + blank/comment-only header), so
7129+
// ranking it with #explicit-key is safe. Mutually exclusive with #explicit-key (plain key body).
7130+
if (key === 'blockscalar-key') return 0.8;
70997131
// A flow collection (`{ … }` / `[ … ]`) is a begin/end region opened by a bracket; it must be
71007132
// tried before #punctuation (which would otherwise claim the `{`/`[` as a bare bracket) and
71017133
// before the scalar tokens. Its `{`/`[` can never lead a plain scalar, so this ranking is safe.

yaml.tmLanguage.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
{
1010
"include": "#explicit-key"
1111
},
12+
{
13+
"include": "#blockscalar-key"
14+
},
1215
{
1316
"include": "#flow-sequence"
1417
},
@@ -222,6 +225,32 @@
222225
}
223226
}
224227
},
228+
"blockscalar-key": {
229+
"begin": "(\\?)([\\t ]+)([|>](?:[1-9][-+]?|[-+][1-9]?|[-+])?)(?=[\\t ]*(?:#|$))(.*\\n?)",
230+
"beginCaptures": {
231+
"1": {
232+
"name": "punctuation.definition.map.key.yaml"
233+
},
234+
"3": {
235+
"name": "entity.name.tag.yaml"
236+
},
237+
"4": {
238+
"patterns": [
239+
{
240+
"include": "#comment"
241+
}
242+
]
243+
}
244+
},
245+
"end": "^(?=\\S)|(?!\\G)",
246+
"patterns": [
247+
{
248+
"begin": "^([ \\t]+)(?! )",
249+
"end": "^(?!\\1|[ \\t]*$)",
250+
"contentName": "entity.name.tag.yaml"
251+
}
252+
]
253+
},
225254
"flow-key-double": {
226255
"name": "string.quoted.double.yaml entity.name.tag.yaml",
227256
"begin": "\"",

0 commit comments

Comments
 (0)