Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Commit f4cfb5b

Browse files
Remove implicit g flag from snippet transformations
Breaks backward-compatibility, but fixes a bug because this was never supposed to work this way.
1 parent 009b767 commit f4cfb5b

File tree

3 files changed

+56
-13
lines changed

3 files changed

+56
-13
lines changed

lib/snippet-body.pegjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ variableContentChar = !variable char:('\\}' / [^}]) { return char; }
6363
escapedForwardSlash = pair:'\\/' { return pair; }
6464

6565
// A pattern and replacement for a transformed tab stop.
66-
transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[imy]* {
67-
let reFind = new RegExp(find.join(''), flags.join('') + 'g');
66+
transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[gimy]* {
67+
let reFind = new RegExp(find.join(''), flags.join(''));
6868
return { find: reFind, replace: replace[0] };
6969
}
7070

spec/body-parser-spec.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,19 @@ the quick brown $1fox \${2:jumped \${3:over}
6666

6767
it("parses a snippet with transformations", () => {
6868
const bodyTree = BodyParser.parse("<${1:p}>$0</${1/f/F/}>");
69+
expect(bodyTree).toEqual([
70+
'<',
71+
{index: 1, content: ['p']},
72+
'>',
73+
{index: 0, content: []},
74+
'</',
75+
{index: 1, content: [], substitution: {find: /f/, replace: ['F']}},
76+
'>'
77+
]);
78+
});
79+
80+
it("parses a snippet with transformations and a global flag", () => {
81+
const bodyTree = BodyParser.parse("<${1:p}>$0</${1/f/F/g}>");
6982
expect(bodyTree).toEqual([
7083
'<',
7184
{index: 1, content: ['p']},
@@ -78,7 +91,7 @@ the quick brown $1fox \${2:jumped \${3:over}
7891
});
7992

8093
it("parses a snippet with multiple tab stops with transformations", () => {
81-
const bodyTree = BodyParser.parse("${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2");
94+
const bodyTree = BodyParser.parse("${1:placeholder} ${1/(.)/\\u$1/g} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2");
8295
expect(bodyTree).toEqual([
8396
{index: 1, content: ['placeholder']},
8497
' ',
@@ -102,7 +115,7 @@ the quick brown $1fox \${2:jumped \${3:over}
102115
index: 2,
103116
content: [],
104117
substitution: {
105-
find: /^(.*)$/g,
118+
find: /^(.*)$/,
106119
replace: [
107120
{escape: 'L'},
108121
{backreference: 1}
@@ -116,7 +129,7 @@ the quick brown $1fox \${2:jumped \${3:over}
116129

117130

118131
it("parses a snippet with transformations and mirrors", () => {
119-
const bodyTree = BodyParser.parse("${1:placeholder}\n${1/(.)/\\u$1/}\n$1");
132+
const bodyTree = BodyParser.parse("${1:placeholder}\n${1/(.)/\\u$1/g}\n$1");
120133
expect(bodyTree).toEqual([
121134
{index: 1, content: ['placeholder']},
122135
'\n',
@@ -148,7 +161,7 @@ the quick brown $1fox \${2:jumped \${3:over}
148161
index: 1,
149162
content: [],
150163
substitution: {
151-
find: /(.)(.*)/g,
164+
find: /(.)(.*)/,
152165
replace: [
153166
{escape: 'u'},
154167
{backreference: 1},
@@ -174,7 +187,7 @@ the quick brown $1fox \${2:jumped \${3:over}
174187
index: 1,
175188
content: [],
176189
substitution: {
177-
find: /(.)\/(.*)/g,
190+
find: /(.)\/(.*)/,
178191
replace: [
179192
{escape: 'u'},
180193
{backreference: 1},

spec/snippets-spec.js

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,27 +263,27 @@ third tabstop $3\
263263
},
264264
"transform with non-transforming mirrors": {
265265
prefix: "t13",
266-
body: "${1:placeholder}\n${1/(.)/\\u$1/}\n$1"
266+
body: "${1:placeholder}\n${1/(.)/\\u$1/g}\n$1"
267267
},
268268
"multiple tab stops, some with transforms and some without": {
269269
prefix: "t14",
270-
body: "${1:placeholder} ${1/(.)/\\u$1/} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2"
270+
body: "${1:placeholder} ${1/(.)/\\u$1/g} $1 ${2:ANOTHER} ${2/^(.*)$/\\L$1/} $2"
271271
},
272272
"has a transformed tab stop without a corresponding ordinary tab stop": {
273273
prefix: 't15',
274-
body: "${1/(.)/\\u$1/} & $2"
274+
body: "${1/(.)/\\u$1/g} & $2"
275275
},
276276
"has a transformed tab stop that occurs before the corresponding ordinary tab stop": {
277277
prefix: 't16',
278-
body: "& ${1/(.)/\\u$1/} & ${1:q}"
278+
body: "& ${1/(.)/\\u$1/g} & ${1:q}"
279279
},
280280
"has a placeholder that mirrors another tab stop's content": {
281281
prefix: 't17',
282282
body: "$4console.${3:log}('${2:uh $1}', $1);$0"
283283
},
284284
"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": {
285285
prefix: 't18',
286-
body: '// $1\n// ${1/./=/}'
286+
body: '// $1\n// ${1/./=/g}'
287287
},
288288
"has two tab stops adjacent to one another": {
289289
prefix: 't19',
@@ -292,6 +292,14 @@ third tabstop $3\
292292
"has several adjacent tab stops, one of which has a placeholder with reference to another tab stop at its edge": {
293293
prefix: 't20',
294294
body: '${1:foo}${2:bar}${3:baz $1}$4'
295+
},
296+
"banner without global flag": {
297+
prefix: "bannerWrong",
298+
body: "// $1\n// ${1/./=/}"
299+
},
300+
"banner with globalFlag": {
301+
prefix: "bannerCorrect",
302+
body: "// $1\n// ${1/./=/g}"
295303
}
296304
}
297305
});
@@ -902,6 +910,28 @@ foo\
902910
});
903911
});
904912

913+
describe("when the snippet contains a transformation without a global flag", () => {
914+
it("should transform only the first character", () => {
915+
editor.setText('bannerWrong');
916+
editor.setCursorScreenPosition([0, 11]);
917+
simulateTabKeyEvent();
918+
expect(editor.getText()).toBe("// \n// ");
919+
editor.insertText('TEST');
920+
expect(editor.getText()).toBe("// TEST\n// =EST");
921+
});
922+
});
923+
924+
describe("when the snippet contains a transformation with a global flag", () => {
925+
it("should transform all characters", () => {
926+
editor.setText('bannerCorrect');
927+
editor.setCursorScreenPosition([0, 13]);
928+
simulateTabKeyEvent();
929+
expect(editor.getText()).toBe("// \n// ");
930+
editor.insertText('TEST');
931+
expect(editor.getText()).toBe("// TEST\n// ====");
932+
});
933+
});
934+
905935
describe("when the snippet contains multiple tab stops, some with transformations and some without", () => {
906936
it("does not get confused", () => {
907937
editor.setText('t14');
@@ -1189,7 +1219,7 @@ foo\
11891219
atom.workspace.destroyActivePaneItem();
11901220
const configDirPath = temp.mkdirSync('atom-config-dir-');
11911221
spyOn(atom, 'getConfigDirPath').andReturn(configDirPath);
1192-
atom.workspace.open('atom://.atom/snippets');
1222+
atom.workspace.open('atom://.pulsar/snippets');
11931223

11941224
waitsFor(() => atom.workspace.getActiveTextEditor() != null);
11951225

0 commit comments

Comments
 (0)