[incremental search] refining forward/backward behavior

This commit is contained in:
Robert Krahn 2013-03-10 09:25:40 -07:00
commit 1423893c3b
2 changed files with 80 additions and 57 deletions

View file

@ -31,7 +31,6 @@
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
var lang = require("./lib/lang");
var oop = require("./lib/oop"); var oop = require("./lib/oop");
var Range = require("./range").Range; var Range = require("./range").Range;
var Search = require("./search").Search; var Search = require("./search").Search;
@ -65,46 +64,51 @@ oop.inherits(IncrementalSearch, Search);
var iSearch = this; var iSearch = this;
iSearch.activate = function(editor) { iSearch.activate = function(editor, backwards) {
this.$editor = editor; this.$editor = editor;
this.$startRange = this.$currentRange = editor.selection.toOrientedRange(); var pos = editor.getCursorPosition();
this.$startRange = this.$currentRange = Range.fromPoints(pos, pos);
// this.$startRange = this.$currentRange = editor.selection.toOrientedRange();
this.installKeyboardHandler(editor); this.installKeyboardHandler(editor);
this.$options.needle = '';
this.$options.backwards = backwards;
} }
this.deactivate = function() { iSearch.deactivate = function(reset) {
this.cancelSearch(reset);
this.uninstallKeyboardHandler(this.$editor); this.uninstallKeyboardHandler(this.$editor);
delete this.$editor; delete this.$editor;
} }
iSearch.cancelSearch = function() { iSearch.cancelSearch = function(reset) {
var session = this.$editor.session, var e = this.$editor;
sel = this.$editor.selection; this.$prevNeedle = this.$options.needle;
this.$options.needle = ''; this.$options.needle = '';
session.highlight(null); e.session.highlight(null);
sel.setRange(this.$startRange); if (reset) e.selection.setRange(this.$startRange);
else e.selection.clearSelection();
return this.$currentRange = this.$startRange; return this.$currentRange = this.$startRange;
} }
iSearch.highlightAndFindWithNeedle = function(dir, moveToNext, needleUpdateFunc) { iSearch.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) {
if (!this.$editor) return null; if (!this.$editor) return null;
dir = dir || 'forward'; var options = this.$options;
var session = this.$editor.session,
options = this.$options;
if (needleUpdateFunc) options.needle = needleUpdateFunc(options.needle || '') || ''; if (needleUpdateFunc) options.needle = needleUpdateFunc(options.needle || '') || '';
if (options.needle.length === 0) { if (options.needle.length === 0) {
return this.cancelSearch(); return this.cancelSearch(true);
} }
if (dir === "forward") {
options.start = moveToNext ? this.$currentRange.end : this.$currentRange.start;
options.backwards = false;
} else {
options.start = moveToNext ? this.$currentRange.start : this.$currentRange.end;
options.backwards = true;
}
var range = this.find(session);
if (!range) range = this.$currentRange;
this.$editor.selection.setRange(range); // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
var session = this.$editor.session, range = this.$currentRange;
if (!options.backwards) {
options.start = moveToNext ? range.end : range.start;
} else {
options.start = moveToNext ? range.start : range.end;
}
range = this.find(session) || range;
// if (dir === "backward") range = Range.fromPoints(range.end, range.start);
this.$editor.selection.setRange(range, options.backwards);
this.$currentRange = range; this.$currentRange = range;
session.highlight(options.re); session.highlight(options.re);
@ -112,58 +116,77 @@ oop.inherits(IncrementalSearch, Search);
} }
this.addChar = function(c) { this.addChar = function(c) {
return this.highlightAndFindWithNeedle('forward', false, function(needle) { return this.highlightAndFindWithNeedle(false, function(needle) {
return needle + c; return needle + c;
}); });
}, }
iSearch.removeChar = function(c) { iSearch.removeChar = function(c) {
return this.highlightAndFindWithNeedle('forward', false, function(needle) { return this.highlightAndFindWithNeedle(false, function(needle) {
return needle.length > 0 ? needle.substring(0, needle.length-1) : needle; return needle.length > 0 ? needle.substring(0, needle.length-1) : needle;
}); });
} }
iSearch.forward = function() { iSearch.next = function(backwards) {
return this.highlightAndFindWithNeedle('forward', true); this.$options.backwards = backwards;
return this.highlightAndFindWithNeedle(true);
} }
iSearch.backward = function() { iSearch.installKeyboardHandler = function(editor) {
return this.highlightAndFindWithNeedle('backward', true); // this.$origKeyboardHandlers = [].concat(editor.keyBinding.$handlers);
} // this.$origKeyboardHandlers.reverse().forEach(function(handler) {
// editor.keyBinding.removeKeyboardHandler(handler);
this.installKeyboardHandler = function(editor) { // });
this.$origKeyboardHandlers = [].concat(editor.keyBinding.$handlers);
this.$origKeyboardHandlers.reverse().forEach(function(handler) {
editor.keyBinding.removeKeyboardHandler(handler);
});
editor.keyBinding.addKeyboardHandler(this.$keyboardHandler); editor.keyBinding.addKeyboardHandler(this.$keyboardHandler);
} }
this.uninstallKeyboardHandler = function(editor) { iSearch.uninstallKeyboardHandler = function(editor) {
editor.keyBinding.removeKeyboardHandler(this.$keyboardHandler); editor.keyBinding.removeKeyboardHandler(this.$keyboardHandler);
if (this.$origKeyboardHandlers) { // if (this.$origKeyboardHandlers) {
this.$origKeyboardHandlers.forEach(function(handler) { // this.$origKeyboardHandlers.forEach(function(handler) {
editor.keyBinding.addKeyboardHandler(handler); // editor.keyBinding.addKeyboardHandler(handler);
}); // });
delete this.$origKeyboardHandlers; // delete this.$origKeyboardHandlers;
} // }
}
iSearch.message = function(msg) {
console.log(msg);
if (this.commandLine)
this.commandLine.setValue(msg, 1);
} }
iSearch.handleKeyboard = function(data, hashId, key, keyCode) { iSearch.handleKeyboard = function(data, hashId, key, keyCode) {
console.log("data: %s, hashId: %s, key: %s, keyCode: %s", this.message("data: " + data + ", hashId: " + hashId + ", key: " + key + ", keyCode: " + keyCode);
data, hashId, key, keyCode); var stop = {command: 'null'},
result = undefined;
console.log(this.$options.needle);
if (hashId === 0) { if (hashId === 0) {
if (key === 'backspace') this.removeChar(); if (key === 'backspace') { this.removeChar(); result = stop; }
else if (key.length === 1) this.addChar(key); if (key === 'return') { this.deactivate(); this.message(''); return stop; }
if (key === 'esc') { this.deactivate(true); this.message(''); return stop; }
if (key.length === 1) { this.addChar(key); result = stop; }
} }
if (hashId === 1) { if (hashId === 1) {
if (key === 's') this.forward(); if (key === 's' || key === 'r') {
if (key === 'r') this.backward(); if (this.$options.needle.length === 0)
this.$options.needle = this.$prevNeedle || '';
this.$options.backwards = key === 'r';
this.forward();
result = stop;
}
if (key === 'g') { this.deactivate(true); this.message(''); return stop; }
// let others handle but don't deactivate iSearch
// stop.passEvent = true;
// return stop;
} }
console.log(this.$options.needle); this.message('isearch: ' + this.$options.needle);
return {command: 'null'} // this.deactivate();
return result;
} }

