diff --git a/lib/snippet-body.pegjs b/lib/snippet-body.pegjs index 476c65af..42bb7dfa 100644 --- a/lib/snippet-body.pegjs +++ b/lib/snippet-body.pegjs @@ -63,8 +63,8 @@ variableContentChar = !variable char:('\\}' / [^}]) { return char; } escapedForwardSlash = pair:'\\/' { return pair; } // A pattern and replacement for a transformed tab stop. -transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[imy]* { - let reFind = new RegExp(find.join(''), flags.join('') + 'g'); +transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[gimy]* { + let reFind = new RegExp(find.join(''), flags.join('')); return { find: reFind, replace: replace[0] }; } diff --git a/package.json b/package.json index cbd9d429..02e30122 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "snippets", - "version": "1.6.1", + "version": "1.7.0", "main": "./lib/snippets", "description": "Expand snippets matching the current prefix with `tab`.", "repository": "https://github.com/atom/snippets", diff --git a/spec/body-parser-spec.js b/spec/body-parser-spec.js index 35492ded..6f048c36 100644 --- a/spec/body-parser-spec.js +++ b/spec/body-parser-spec.js @@ -66,6 +66,19 @@ the quick brown $1fox \${2:jumped \${3:over} it("parses a snippet with transformations", () => { const bodyTree = BodyParser.parse("<${1:p}>$0"); + expect(bodyTree).toEqual([ + '<', + {index: 1, content: ['p']}, + '>', + {index: 0, content: []}, + '' + ]); + }); + + it("parses a snippet with transformations and a global flag", () => { + const bodyTree = BodyParser.parse("<${1:p}>$0"); expect(bodyTree).toEqual([ '<', {index: 1, content: ['p']}, @@ -78,7 +91,7 @@ the quick brown $1fox \${2:jumped \${3:over} }); it("parses a snippet with multiple tab stops with transformations", () => { - const bodyTree = BodyParser.parse("${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2"); + const bodyTree = BodyParser.parse("${1:placeholder} ${1/(.)/\\u$1/g} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2"); expect(bodyTree).toEqual([ {index: 1, content: ['placeholder']}, ' ', @@ -102,7 +115,7 @@ the quick brown $1fox \${2:jumped \${3:over} index: 2, content: [], substitution: { - find: /^(.*)$/g, + find: /^(.*)$/, replace: [ {escape: 'L'}, {backreference: 1} @@ -116,7 +129,7 @@ the quick brown $1fox \${2:jumped \${3:over} it("parses a snippet with transformations and mirrors", () => { - const bodyTree = BodyParser.parse("${1:placeholder}\n${1/(.)/\\u$1/}\n$1"); + const bodyTree = BodyParser.parse("${1:placeholder}\n${1/(.)/\\u$1/g}\n$1"); expect(bodyTree).toEqual([ {index: 1, content: ['placeholder']}, '\n', @@ -148,7 +161,7 @@ the quick brown $1fox \${2:jumped \${3:over} index: 1, content: [], substitution: { - find: /(.)(.*)/g, + find: /(.)(.*)/, replace: [ {escape: 'u'}, {backreference: 1}, @@ -174,7 +187,7 @@ the quick brown $1fox \${2:jumped \${3:over} index: 1, content: [], substitution: { - find: /(.)\/(.*)/g, + find: /(.)\/(.*)/, replace: [ {escape: 'u'}, {backreference: 1}, diff --git a/spec/snippets-spec.js b/spec/snippets-spec.js index d72f9af8..c4b57aa3 100644 --- a/spec/snippets-spec.js +++ b/spec/snippets-spec.js @@ -265,19 +265,19 @@ third tabstop $3\ }, "transform with non-transforming mirrors": { prefix: "t13", - body: "${1:placeholder}\n${1/(.)/\\u$1/}\n$1" + body: "${1:placeholder}\n${1/(.)/\\u$1/g}\n$1" }, "multiple tab stops, some with transforms and some without": { prefix: "t14", - body: "${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2" + body: "${1:placeholder} ${1/(.)/\\u$1/g} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2" }, "has a transformed tab stop without a corresponding ordinary tab stop": { prefix: 't15', - body: "${1/(.)/\\u$1/} & $2" + body: "${1/(.)/\\u$1/g} & $2" }, "has a transformed tab stop that occurs before the corresponding ordinary tab stop": { prefix: 't16', - body: "& ${1/(.)/\\u$1/} & ${1:q}" + body: "& ${1/(.)/\\u$1/g} & ${1:q}" }, "has a placeholder that mirrors another tab stop's content": { prefix: 't17', @@ -285,7 +285,7 @@ third tabstop $3\ }, "has a transformed tab stop such that it is possible to move the cursor between the ordinary tab stop and its transformed version without an intermediate step": { prefix: 't18', - body: '// $1\n// ${1/./=/}' + body: '// $1\n// ${1/./=/g}' }, "has two tab stops adjacent to one another": { prefix: 't19', @@ -294,6 +294,14 @@ third tabstop $3\ "has several adjacent tab stops, one of which has a placeholder with reference to another tab stop at its edge": { prefix: 't20', body: '${1:foo}${2:bar}${3:baz $1}$4' + }, + "banner without global flag": { + prefix: "bannerWrong", + body: "// $1\n// ${1/./=/}" + }, + "banner with globalFlag": { + prefix: "bannerCorrect", + body: "// $1\n// ${1/./=/g}" } } }); @@ -904,6 +912,28 @@ foo\ }); }); + describe("when the snippet contains a transformation without a global flag", () => { + it("should transform only the first character", () => { + editor.setText('bannerWrong'); + editor.setCursorScreenPosition([0, 11]); + simulateTabKeyEvent(); + expect(editor.getText()).toBe("// \n// "); + editor.insertText('TEST'); + expect(editor.getText()).toBe("// TEST\n// =EST"); + }); + }); + + describe("when the snippet contains a transformation with a global flag", () => { + it("should transform all characters", () => { + editor.setText('bannerCorrect'); + editor.setCursorScreenPosition([0, 13]); + simulateTabKeyEvent(); + expect(editor.getText()).toBe("// \n// "); + editor.insertText('TEST'); + expect(editor.getText()).toBe("// TEST\n// ===="); + }); + }); + describe("when the snippet contains multiple tab stops, some with transformations and some without", () => { it("does not get confused", () => { editor.setText('t14');