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