View file

@ -105,20 +105,20 @@ module.exports = {
"test: forward / backward" : function() { "test: forward / backward" : function() {
iSearch.activate(editor); iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2'); iSearch.addChar('1'); iSearch.addChar('2');
var range = iSearch.forward(); var range = iSearch.next();
testRanges("Range: [1/3] -> [1/5]", [range], "range"); testRanges("Range: [1/3] -> [1/5]", [range], "range");
range = iSearch.forward(); range = iSearch.next();
testRanges("Range: [1/3] -> [1/5]", [range], "range"); testRanges("Range: [1/3] -> [1/5]", [range], "range");
range = iSearch.backward(); range = iSearch.next(true); // backwards
testRanges("Range: [0/3] -> [0/5]", [range], "range"); testRanges("Range: [0/3] -> [0/5]", [range], "range");
}, },
"test: cancelSearch" : function() { "test: cancelSearch" : function() {
iSearch.activate(editor); iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2'); iSearch.addChar('1'); iSearch.addChar('2');
var range = iSearch.cancelSearch(); var range = iSearch.cancelSearch(true);
testRanges("Range: [0/0] -> [0/0]", [range], "range"); testRanges("Range: [0/0] -> [0/0]", [range], "range");
iSearch.addChar('1'); range = iSearch.addChar('2'); iSearch.addChar('1'); range = iSearch.addChar('2');