search rewrite
This commit is contained in:
parent
675386fc4c
commit
3d774aa2b6
4 changed files with 300 additions and 269 deletions
|
|
@ -1954,65 +1954,84 @@ var Editor = function(renderer, session) {
|
|||
};
|
||||
|
||||
/** related to: Search.find
|
||||
* Editor.find(needle, options)
|
||||
* - needle (String): The text to search for
|
||||
* Editor.find(needle, options)
|
||||
* - needle (String): The text to search for (optional)
|
||||
* - options (Object): An object defining various search properties
|
||||
* - animate (Boolean): If `true` animate scrolling
|
||||
*
|
||||
* Attempts to find `needle` within the document. For more information on `options`, see [[Search `Search`]].
|
||||
**/
|
||||
this.find = function(needle, options, animate) {
|
||||
this.clearSelection();
|
||||
options = options || {};
|
||||
options.needle = needle;
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
if (typeof needle == "string" || needle instanceof RegExp)
|
||||
options.needle = needle;
|
||||
else if (typeof needle == "object")
|
||||
oop.mixin(options, needle);
|
||||
|
||||
var range = this.selection.getRange();
|
||||
if (options.needle == null) {
|
||||
needle = this.session.getTextRange(range)
|
||||
|| this.$search.$options.needle;
|
||||
if (!needle) {
|
||||
range = this.session.getWordRange(range.start.row, range.start.column);
|
||||
needle = this.session.getTextRange(range);
|
||||
}
|
||||
this.$search.set({needle: needle});
|
||||
}
|
||||
|
||||
this.$search.set(options);
|
||||
this.$find(options.backwards, animate);
|
||||
if (!options.start)
|
||||
this.$search.set({start: range});
|
||||
|
||||
var newRange = this.$search.find(this.session);
|
||||
if (options.preventScroll)
|
||||
return newRange;
|
||||
if (newRange) {
|
||||
this.revealRange(newRange, animate);
|
||||
return newRange;
|
||||
}
|
||||
// clear selection if nothing is found
|
||||
if (options.backwards)
|
||||
range.start = range.end;
|
||||
else
|
||||
range.end = range.start;
|
||||
this.selection.setRange(range);
|
||||
};
|
||||
|
||||
/** related to: Editor.find
|
||||
* Editor.findNext(options)
|
||||
* Editor.findNext(options)
|
||||
* - options (Object): search options
|
||||
* - animate (Boolean): If `true` animate scrolling
|
||||
*
|
||||
*
|
||||
* Performs another search for `needle` in the document. For more information on `options`, see [[Search `Search`]].
|
||||
**/
|
||||
this.findNext = function(options, animate) {
|
||||
options = options || {};
|
||||
this.$search.set(options);
|
||||
this.$find(false, animate);
|
||||
this.find({skipCurrent: true, backwards: false}, options, animate);
|
||||
};
|
||||
|
||||
/** related to: Editor.find
|
||||
* Editor.findPrevious(options)
|
||||
* Editor.findPrevious(options)
|
||||
* - options (Object): search options
|
||||
* - animate (Boolean): If `true` animate scrolling
|
||||
*
|
||||
*
|
||||
* Performs a search for `needle` backwards. For more information on `options`, see [[Search `Search`]].
|
||||
**/
|
||||
this.findPrevious = function(options, animate) {
|
||||
options = options || {};
|
||||
this.$search.set(options);
|
||||
this.$find(true, animate);
|
||||
this.find(options, {skipCurrent: true, backwards: true}, animate);
|
||||
};
|
||||
|
||||
this.$find = function(backwards, animate) {
|
||||
if (!this.selection.isEmpty())
|
||||
this.$search.set({needle: this.session.getTextRange(this.getSelectionRange())});
|
||||
this.revealRange = function(range, animate) {
|
||||
this.$blockScrolling += 1;
|
||||
this.session.unfold(range);
|
||||
this.selection.setSelectionRange(range);
|
||||
this.$blockScrolling -= 1;
|
||||
|
||||
if (typeof backwards != "undefined")
|
||||
this.$search.set({backwards: backwards});
|
||||
|
||||
var range = this.$search.find(this.session);
|
||||
if (range) {
|
||||
this.$blockScrolling += 1;
|
||||
this.session.unfold(range);
|
||||
this.selection.setSelectionRange(range);
|
||||
this.$blockScrolling -= 1;
|
||||
|
||||
var scrollTop = this.renderer.scrollTop;
|
||||
this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);
|
||||
var scrollTop = this.renderer.scrollTop;
|
||||
this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);
|
||||
if (animate != false)
|
||||
this.renderer.animateScrolling(scrollTop);
|
||||
}
|
||||
};
|
||||
|
||||
/** related to: UndoManager.undo
|
||||
|
|
|
|||
|
|
@ -116,6 +116,20 @@ exports.escapeRegExp = function(str) {
|
|||
return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
|
||||
};
|
||||
|
||||
exports.getMatchOffsets = function(string, regExp) {
|
||||
var matches = [];
|
||||
|
||||
string.replace(regExp, function(str) {
|
||||
matches.push({
|
||||
offset: arguments[arguments.length-2],
|
||||
length: str.length
|
||||
});
|
||||
});
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
|
||||
exports.deferredCall = function(fcn) {
|
||||
|
||||
var timer = null;
|
||||
|
|
|
|||
|
|
@ -54,35 +54,25 @@ var Range = require("./range").Range;
|
|||
/**
|
||||
* new Search()
|
||||
*
|
||||
* Creates a new `Search` object. The search options contain the following defaults:
|
||||
* Creates a new `Search` object. The following search options ae avaliable:
|
||||
*
|
||||
* * `needle`: `""`
|
||||
* * `backwards`: `false`
|
||||
* * `wrap`: `false`
|
||||
* * `caseSensitive`: `false`
|
||||
* * `wholeWord`: `false`
|
||||
* * `scope`: `ALL`
|
||||
* * `regExp`: `false`
|
||||
* * needle: string or regular expression
|
||||
* * backwards: false
|
||||
* * wrap: false
|
||||
* * caseSensitive: false
|
||||
* * wholeWord: false
|
||||
* * range: Range or null for whole document
|
||||
* * regExp: false
|
||||
* * start: Range or position
|
||||
* * skipCurrent: false
|
||||
*
|
||||
**/
|
||||
|
||||
var Search = function() {
|
||||
this.$options = {
|
||||
needle: "",
|
||||
backwards: false,
|
||||
wrap: false,
|
||||
caseSensitive: false,
|
||||
wholeWord: false,
|
||||
scope: Search.ALL,
|
||||
regExp: false
|
||||
};
|
||||
this.$options = {};
|
||||
};
|
||||
|
||||
Search.ALL = 1;
|
||||
Search.SELECTION = 2;
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
* Search.set(options) -> Search
|
||||
* - options (Object): An object containing all the new search properties
|
||||
|
|
@ -105,6 +95,9 @@ Search.SELECTION = 2;
|
|||
return lang.copyObject(this.$options);
|
||||
};
|
||||
|
||||
this.setOptions = function(options) {
|
||||
this.$options = options;
|
||||
};
|
||||
/**
|
||||
* Search.find(session) -> Range
|
||||
* - session (EditSession): The session to search with
|
||||
|
|
@ -113,17 +106,18 @@ Search.SELECTION = 2;
|
|||
*
|
||||
**/
|
||||
this.find = function(session) {
|
||||
if (!this.$options.needle)
|
||||
return null;
|
||||
|
||||
var iterator = this.$matchIterator(session);
|
||||
var iterator = this.$matchIterator(session, this.$options);
|
||||
|
||||
if (!iterator)
|
||||
return false;
|
||||
|
||||
var firstRange = null;
|
||||
iterator.forEach(function(range) {
|
||||
firstRange = range;
|
||||
iterator.forEach(function(range, row, offset) {
|
||||
if (!range.start) {
|
||||
var column = range.offset + (offset || 0);
|
||||
firstRange = new Range(row, column, row, column+range.length);
|
||||
} else
|
||||
firstRange = range;
|
||||
return true;
|
||||
});
|
||||
|
||||
|
|
@ -141,23 +135,53 @@ Search.SELECTION = 2;
|
|||
var options = this.$options;
|
||||
if (!options.needle)
|
||||
return [];
|
||||
this.$assembleRegExp(options);
|
||||
|
||||
var iterator = this.$matchIterator(session);
|
||||
|
||||
if (!iterator)
|
||||
return false;
|
||||
|
||||
var ignoreCursor = !options.start && options.wrap && options.scope == Search.ALL;
|
||||
if (ignoreCursor)
|
||||
options.start = {row: 0, column: 0};
|
||||
if (options.range) {
|
||||
var range = options.range;
|
||||
var lines = session.getLines(range.start.row, range.end.row);
|
||||
} else
|
||||
var lines = session.doc.getAllLines();
|
||||
|
||||
var ranges = [];
|
||||
iterator.forEach(function(range) {
|
||||
ranges.push(range);
|
||||
});
|
||||
var re = options.re;
|
||||
if (options.$isMultiLine) {
|
||||
var len = re.length;
|
||||
var maxRow = lines.length - len;
|
||||
for (var row = re.offset || 0; row < maxRow; row++) {
|
||||
for (var j = 0; j < re.length; j++)
|
||||
if (lines[row + j].search(re[j]) == -1)
|
||||
break;
|
||||
|
||||
if (ignoreCursor)
|
||||
options.start = null;
|
||||
var startIndex = lines[row + j].match(re[0])[0].length;
|
||||
var endIndex = line.match(re[len - 1])[0].length;
|
||||
|
||||
ranges.push(new Range(
|
||||
row, startLine.length - startIndex,
|
||||
row + len - 1, endIndex
|
||||
));
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var matches = lang.getMatchOffsets(lines[i], re);
|
||||
for (var j = 0; j < matches.length; j++) {
|
||||
var match = matches[j];
|
||||
ranges.push(new Range(i, match.offset, i, match.offset + match.length));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (options.range) {
|
||||
var startColumn = range.start.column;
|
||||
var endColumn = range.start.column;
|
||||
var i = 0, j = ranges.length - 1;
|
||||
while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row)
|
||||
i++;
|
||||
|
||||
while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row)
|
||||
j--;
|
||||
return ranges.slice(i, j + 1);
|
||||
}
|
||||
|
||||
return ranges;
|
||||
};
|
||||
|
|
@ -173,252 +197,195 @@ Search.SELECTION = 2;
|
|||
*
|
||||
**/
|
||||
this.replace = function(input, replacement) {
|
||||
if (!this.$options.regExp)
|
||||
return input == this.$options.needle ? replacement : null;
|
||||
|
||||
var re = this.$assembleRegExp();
|
||||
var options = this.$options;
|
||||
|
||||
var re = this.$assembleRegExp(options);
|
||||
if (options.$isMultiLine)
|
||||
return replacement;
|
||||
|
||||
if (!re)
|
||||
return;
|
||||
|
||||
var match = re.exec(input);
|
||||
if (match && match[0].length == input.length) {
|
||||
return input.replace(re, replacement);
|
||||
}
|
||||
else {
|
||||
if (!match || match[0].length != input.length)
|
||||
return null;
|
||||
|
||||
replacement = input.replace(re, replacement)
|
||||
if (options.preserveCase) {
|
||||
replacement = replacement.split("");
|
||||
for (var i = Math.min(input.length, input.length); i--; ) {
|
||||
var ch = input[i];
|
||||
if (ch && ch.toLowerCase() != ch)
|
||||
replacement[i] = replacement[i].toUpperCase();
|
||||
else
|
||||
replacement[i] = replacement[i].toLowerCase();
|
||||
}
|
||||
replacement = replacement.join("");
|
||||
}
|
||||
|
||||
return replacement;
|
||||
};
|
||||
|
||||
/** internal, hide
|
||||
* Search.$matchIterator(session) -> String | Boolean
|
||||
* - session (EditSession): The session to search with
|
||||
*
|
||||
*
|
||||
*
|
||||
**/
|
||||
this.$matchIterator = function(session) {
|
||||
var re = this.$assembleRegExp();
|
||||
this.$matchIterator = function(session, options) {
|
||||
var re = this.$assembleRegExp(options);
|
||||
if (!re)
|
||||
return false;
|
||||
|
||||
var self = this, callback, backwards = this.$options.backwards;
|
||||
var self = this, callback, backwards = options.backwards;
|
||||
|
||||
if (this.$options.$isMultiLine) {
|
||||
var matchIterator = function(line, startIndex, row) {
|
||||
var startLine = line;
|
||||
if (startIndex)
|
||||
line = line.substring(startIndex);
|
||||
|
||||
var len = re.length;
|
||||
var part = re[0];
|
||||
if (line.slice(-part.length) != part)
|
||||
if (options.$isMultiLine) {
|
||||
var len = re.length;
|
||||
var matchIterator = function(line, row, offset) {
|
||||
var startIndex = line.search(re[0]);
|
||||
if (startIndex == -1)
|
||||
return;
|
||||
|
||||
for (var i = 1; i < len - 1; i++)
|
||||
if (re[i] != session.getLine(row + i))
|
||||
for (var i = 1; i < len; i++) {
|
||||
line = session.getLine(row + i);
|
||||
if (line.search(re[i]) == -1)
|
||||
return;
|
||||
}
|
||||
|
||||
part = re[len - 1];
|
||||
if (session.getLine(row + len - 1).slice(0, part.length) != part)
|
||||
return;
|
||||
var endIndex = line.match(re[len - 1])[0].length;
|
||||
|
||||
var range = new Range(row, startIndex, row + len - 1, endIndex);
|
||||
if (re.offset == 1) {
|
||||
range.start.row--;
|
||||
range.start.column = Number.MAX_VALUE;
|
||||
} else if (offset)
|
||||
range.start.column += offset;
|
||||
|
||||
var range = new Range(
|
||||
row, startLine.length - re[0].length,
|
||||
row + len - 1, re[len - 1].length
|
||||
);
|
||||
if (callback(range))
|
||||
return true;
|
||||
}
|
||||
} else if (backwards) {
|
||||
var matchIterator = function(line, startIndex, row) {
|
||||
if (startIndex)
|
||||
line = line.substring(startIndex);
|
||||
|
||||
var matches = [];
|
||||
|
||||
line.replace(re, function(str) {
|
||||
var offset = arguments[arguments.length-2];
|
||||
matches.push({
|
||||
str: str,
|
||||
offset: startIndex + offset
|
||||
});
|
||||
return str;
|
||||
});
|
||||
|
||||
for (var i=matches.length-1; i>= 0; i--) {
|
||||
var match = matches[i];
|
||||
var range = self.$rangeFromMatch(row, match.offset, match.str.length);
|
||||
if (callback(range))
|
||||
var matchIterator = function(line, row, startIndex) {
|
||||
var matches = lang.getMatchOffsets(line, re);
|
||||
for (var i = matches.length-1; i >= 0; i--)
|
||||
if (callback(matches[i], row, startIndex))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var matchIterator = function(line, startIndex, row) {
|
||||
if (startIndex)
|
||||
line = line.substring(startIndex);
|
||||
|
||||
var matches = [];
|
||||
|
||||
line.replace(re, function(str) {
|
||||
var offset = arguments[arguments.length-2];
|
||||
matches.push({
|
||||
str: str,
|
||||
offset: startIndex + offset
|
||||
});
|
||||
return str;
|
||||
});
|
||||
|
||||
for (var i=0; i<matches.length; i++) {
|
||||
var match = matches[i];
|
||||
var range = self.$rangeFromMatch(row, match.offset, match.str.length);
|
||||
if (callback(range))
|
||||
var matchIterator = function(line, row, startIndex) {
|
||||
var matches = lang.getMatchOffsets(line, re);
|
||||
for (var i = 0; i < matches.length; i++)
|
||||
if (callback(matches[i], row, startIndex))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {forEach: function(_callback) {
|
||||
callback = _callback;
|
||||
self.$lineIterator(session).forEach(matchIterator);
|
||||
}};
|
||||
};
|
||||
|
||||
this.$rangeFromMatch = function(row, column, length) {
|
||||
return new Range(row, column, row, column+length);
|
||||
};
|
||||
|
||||
this.$assembleRegExp = function() {
|
||||
if (typeof this.$options.needle != 'string')
|
||||
return this.$options.needle;
|
||||
|
||||
var needle = this.$options.needle;
|
||||
|
||||
if (!this.$options.regExp) {
|
||||
if (/[\n\r]/.test(needle)){
|
||||
this.$options.$isMultiLine = true;
|
||||
return needle.split(/\r\n|\r|\n/)
|
||||
return {
|
||||
forEach: function(_callback) {
|
||||
callback = _callback;
|
||||
self.$lineIterator(session, options).forEach(matchIterator);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.$assembleRegExp = function(options) {
|
||||
if (options.needle instanceof RegExp)
|
||||
return options.re = options.needle;
|
||||
|
||||
var needle = options.needle;
|
||||
|
||||
if (!options.needle)
|
||||
return options.re = false;
|
||||
|
||||
if (!options.regExp)
|
||||
needle = lang.escapeRegExp(needle);
|
||||
}
|
||||
|
||||
this.$options.$isMultiLine = false;
|
||||
|
||||
if (this.$options.wholeWord) {
|
||||
if (options.wholeWord)
|
||||
needle = "\\b" + needle + "\\b";
|
||||
}
|
||||
|
||||
var modifier = "g";
|
||||
if (!this.$options.caseSensitive) {
|
||||
modifier += "i";
|
||||
}
|
||||
var modifier = options.caseSensitive ? "g" : "gi";
|
||||
|
||||
options.$isMultiLine = /[\n\r]/.test(needle);
|
||||
if (options.$isMultiLine)
|
||||
return options.re = this.$assembleMultilineRegExp(needle, modifier);
|
||||
|
||||
try {
|
||||
var re = new RegExp(needle, modifier);
|
||||
} catch(e) {
|
||||
var re = false;
|
||||
}
|
||||
catch(e) {
|
||||
return options.re = re;
|
||||
};
|
||||
|
||||
this.$assembleMultilineRegExp = function(needle, modifier) {
|
||||
var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n");
|
||||
var re = [];
|
||||
for (var i = 0; i < parts.length; i++) try {
|
||||
re.push(new RegExp(parts[i], modifier));
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parts[0] == "") {
|
||||
re.shift();
|
||||
re.offset = 1;
|
||||
} else {
|
||||
re.offset = 0;
|
||||
}
|
||||
return re;
|
||||
};
|
||||
|
||||
this.$lineIterator = function(session) {
|
||||
var searchSelection = this.$options.scope == Search.SELECTION;
|
||||
var backwards = this.$options.backwards;
|
||||
this.$lineIterator = function(session, options) {
|
||||
var range = options.range;
|
||||
var backwards = options.backwards == true;
|
||||
var skipCurrent = options.skipCurrent != false;
|
||||
|
||||
var range = this.$options.range || session.getSelection().getRange();
|
||||
var start = this.$options.start || range[searchSelection != backwards ? "start" : "end"];
|
||||
var range = options.range;
|
||||
var start = options.start;
|
||||
if (!start)
|
||||
start = range ? range[backwards ? "end" : "start"] : session.selection.getRange();
|
||||
|
||||
if (start.start)
|
||||
start = start[skipCurrent != backwards ? "end" : "start"];
|
||||
|
||||
var firstRow = searchSelection ? range.start.row : 0;
|
||||
var firstColumn = searchSelection ? range.start.column : 0;
|
||||
var lastRow = searchSelection ? range.end.row : session.getLength() - 1;
|
||||
|
||||
var wrap = this.$options.wrap;
|
||||
var inWrap = false;
|
||||
|
||||
function getLine(row) {
|
||||
var line = session.getLine(row);
|
||||
if (searchSelection && row == range.end.row) {
|
||||
line = line.substring(0, range.end.column);
|
||||
}
|
||||
if (inWrap && row == start.row) {
|
||||
line = line.substring(0, start.column);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
var firstRow = range ? range.start.row : 0;
|
||||
var firstColumn = range ? range.start.column : 0;
|
||||
var lastRow = range ? range.end.row : session.getLength() - 1;
|
||||
|
||||
if (!backwards) {
|
||||
var forEach = function(callback) {
|
||||
var row = start.row;
|
||||
|
||||
var line = getLine(row);
|
||||
var startIndex = start.column;
|
||||
var line = session.getLine(row).substr(start.column);
|
||||
if (callback(line, row, start.column))
|
||||
return;
|
||||
|
||||
var stop = false;
|
||||
inWrap = false;
|
||||
|
||||
while (!callback(line, startIndex, row)) {
|
||||
if (stop)
|
||||
for (row = row+1; row <= lastRow; row++)
|
||||
if (callback(session.getLine(row), row))
|
||||
return;
|
||||
|
||||
row++;
|
||||
startIndex = 0;
|
||||
if (options.wrap == false)
|
||||
return;
|
||||
|
||||
if (row > lastRow) {
|
||||
if (wrap) {
|
||||
row = firstRow;
|
||||
startIndex = firstColumn;
|
||||
inWrap = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (row == start.row)
|
||||
stop = true;
|
||||
|
||||
line = getLine(row);
|
||||
}
|
||||
for (row = firstRow, lastRow = start.row; row <= lastRow; row++)
|
||||
if (callback(session.getLine(row), row))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
var forEach = function(callback) {
|
||||
var row = start.row;
|
||||
|
||||
var line = session.getLine(row).substring(0, start.column);
|
||||
var startIndex = 0;
|
||||
var stop = false;
|
||||
var inWrap = false;
|
||||
if (callback(line, row))
|
||||
return;
|
||||
|
||||
while (!callback(line, startIndex, row)) {
|
||||
if (stop)
|
||||
for (row--; row >= firstRow; row--)
|
||||
if (callback(session.getLine(row), row))
|
||||
return;
|
||||
|
||||
row--;
|
||||
startIndex = 0;
|
||||
if (options.wrap == false)
|
||||
return;
|
||||
|
||||
if (row < firstRow) {
|
||||
if (wrap) {
|
||||
row = lastRow;
|
||||
inWrap = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (row == start.row)
|
||||
stop = true;
|
||||
|
||||
line = session.getLine(row);
|
||||
if (searchSelection) {
|
||||
if (row == firstRow)
|
||||
startIndex = firstColumn;
|
||||
else if (row == lastRow)
|
||||
line = line.substring(0, range.end.column);
|
||||
}
|
||||
|
||||
if (inWrap && row == start.row)
|
||||
startIndex = start.column;
|
||||
}
|
||||
for (row = lastRow, firstRow = start.row; row >= firstRow; row--)
|
||||
if (callback(session.getLine(row), row))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ module.exports = {
|
|||
var search = new Search();
|
||||
search.set({
|
||||
needle: "juhu",
|
||||
scope: Search.ALL
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -90,7 +89,7 @@ module.exports = {
|
|||
assert.position(range.end, 1, 12);
|
||||
},
|
||||
|
||||
"test: wrap search is off by default" : function() {
|
||||
"test: wrap search is on by default" : function() {
|
||||
var session = new EditSession(["abc", "juhu kinners 123", "456"]);
|
||||
session.getSelection().moveCursorTo(2, 1);
|
||||
|
||||
|
|
@ -98,7 +97,7 @@ module.exports = {
|
|||
needle: "kinners"
|
||||
});
|
||||
|
||||
assert.equal(search.find(session), null);
|
||||
assert.notEqual(search.find(session), null);
|
||||
},
|
||||
|
||||
"test: wrap search should wrap at file end" : function() {
|
||||
|
|
@ -115,6 +114,20 @@ module.exports = {
|
|||
assert.position(range.end, 1, 12);
|
||||
},
|
||||
|
||||
"test: wrap search should find needle even if it starts inside it" : function() {
|
||||
var session = new EditSession(["abc", "juhu kinners 123", "456"]);
|
||||
session.getSelection().moveCursorTo(6, 1);
|
||||
|
||||
var search = new Search().set({
|
||||
needle: "kinners",
|
||||
wrap: true
|
||||
});
|
||||
|
||||
var range = search.find(session);
|
||||
assert.position(range.start, 1, 5);
|
||||
assert.position(range.end, 1, 12);
|
||||
},
|
||||
|
||||
"test: wrap search with no match should return 'null'": function() {
|
||||
var session = new EditSession(["abc", "juhu kinners 123", "456"]);
|
||||
session.getSelection().moveCursorTo(2, 1);
|
||||
|
|
@ -183,13 +196,19 @@ module.exports = {
|
|||
var search = new Search().set({
|
||||
needle: "juhu",
|
||||
wrap: true,
|
||||
scope: Search.SELECTION
|
||||
range: session.getSelection().getRange()
|
||||
});
|
||||
|
||||
var range = search.find(session);
|
||||
assert.position(range.start, 1, 0);
|
||||
assert.position(range.end, 1, 4);
|
||||
|
||||
search = new Search().set({
|
||||
needle: "juhu",
|
||||
wrap: true,
|
||||
range: session.getSelection().getRange()
|
||||
});
|
||||
|
||||
session.getSelection().setSelectionAnchor(0, 2);
|
||||
session.getSelection().selectTo(3, 2);
|
||||
|
||||
|
|
@ -201,24 +220,32 @@ module.exports = {
|
|||
"test: find backwards in selection": function() {
|
||||
var session = new EditSession(["juhu", "juhu", "juhu", "juhu"]);
|
||||
|
||||
session.getSelection().setSelectionAnchor(0, 2);
|
||||
session.getSelection().selectTo(3, 2);
|
||||
|
||||
var search = new Search().set({
|
||||
needle: "juhu",
|
||||
wrap: true,
|
||||
backwards: true,
|
||||
scope: Search.SELECTION
|
||||
range: session.getSelection().getRange()
|
||||
});
|
||||
|
||||
session.getSelection().setSelectionAnchor(0, 2);
|
||||
session.getSelection().selectTo(3, 2);
|
||||
|
||||
var range = search.find(session);
|
||||
assert.position(range.start, 2, 0);
|
||||
assert.position(range.end, 2, 4);
|
||||
|
||||
search = new Search().set({
|
||||
needle: "juhu",
|
||||
wrap: true,
|
||||
range: session.getSelection().getRange()
|
||||
});
|
||||
|
||||
session.getSelection().setSelectionAnchor(0, 2);
|
||||
session.getSelection().selectTo(1, 2);
|
||||
|
||||
assert.equal(search.find(session), null);
|
||||
var range = search.find(session);
|
||||
assert.position(range.start, 1, 0);
|
||||
assert.position(range.end, 1, 4);
|
||||
},
|
||||
|
||||
"test: edge case - match directly before the cursor" : function() {
|
||||
|
|
@ -295,15 +322,15 @@ module.exports = {
|
|||
"test: find all matches in selection" : function() {
|
||||
var session = new EditSession(["juhu", "juhu", "juhu", "juhu"]);
|
||||
|
||||
session.getSelection().setSelectionAnchor(0, 2);
|
||||
session.getSelection().selectTo(3, 2);
|
||||
|
||||
var search = new Search().set({
|
||||
needle: "uh",
|
||||
wrap: true,
|
||||
scope: Search.SELECTION
|
||||
range: session.getSelection().getRange()
|
||||
});
|
||||
|
||||
session.getSelection().setSelectionAnchor(0, 2);
|
||||
session.getSelection().selectTo(3, 2);
|
||||
|
||||
var ranges = search.findAll(session);
|
||||
|
||||
assert.equal(ranges.length, 2);
|
||||
|
|
@ -322,6 +349,11 @@ module.exports = {
|
|||
assert.equal(search.replace("", "kinners"), null);
|
||||
assert.equal(search.replace(" juhu", "kinners"), null);
|
||||
|
||||
// case sensitivity
|
||||
assert.equal(search.replace("Juhu", "kinners"), "kinners");
|
||||
search.set({caseSensitive: true});
|
||||
assert.equal(search.replace("Juhu", "kinners"), null);
|
||||
|
||||
// regexp replacement
|
||||
},
|
||||
|
||||
|
|
@ -356,7 +388,6 @@ module.exports = {
|
|||
needle: "[ ]+$",
|
||||
regExp: true,
|
||||
wrap: true,
|
||||
scope: Search.ALL
|
||||
});
|
||||
|
||||
session.getSelection().moveCursorTo(1, 2);
|
||||
|
|
@ -404,12 +435,12 @@ module.exports = {
|
|||
var ranges = search.findAll(session);
|
||||
|
||||
assert.equal(ranges.length, 3);
|
||||
assert.position(ranges[0].start, 0, 23);
|
||||
assert.position(ranges[0].end, 0, 26);
|
||||
assert.position(ranges[2].start, 0, 23);
|
||||
assert.position(ranges[2].end, 0, 26);
|
||||
assert.position(ranges[1].start, 0, 8);
|
||||
assert.position(ranges[1].end, 0, 11);
|
||||
assert.position(ranges[2].start, 0, 0);
|
||||
assert.position(ranges[2].end, 0, 3);
|
||||
assert.position(ranges[0].start, 0, 0);
|
||||
assert.position(ranges[0].end, 0, 3);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue