Skip to content

Commit fcb3a43

Browse files
committed
.replace() support a replacer function - resolves #377
1 parent de83ff7 commit fcb3a43

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

packages/krl-stdlib/src/index.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ stdlib.ord = function(ctx, val){
318318
var code = val.charCodeAt(0);
319319
return _.isNaN(code) ? null : code;
320320
};
321-
stdlib.replace = function(ctx, val, regex, replacement){
321+
stdlib.replace = function*(ctx, val, regex, replacement){
322322
if(arguments.length < 3){
323323
return val;
324324
}
@@ -329,6 +329,21 @@ stdlib.replace = function(ctx, val, regex, replacement){
329329
if(types.isNull(replacement)){
330330
return val.replace(regex, "");
331331
}
332+
if(types.isFunction(replacement)){
333+
regex = stdlib.as(ctx, regex, "RegExp");
334+
var out = "";
335+
var lastI = 0;
336+
var m;
337+
while(m = regex.exec(val)){// eslint-disable-line no-cond-assign
338+
out += val.substring(lastI, m.index) + (yield replacement(ctx, m.concat([m.index, val])));
339+
lastI = m.index + m[0].length;
340+
if(!regex.global){
341+
break;
342+
}
343+
}
344+
out += val.substring(lastI);
345+
return out;
346+
}
332347
return val.replace(regex, types.toString(replacement));
333348
};
334349
stdlib.split = function(ctx, val, split_on){

packages/krl-stdlib/src/tests.js

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,9 @@ test("number operators", function(t){
388388
t.end();
389389
});
390390

391-
test("string operators", function(t){
391+
ytest("string operators", function*(t){
392392
var tf = _.partial(testFn, t);
393+
var ytf = mkTf(t);
393394

394395
tf("sprintf", ["Bob"], "");
395396
tf("sprintf", ["Bob", "Yo"], "Yo");
@@ -433,11 +434,34 @@ test("string operators", function(t){
433434
tf("ord", ["bill"], 98);
434435
tf("ord", ["0"], 48);
435436

436-
tf("replace", ["william W.", /W/i], "illiam W.");
437-
tf("replace", ["William W.", /W/g, "B"], "Billiam B.");
438-
tf("replace", ["Sa5m", 5, true], "Satruem");
439-
tf("replace", [[false, void 0], /(?:)/ig], "[Array]");
440-
tf("replace", [[false, void 0]], [false, void 0]);
437+
yield ytf("replace", ["william W.", /W/i], "illiam W.");
438+
yield ytf("replace", ["William W.", /W/g, "B"], "Billiam B.");
439+
yield ytf("replace", ["Sa5m", 5, true], "Satruem");
440+
yield ytf("replace", [[false, void 0], /(?:)/ig], "[Array]");
441+
yield ytf("replace", [[false, void 0]], [false, void 0]);
442+
443+
yield ytf("replace", ["start 1 then 2? 3-42 end", /(\d+)/g, function(match){
444+
return (parseInt(match, 10) * 2) + "";
445+
}], "start 2 then 4? 6-84 end");
446+
447+
yield ytf("replace", ["1 2 3", /(\d)/g, function(match, p1, offset, string){
448+
t.equals(arguments.length, 4);
449+
t.equals(match, p1);
450+
t.equals(string.substring(offset, offset + p1.length), p1);
451+
t.equals(string, "1 2 3");
452+
return (parseInt(match, 10) * 2) + "";
453+
}], "2 4 6");
454+
455+
yield ytf("replace", ["000abc333???wat", /([a-z]+)(\d*)([^\w]*)/, function(match, p1, p2, p3, offset, string){
456+
t.equals(arguments.length, 6);
457+
t.equals(match, "abc333???");
458+
t.equals(p1, "abc");
459+
t.equals(p2, "333");
460+
t.equals(p3, "???");
461+
t.equals(offset, 3);
462+
t.equals(string, "000abc333???wat");
463+
return "[" + p1 + " - " + p2 + " : " + p3 + "]";
464+
}], "000[abc - 333 : ???]wat");
441465

442466
tf("split", ["a;b;3;4;", /;/], ["a", "b", "3", "4", ""]);
443467
tf("split", ["a;b;3;4;", ""], ["a", ";", "b", ";", "3", ";", "4", ";"]);
@@ -458,8 +482,6 @@ test("string operators", function(t){
458482
tf("substr", [void 0, "Not an index", 2], "null");
459483

460484
tf("uc", ["loWer"], "LOWER");
461-
462-
t.end();
463485
});
464486

465487
ytest("collection operators", function*(t){

0 commit comments

Comments
 (0)