find in selection and refactor search code
This commit is contained in:
parent
528601eb6c
commit
f655d16a78
2 changed files with 183 additions and 82 deletions
|
|
@ -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 wrap = this.$options.wrap;
|
||||||
|
|
||||||
|
function getLine(row) {
|
||||||
var line = doc.getLine(row);
|
var line = doc.getLine(row);
|
||||||
var wrapped = false;
|
if (searchSelection && row == range.end.row) {
|
||||||
|
line = line.substring(0, range.end.column);
|
||||||
var re = this.$assembleRegExp();
|
|
||||||
re.lastIndex = column;
|
|
||||||
|
|
||||||
do {
|
|
||||||
var match = re.exec(line);
|
|
||||||
if (!match) {
|
|
||||||
if (row == startRow && wrapped) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
forEach: function(callback) {
|
||||||
|
var row = start.row;
|
||||||
|
|
||||||
|
var line = getLine(row);
|
||||||
|
startIndex = start.column;
|
||||||
|
|
||||||
|
while (!callback(line, startIndex, row)) {
|
||||||
|
|
||||||
row++;
|
row++;
|
||||||
|
startIndex = 0;
|
||||||
|
|
||||||
if (row >= doc.getLength()) {
|
if (row > lastRow) {
|
||||||
if (this.$options.wrap) {
|
if (wrap) {
|
||||||
row = 0;
|
row = firstRow;
|
||||||
wrapped = true;
|
startIndex = firstColumn;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
line = doc.getLine(row);
|
if (row == start.row)
|
||||||
re.lastIndex = 0;
|
return;
|
||||||
}
|
|
||||||
} while(!match);
|
|
||||||
|
|
||||||
var range = {
|
var line = getLine(row);
|
||||||
start: {
|
}
|
||||||
row: row,
|
|
||||||
column: match.index
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
row: row,
|
|
||||||
column: match.index + match[0].length
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
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 range = doc.getSelection().getRange();
|
||||||
|
var start = searchSelection ? range.end : range.start;
|
||||||
|
|
||||||
|
var firstRow = searchSelection ? range.start.row : 0;
|
||||||
|
var firstColumn = searchSelection ? range.start.column : 0;
|
||||||
|
var lastRow = searchSelection ? range.end.row : doc.getLength() - 1;
|
||||||
|
|
||||||
|
var wrap = this.$options.wrap;
|
||||||
|
|
||||||
|
return {
|
||||||
|
forEach : function(callback) {
|
||||||
var row = start.row;
|
var row = start.row;
|
||||||
var column = start.column;
|
|
||||||
|
|
||||||
var startRow = row;
|
var line = doc.getLine(row).substring(0, start.column);
|
||||||
|
var startIndex = 0;
|
||||||
|
|
||||||
var line = doc.getLine(row).substring(0, column);
|
while (!callback(line, startIndex, row)) {
|
||||||
var wrapped = false;
|
|
||||||
|
|
||||||
var re = this.$assembleRegExp();
|
|
||||||
|
|
||||||
var found = false;
|
|
||||||
var lastOffset = 0;
|
|
||||||
var match = "";
|
|
||||||
|
|
||||||
do {
|
|
||||||
line.replace(re, function(str, offset) {
|
|
||||||
match = str;
|
|
||||||
found = true;
|
|
||||||
lastOffset = offset;
|
|
||||||
return str;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
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;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
line = doc.getLine(row);
|
if (row == start.row)
|
||||||
}
|
return null;
|
||||||
} while(!found);
|
|
||||||
|
|
||||||
var range = {
|
line = doc.getLine(row);
|
||||||
start: {
|
if (searchSelection && row == firstRow) {
|
||||||
row: row,
|
startIndex = firstColumn;
|
||||||
column: lastOffset
|
}
|
||||||
},
|
}
|
||||||
end: {
|
|
||||||
row: row,
|
|
||||||
column: lastOffset + match.length
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return range;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(ace.Search.prototype);
|
}).call(ace.Search.prototype);
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue