isearch: add regexp support

This commit is contained in:
Robert Krahn 2014-11-04 13:01:08 -08:00
commit 7bb5b305be
2 changed files with 67 additions and 10 deletions

View file

@ -64,6 +64,34 @@ function IncrementalSearch() {
oop.inherits(IncrementalSearch, Search); oop.inherits(IncrementalSearch, Search);
// regexp handling
function isRegExp(obj) {
return obj instanceof RegExp;
}
function regExpToObject(re) {
var string = String(re),
start = string.indexOf('/'),
flagStart = string.lastIndexOf('/');
return {
expression: string.slice(start+1, flagStart),
flags: string.slice(flagStart+1)
}
}
function stringToRegExp(string, flags) {
try {
return new RegExp(string, flags);
} catch (e) { return string; }
}
function objectToRegExp(obj) {
return stringToRegExp(obj.expression, obj.flags);
}
// iSearch class
;(function() { ;(function() {
this.activate = function(ed, backwards) { this.activate = function(ed, backwards) {
@ -140,7 +168,9 @@ oop.inherits(IncrementalSearch, Search);
// try to find the next occurence and enable highlighting marker // try to find the next occurence and enable highlighting marker
options.start = this.$currentPos; options.start = this.$currentPos;
var session = this.$editor.session, var session = this.$editor.session,
found = this.find(session); found = this.find(session),
shouldSelect = this.$editor.emacsMark ?
!!this.$editor.emacsMark() : !this.$editor.selection.isEmpty();
if (found) { if (found) {
if (options.backwards) found = Range.fromPoints(found.end, found.start); if (options.backwards) found = Range.fromPoints(found.end, found.start);
this.$editor.moveCursorToPosition(found.end); this.$editor.moveCursorToPosition(found.end);
@ -156,13 +186,21 @@ oop.inherits(IncrementalSearch, Search);
this.addString = function(s) { this.addString = function(s) {
return this.highlightAndFindWithNeedle(false, function(needle) { return this.highlightAndFindWithNeedle(false, function(needle) {
return needle + s; if (!isRegExp(needle))
return needle + s;
var reObj = regExpToObject(needle);
reObj.expression += s;
return objectToRegExp(reObj);
}); });
} }
this.removeChar = function(c) { this.removeChar = function(c) {
return this.highlightAndFindWithNeedle(false, function(needle) { return this.highlightAndFindWithNeedle(false, function(needle) {
return needle.length > 0 ? needle.substring(0, needle.length-1) : needle; if (!isRegExp(needle))
return needle.substring(0, needle.length-1);
var reObj = regExpToObject(needle);
reObj.expression = reObj.expression.substring(0, reObj.expression.length-1);
return objectToRegExp(reObj);
}); });
} }
@ -189,6 +227,18 @@ oop.inherits(IncrementalSearch, Search);
this.addString(text); this.addString(text);
} }
this.convertNeedleToRegExp = function() {
return this.highlightAndFindWithNeedle(false, function(needle) {
return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig');
});
}
this.convertNeedleToString = function() {
return this.highlightAndFindWithNeedle(false, function(needle) {
return isRegExp(needle) ? regExpToObject(needle).expression : needle;
});
}
this.statusMessage = function(found) { this.statusMessage = function(found) {
var options = this.$options, msg = ''; var options = this.$options, msg = '';
msg += options.backwards ? 'reverse-' : ''; msg += options.backwards ? 'reverse-' : '';

View file

@ -35,10 +35,12 @@ if (typeof process !== "undefined") {
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
var config = require("./config");
var EditSession = require("./edit_session").EditSession; var EditSession = require("./edit_session").EditSession;
var Editor = require("./editor").Editor; var Editor = require("./editor").Editor;
var MockRenderer = require("./test/mockrenderer").MockRenderer; var MockRenderer = require("./test/mockrenderer").MockRenderer;
var Range = require("./range").Range; var Range = require("./range").Range;
var MultiSelect = require("./multi_select").MultiSelect;
var assert = require("./test/assertions"); var assert = require("./test/assertions");
var IncrementalSearch = require("./incremental_search").IncrementalSearch; var IncrementalSearch = require("./incremental_search").IncrementalSearch;
@ -69,6 +71,7 @@ module.exports = {
setUp: function() { setUp: function() {
var session = new EditSession(["abc123", "xyz124"]); var session = new EditSession(["abc123", "xyz124"]);
editor = new Editor(new MockRenderer(), session); editor = new Editor(new MockRenderer(), session);
new MultiSelect(editor);
iSearch = new IncrementalSearch(); iSearch = new IncrementalSearch();
}, },
@ -190,13 +193,17 @@ module.exports = {
testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
}, },
"test: extend selection in emacs mark mode" : function() { "test: extend selection in emacs mark mode" : function(next) {
var emacs = require('./keyboard/emacs'); config.loadModule("ace/keyboard/emacs", function(emacs) {
editor.keyBinding.addKeyboardHandler(emacs.handler); // var emacs = require('./keyboard/emacs');
emacs.handler.commands.setMark.exec(editor); editor.keyBinding.addKeyboardHandler(emacs.handler);
iSearch.activate(editor); emacs.handler.commands.setMark.exec(editor);
iSearch.addString('1'); iSearch.addString('2');; iSearch.activate(editor);
testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); iSearch.addString('1'); iSearch.addString('2');
testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
next();
});
} }
}; };