Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Added new line and tab as replacement in case of regex search #11614

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/search/FindInFilesUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ define(function (require, exports, module) {
// Single-file scope: don't use any file filters
filter = null;
}

if (queryInfo.isRegexp) {
replaceText = FindUtils.parseString(replaceText);
}

searchAndShowResults(queryInfo, scope, filter, replaceText, candidateFilesPromise);
}
return null;
Expand Down
2 changes: 1 addition & 1 deletion src/search/FindReplace.js
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ define(function (require, exports, module) {
// Delegate to Replace in Files.
FindInFilesUI.searchAndShowResults(state.queryInfo, editor.document.file, null, replaceText);
} else {
cm.replaceSelection(state.queryInfo.isRegexp ? FindUtils.parseDollars(replaceText, state.lastMatch) : replaceText);
cm.replaceSelection(state.queryInfo.isRegexp ? FindUtils.parseRegexp(replaceText, state.lastMatch) : replaceText);

updateResultSet(editor); // we updated the text, so result count & tickmarks must be refreshed

Expand Down
43 changes: 41 additions & 2 deletions src/search/FindUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,43 @@ define(function (require, exports, module) {
return replaceWith;
}

/**
* Parses a string and replace the \r, \n and \t sequences of characters
* with a character based on the regex meaning of these sequences.
* \n => Line Feed
* \r => Carriage Return
* \t => Tab
*
* @param {string} string - The string to parse.
* @return {string} The replaced text.
*/
function parseString(string) {
return string.replace(/\\(.)/g, function (match, ch) {
if (ch === "n") {
return "\n";
}
if (ch === "r") {
return "\r";
}
if (ch === "t") {
return "\t";
}
return ch;
});
}

/**
* Parses a string through parseDollars and parseString functions.
*
* @param {string} string - The string to parse.
* @param {Object} match - The match data from the regexp.
* @return {string} The replaced text.
*/
function parseRegexp(string, match) {
var str = parseDollars(string, match);
return parseString(str);
}

/**
* Does a set of replacements in a single document in memory.
* @param {!Document} doc The document to do the replacements in.
Expand All @@ -126,7 +163,7 @@ define(function (require, exports, module) {
doc.batchOperation(function () {
matchInfo.matches.reverse().forEach(function (match) {
if (match.isChecked) {
doc.replaceRange(isRegexp ? parseDollars(replaceText, match.result) : replaceText, match.start, match.end);
doc.replaceRange(isRegexp ? parseRegexp(replaceText, match.result) : replaceText, match.start, match.end);
}
});
});
Expand Down Expand Up @@ -158,7 +195,7 @@ define(function (require, exports, module) {
matchInfo.matches.forEach(function (match) {
if (match.isChecked) {
result.push(contents.slice(lastIndex, match.startOffset));
result.push(isRegexp ? parseDollars(replaceText, match.result) : replaceText);
result.push(isRegexp ? parseRegexp(replaceText, match.result) : replaceText);
lastIndex = match.endOffset;
}
});
Expand Down Expand Up @@ -518,6 +555,8 @@ define(function (require, exports, module) {
}

exports.parseDollars = parseDollars;
exports.parseString = parseString;
exports.parseRegexp = parseRegexp;
exports.hasCheckedMatches = hasCheckedMatches;
exports.performReplacements = performReplacements;
exports.labelForScope = labelForScope;
Expand Down
31 changes: 31 additions & 0 deletions test/spec/FindInFiles-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,37 @@ define(function (require, exports, module) {
});
});

it("should replace instances of a string in a project with escaped chars", function () {
openTestProjectCopy(defaultSourcePath);
doBasicTest({
queryInfo: {query: "bar"},
numMatches: 7,
replaceText: "\\r\\n\\t",
knownGoodFolder: "replace-escaped-chars"
});
});

it("should replace instances of a string in a project with escaped chars in regex mode", function () {
openTestProjectCopy(defaultSourcePath);
doBasicTest({
queryInfo: {query: "bar", isRegexp: true},
numMatches: 7,
replaceText: "\\\\r\\\\n\\\\t",
knownGoodFolder: "replace-escaped-chars"
});
});

it("should replace instances of a regexp in a project with unescaped chars in regex mode", function () {
openTestProjectCopy(defaultSourcePath, FileUtils.LINE_ENDINGS_LF);
doBasicTest({
queryInfo: {query: "\n", isRegexp: true},
numMatches: 51,
replaceText: "\\t\\r\\n",
knownGoodFolder: "replace-unescaped-chars",
lineEndings: FileUtils.LINE_ENDINGS_CRLF
});
});

it("should replace instances of a string in a project respecting CRLF line endings", function () {
openTestProjectCopy(defaultSourcePath, FileUtils.LINE_ENDINGS_CRLF);
doBasicTest({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
\r\n\t.txt file

This file should *not* show up in certain searches
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* foo.css */
body {
margin: 0;
}
h1, footer {
padding: 2px auto;
}
ul.foo {
list-style: none;
}
.\r\n\t {
font-size: large;
}
22 changes: 22 additions & 0 deletions test/spec/FindReplace-known-goods/replace-escaped-chars/foo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Foo</title>
<link rel="stylesheet" href="css/foo.css">
<script src="foo.js"></script>
</head>

<body>

<h1>Foo</h1>
<p>Intro to foo</p>
<ul class="foo">
<li>foo</li>
<li>\r\n\t</li>
<li>baz</li>
</ul>
<p class="\r\n\t">It's all about the \r\n\t</p>

</body>
</html>
13 changes: 13 additions & 0 deletions test/spec/FindReplace-known-goods/replace-escaped-chars/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Test comment */
define(function (require, exports, module) {
var Foo = require("modules/Foo"),
\r\n\t = require("modules/\r\n\t"),
Baz = require("modules/Baz");

function callFoo() {

foo();

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bar.txt file

This file should *not* show up in certain searches
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* foo.css */
body {
margin: 0;
}
h1, footer {
padding: 2px auto;
}
ul.foo {
list-style: none;
}
.bar {
font-size: large;
}
22 changes: 22 additions & 0 deletions test/spec/FindReplace-known-goods/replace-unescaped-chars/foo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Foo</title>
<link rel="stylesheet" href="css/foo.css">
<script src="foo.js"></script>
</head>

<body>

<h1>Foo</h1>
<p>Intro to foo</p>
<ul class="foo">
<li>foo</li>
<li>bar</li>
<li>baz</li>
</ul>
<p class="bar">It's all about the bar</p>

</body>
</html>
13 changes: 13 additions & 0 deletions test/spec/FindReplace-known-goods/replace-unescaped-chars/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Test comment */
define(function (require, exports, module) {
var Foo = require("modules/Foo"),
Bar = require("modules/Bar"),
Baz = require("modules/Baz");

function callFoo() {

foo();

}

}
64 changes: 64 additions & 0 deletions test/spec/FindReplace-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,70 @@ define(function (require, exports, module) {
expect(/_modules\/Foo-Foo\$&/i.test(myEditor.getSelectedText())).toBe(true);
});
});

it("should replace a string with \\r\\n\\t chars", function () {
runs(function () {
twCommandManager.execute(Commands.CMD_REPLACE);
enterSearchText("Foo");
enterReplaceText("\\r\\n\\t");

var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}};

expectSelection(expectedMatch);
expect(/Foo/.test(myEditor.getSelectedText())).toBe(true);

expect(tw$("#replace-yes").is(":enabled")).toBe(true);
tw$("#replace-yes").click();

myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: 8}, {line: LINE_FIRST_REQUIRE, ch: 14});
expect(myEditor.getSelectedText()).toEqual("\\r\\n\\t");
});
});

it("should replace a string with \\r\\n\\t chars in regex mode", function () {
runs(function () {
twCommandManager.execute(Commands.CMD_REPLACE);
toggleRegexp(true);
enterSearchText("Foo");
enterReplaceText("\\\\r\\\\n\\\\t");

var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}};

expectSelection(expectedMatch);
expect(/Foo/.test(myEditor.getSelectedText())).toBe(true);

expect(tw$("#replace-yes").is(":enabled")).toBe(true);
tw$("#replace-yes").click();

myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: 8}, {line: LINE_FIRST_REQUIRE, ch: 14});
expect(myEditor.getSelectedText()).toEqual("\\r\\n\\t");
});
});

it("should replace a string with a new line and a tab in regex mode", function () {
runs(function () {
var oldLineSeparator = myEditor._codeMirror.getOption("lineSeparator");
myEditor._codeMirror.setOption("lineSeparator", "\r\n");

twCommandManager.execute(Commands.CMD_REPLACE);
toggleRegexp(true);
enterSearchText("Foo");
enterReplaceText("\\r\\n\\t");

var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}};

expectSelection(expectedMatch);
expect(/Foo/.test(myEditor.getSelectedText())).toBe(true);

expect(tw$("#replace-yes").is(":enabled")).toBe(true);
tw$("#replace-yes").click();

myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: 4}, {line: LINE_FIRST_REQUIRE + 1, ch: 3});
expect(myEditor.getSelectedText()).toEqual("var \r\n\t =");

myEditor._codeMirror.setOption("lineSeparator", oldLineSeparator);
});
});
});


Expand Down