find in selection and refactor search code

This commit is contained in:
Fabian Jakobs 2010-04-28 12:44:38 +02:00
commit f655d16a78
2 changed files with 183 additions and 82 deletions

View file

@ -6,7 +6,8 @@ ace.Search = function() {
backwards: false, backwards: false,
wrap: false, wrap: false,
caseSensitive: false, caseSensitive: false,
wholeWord: false wholeWord: false,
scope: ace.Search.ALL
}; };
}; };
@ -32,6 +33,71 @@ ace.Search.SELECTION = 2;
} }
}; };
this.$findForward = function(doc) {
var re = this.$assembleRegExp();
var match = null;
var matchedRow = -1;
this.$forwardLineIterator(doc).forEach(function(line, startIndex, row) {
re.lastIndex = startIndex;
match = re.exec(line);
if (match) {
matchedRow = row;
return true;
}
});
if (!match)
return null;
return this.$rangeFromMatch(matchedRow, match.index, match[0].length);
};
this.$findBackward = function(doc) {
var re = this.$assembleRegExp();
var found = false;
var lastOffset = 0;
var lastRow = -1;
var match = "";
this.$backwardLineIterator(doc).forEach(function(line, startIndex, row) {
if (startIndex) {
line = line.substring(startIndex);
}
line.replace(re, function(str, offset) {
match = str;
found = true;
lastOffset = startIndex + offset;
lastRow = row;
return str;
});
if (found) return true;
});
if (!found) {
return null;
}
return this.$rangeFromMatch(lastRow, lastOffset, match.length);
};
this.$rangeFromMatch = function(row, column, length) {
var range = {
start: {
row: row,
column: column
},
end: {
row: row,
column: column + length
}
};
return range;
};
this.$assembleRegExp = function() { this.$assembleRegExp = function() {
var needle = ace.escapeRegExp(this.$options.needle); var needle = ace.escapeRegExp(this.$options.needle);
if (this.$options.wholeWord) { if (this.$options.wholeWord) {
@ -47,110 +113,98 @@ ace.Search.SELECTION = 2;
return re; return re;
}; };
this.$findForward = function(doc) { this.$forwardLineIterator = function(doc) {
var searchSelection = this.$options.scope == ace.Search.SELECTION;
var range = doc.getSelection().getRange();
var start = doc.getSelection().getCursor(); var start = doc.getSelection().getCursor();
var row = start.row;
var column = start.column;
var startRow = row; var firstRow = searchSelection ? range.start.row : 0;
var firstColumn = searchSelection ? range.start.column : 0;
var lastRow = searchSelection ? range.end.row : doc.getLength() - 1;
var line = doc.getLine(row); var wrap = this.$options.wrap;
var wrapped = false;
var re = this.$assembleRegExp(); function getLine(row) {
re.lastIndex = column; var line = doc.getLine(row);
if (searchSelection && row == range.end.row) {
do { line = line.substring(0, range.end.column);
var match = re.exec(line);
if (!match) {
if (row == startRow && wrapped) {
return null;
}
row++;
if (row >= doc.getLength()) {
if (this.$options.wrap) {
row = 0;
wrapped = true;
} else {
return null;
}
}
line = doc.getLine(row);
re.lastIndex = 0;
} }
} while(!match); return line;
}
var range = { return {
start: { forEach: function(callback) {
row: row, var row = start.row;
column: match.index
}, var line = getLine(row);
end: { startIndex = start.column;
row: row,
column: match.index + match[0].length while (!callback(line, startIndex, row)) {
row++;
startIndex = 0;
if (row > lastRow) {
if (wrap) {
row = firstRow;
startIndex = firstColumn;
} else {
return;
}
}
if (row == start.row)
return;
var line = getLine(row);
}
} }
}; };
return range;
}; };
this.$findBackward = function(doc) { this.$backwardLineIterator = function(doc) {
var start = doc.getSelection().getRange().start; var searchSelection = this.$options.scope == ace.Search.SELECTION;
var row = start.row;
var column = start.column;
var startRow = row; var range = doc.getSelection().getRange();
var start = searchSelection ? range.end : range.start;
var line = doc.getLine(row).substring(0, column); var firstRow = searchSelection ? range.start.row : 0;
var wrapped = false; var firstColumn = searchSelection ? range.start.column : 0;
var lastRow = searchSelection ? range.end.row : doc.getLength() - 1;
var re = this.$assembleRegExp(); var wrap = this.$options.wrap;
var found = false; return {
var lastOffset = 0; forEach : function(callback) {
var match = ""; var row = start.row;
do { var line = doc.getLine(row).substring(0, start.column);
line.replace(re, function(str, offset) { var startIndex = 0;
match = str;
found = true;
lastOffset = offset;
return str;
});
if (!found) { while (!callback(line, startIndex, row)) {
if (row == startRow && wrapped) {
return null;
}
row--; row--;
var startIndex = 0;
if (row < 0) { if (row < firstRow) {
if (this.$options.wrap) { if (wrap) {
row = doc.getLength() - 1; row = lastRow;
wrapped = true; } else {
} else { return null;
}
}
if (row == start.row)
return null; return null;
line = doc.getLine(row);
if (searchSelection && row == firstRow) {
startIndex = firstColumn;
} }
} }
line = doc.getLine(row);
}
} while(!found);
var range = {
start: {
row: row,
column: lastOffset
},
end: {
row: row,
column: lastOffset + match.length
} }
}; };
return range;
}; };
}).call(ace.Search.prototype); }).call(ace.Search.prototype);

View file

@ -26,6 +26,7 @@ var SearchTest = new TestCase("SearchTest", {
}); });
var range = search.find(doc); var range = search.find(doc);
console.log(range)
assertPosition(1, 5, range.start); assertPosition(1, 5, range.start);
assertPosition(1, 12, range.end); assertPosition(1, 12, range.end);
}, },
@ -126,5 +127,51 @@ var SearchTest = new TestCase("SearchTest", {
var range = search.find(doc); var range = search.find(doc);
assertPosition(0, 5, range.start); assertPosition(0, 5, range.start);
assertPosition(0, 9, range.end); assertPosition(0, 9, range.end);
},
"test: find in selection": function() {
var doc = new ace.Document(["juhu", "juhu", "juhu", "juhu"]);
doc.getSelection().setSelectionAnchor(1, 0);
doc.getSelection().selectTo(3, 5);
var search = new ace.Search().set({
needle: "juhu",
wrap: true,
scope: ace.Search.SELECTION
});
var range = search.find(doc);
assertPosition(1, 0, range.start);
assertPosition(1, 4, range.end);
doc.getSelection().setSelectionAnchor(0, 2);
doc.getSelection().selectTo(3, 2);
var range = search.find(doc);
assertPosition(1, 0, range.start);
assertPosition(1, 4, range.end);
},
"test: find backwards in selection": function() {
var doc = new ace.Document(["juhu", "juhu", "juhu", "juhu"]);
var search = new ace.Search().set({
needle: "juhu",
wrap: true,
backwards: true,
scope: ace.Search.SELECTION
});
doc.getSelection().setSelectionAnchor(0, 2);
doc.getSelection().selectTo(3, 2);
var range = search.find(doc);
assertPosition(2, 0, range.start);
assertPosition(2, 4, range.end);
doc.getSelection().setSelectionAnchor(0, 2);
doc.getSelection().selectTo(1, 2);
assertEquals(null, search.find(doc));
} }
}); });