diff --git a/src/ext/searchbox.js b/src/ext/searchbox.js index 75e0c49599..7c8fe5e695 100644 --- a/src/ext/searchbox.js +++ b/src/ext/searchbox.js @@ -214,6 +214,10 @@ class SearchBox { ? editor.session.getTextRange(this.searchRange) : editor.getValue(); + /** + * Convert all line ending variations to Unix-style = \n + * Windows (\r\n), MacOS Classic (\r), and Unix (\n) + */ if (editor.$search.$isMultilineSearch(editor.getLastSearchOptions())) value = value.replace(/\r\n|\r|\n/g, "\n"); diff --git a/src/search.js b/src/search.js index 8f12fd978d..fd0f255aad 100644 --- a/src/search.js +++ b/src/search.js @@ -116,9 +116,12 @@ class Search { row = row + len - 2; } } else { - for (var matches, i = 0; i < lines.length; i++) { + for (var matches, i = 0, lng = lines.length; i < lng; i++) { if (this.$isMultilineSearch(options)) { - matches = this.$multiLineForward(session, re, i, lines.length); + matches = this.$multiLineForward(session, re, i, lng); + var end_row = matches.endRow <= lng ? matches.endRow - 1 : lng; + if (end_row > i) + i = end_row; ranges.push(new Range(matches.startRow, matches.startCol, matches.endRow, matches.endCol)); } else { @@ -240,11 +243,16 @@ class Search { if (!re) return; - if (this.$isMultilineSearch(options)) + /** + * Convert all line ending variations to Unix-style = \n + * Windows (\r\n), MacOS Classic (\r), and Unix (\n) + */ + var mtSearch = this.$isMultilineSearch(options); + if (mtSearch) input = input.replace(/\r\n|\r|\n/g, "\n"); var match = re.exec(input); - if (!match || (!this.$isMultilineSearch(options) && match[0].length != input.length)) + if (!match || (!mtSearch && match[0].length != input.length)) return null; if (options.regExp) { @@ -345,12 +353,12 @@ class Search { var match = re.exec(line); re.lastIndex = 0; if (match) { - var before = line.slice(0, match.index).split("\n"); - var inside = match[0].split("\n"); - var startRow = start + before.length - 1; - var startCol = before[before.length - 1].length; - var endRow = startRow + inside.length - 1; - var endCol = inside.length == 1 ? startCol + inside[0].length : inside[inside.length - 1].length; + var beforeMatch = line.slice(0, match.index).split("\n"); + var matchedText = match[0].split("\n"); + var startRow = start + beforeMatch.length - 1; + var startCol = beforeMatch[beforeMatch.length - 1].length; + var endRow = startRow + matchedText.length - 1; + var endCol = matchedText.length == 1 ? startCol + matchedText[0].length : matchedText[matchedText.length - 1].length; return { startRow: startRow, @@ -376,12 +384,12 @@ class Search { var match = multiLineBackwardMatch(line, re, endMargin); if (match) { - var before = line.slice(0, match.index).split("\n"); - var inside = match[0].split("\n"); - var startRow = row + before.length; - var startCol = before[before.length - 1].length; - var endRow = startRow + inside.length - 1; - var endCol = inside.length == 1 ? startCol + inside[0].length : inside[inside.length - 1].length; + var beforeMatch = line.slice(0, match.index).split("\n"); + var matchedText = match[0].split("\n"); + var startRow = row + beforeMatch.length; + var startCol = beforeMatch[beforeMatch.length - 1].length; + var endRow = startRow + matchedText.length - 1; + var endCol = matchedText.length == 1 ? startCol + matchedText[0].length : matchedText[matchedText.length - 1].length; return { startRow: startRow, @@ -402,7 +410,7 @@ class Search { if (!re) return false; - var multiline = this.$isMultilineSearch(options); + var mtSearch = this.$isMultilineSearch(options); var mtForward = this.$multiLineForward; var mtBackward = this.$multiLineBackward; @@ -473,7 +481,7 @@ class Search { } else if (backwards) { var forEachInLine = function(row, endIndex, callback) { - if (multiline) { + if (mtSearch) { var pos = mtBackward(session, re, endIndex, row, firstRow); if (!pos) return false; @@ -508,8 +516,11 @@ class Search { else { var forEachInLine = function(row, startIndex, callback) { re.lastIndex = startIndex; - if (multiline) { + if (mtSearch) { var pos = mtForward(session, re, row, lastRow); + var end_row = pos.endRow <= lastRow ? pos.endRow - 1 : lastRow; + if (end_row > row) + row = end_row; if (!pos) return false; if (callback(pos.startRow, pos.startCol, pos.endRow, pos.endCol)) diff --git a/src/search_highlight.js b/src/search_highlight.js index 7d39e6ef06..f1a4410e64 100644 --- a/src/search_highlight.js +++ b/src/search_highlight.js @@ -36,15 +36,20 @@ class SearchHighlight { var start = config.firstRow, end = config.lastRow; var renderedMarkerRanges = {}; var _search = session.$editor.$search; - var multiline = _search.$isMultilineSearch(session.$editor.getLastSearchOptions()); + var mtSearch = _search.$isMultilineSearch(session.$editor.getLastSearchOptions()); for (var i = start; i <= end; i++) { var ranges = this.cache[i]; if (ranges == null) { - if (multiline) { + if (mtSearch) { ranges = []; - var matches = _search.$multiLineForward(session, this.regExp, i, end, true); - if (matches) ranges.push(new Range(matches.startRow, matches.startCol, matches.endRow, matches.endCol)); + var match = _search.$multiLineForward(session, this.regExp, i, end); + if (match) { + var end_row = match.endRow <= end ? match.endRow - 1 : end; + if (end_row > i) + i = end_row; + ranges.push(new Range(match.startRow, match.startCol, match.endRow, match.endCol)); + } if (ranges.length > this.MAX_RANGES) ranges = ranges.slice(0, this.MAX_RANGES); }