From 96a271b7b5a22838e0539673f6d0718fd2cf7f20 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 31 May 2024 08:56:34 +0200 Subject: [PATCH] Handle escaped braces in snippet field content FIX: Allow backslash-escaped closing braces inside snippet field names/content. See https://discuss.codemirror.net/t/inserting-literal-via-snippets/8136 --- src/snippet.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/snippet.ts b/src/snippet.ts index 71e71ba..bcd287e 100644 --- a/src/snippet.ts +++ b/src/snippet.ts @@ -48,8 +48,9 @@ class Snippet { let fields: {seq: number | null, name: string}[] = [] let lines = [], positions: FieldPos[] = [], m for (let line of template.split(/\r\n?|\n/)) { - while (m = /[#$]\{(?:(\d+)(?::([^}]*))?|([^}]*))\}/.exec(line)) { - let seq = m[1] ? +m[1] : null, name = m[2] || m[3] || "", found = -1 + while (m = /[#$]\{(?:(\d+)(?::([^}]*))?|((?:\\[{}]|[^}])*))\}/.exec(line)) { + let seq = m[1] ? +m[1] : null, rawName = m[2] || m[3] || "", found = -1 + let name = rawName.replace(/\\[{}]/g, m => m[1]) for (let i = 0; i < fields.length; i++) { if (seq != null ? fields[i].seq == seq : name ? fields[i].name == name : false) found = i } @@ -61,7 +62,7 @@ class Snippet { for (let pos of positions) if (pos.field >= found) pos.field++ } positions.push(new FieldPos(found, lines.length, m.index, m.index + name.length)) - line = line.slice(0, m.index) + name + line.slice(m.index + m[0].length) + line = line.slice(0, m.index) + rawName + line.slice(m.index + m[0].length) } line = line.replace(/\\([{}])/g, (_, brace, index) => { for (let pos of positions) if (pos.line == lines.length && pos.from > index) {