isearch: now supports yanking, and killing text from edit buffer

This commit is contained in:
Robert Krahn 2014-03-04 17:39:30 -08:00
commit 58404df349
4 changed files with 72 additions and 18 deletions

View file

@ -94,14 +94,14 @@ exports.iSearchCommands = [{
}, {
name: "extendSearchTerm",
exec: function(iSearch, string) {
iSearch.addChar(string);
iSearch.addString(string);
},
readOnly: true,
isIncrementalSearchCommand: true
}, {
name: "extendSearchTermSpace",
bindKey: "space",
exec: function(iSearch) { iSearch.addChar(' '); },
exec: function(iSearch) { iSearch.addString(' '); },
readOnly: true,
isIncrementalSearchCommand: true
}, {
@ -134,6 +134,28 @@ exports.iSearchCommands = [{
},
readOnly: true,
isIncrementalSearchCommand: true
}, {
name: "yankNextWord",
bindKey: "Ctrl-w",
exec: function(iSearch) {
var ed = iSearch.$editor,
range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorWordRight(); }),
string = ed.session.getTextRange(range);
iSearch.addString(string);
},
readOnly: true,
isIncrementalSearchCommand: true
}, {
name: "yankNextChar",
bindKey: "Ctrl-Alt-y",
exec: function(iSearch) {
var ed = iSearch.$editor,
range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorRight(); }),
string = ed.session.getTextRange(range);
iSearch.addString(string);
},
readOnly: true,
isIncrementalSearchCommand: true
}];
function IncrementalSearchKeyboardHandler(iSearch) {
@ -163,6 +185,8 @@ oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
var handleKeyboard$super = this.handleKeyboard;
this.handleKeyboard = function(data, hashId, key, keyCode) {
if (((hashId === 1/*ctrl*/ || hashId === 8/*command*/) && key === 'v')
|| (hashId === 1/*ctrl*/ && key === 'y')) return null;
var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
if (cmd.command) { return cmd; }
if (hashId == -1) {

View file

@ -72,7 +72,11 @@ oop.inherits(IncrementalSearch, Search);
this.$options.needle = '';
this.$options.backwards = backwards;
ed.keyBinding.addKeyboardHandler(this.$keyboardHandler);
// we need to completely intercept paste, just registering an event handler does not work
this.$originalEditorOnPaste = ed.onPaste;
ed.onPaste = this.onPaste.bind(this);
this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this));
this.$onPasteHandler = ed.addEventListener('paste', this.onPaste.bind(this));
this.selectionFix(ed);
this.statusMessage(true);
}
@ -84,6 +88,7 @@ oop.inherits(IncrementalSearch, Search);
this.$editor.removeEventListener('mousedown', this.$mousedownHandler);
delete this.$mousedownHandler;
}
this.$editor.onPaste = this.$originalEditorOnPaste;
this.message('');
}
@ -150,9 +155,9 @@ oop.inherits(IncrementalSearch, Search);
return found;
}
this.addChar = function(c) {
this.addString = function(s) {
return this.highlightAndFindWithNeedle(false, function(needle) {
return needle + c;
return needle + s;
});
}
@ -181,6 +186,10 @@ oop.inherits(IncrementalSearch, Search);
return true;
}
this.onPaste = function(text) {
this.addString(text);
}
this.statusMessage = function(found) {
var options = this.$options, msg = '';
msg += options.backwards ? 'reverse-' : '';

View file

@ -95,17 +95,17 @@ module.exports = {
"test: find simple text incrementally" : function() {
iSearch.activate(editor);
var range = iSearch.addChar('1'), // "1"
var range = iSearch.addString('1'), // "1"
highlightRanges = callHighlighterUpdate(editor.session);
testRanges("Range: [0/3] -> [0/4]", [range], "range");
testRanges("Range: [0/3] -> [0/4],Range: [1/3] -> [1/4]", highlightRanges, "highlight");
range = iSearch.addChar('2'); // "12"
range = iSearch.addString('2'); // "12"
highlightRanges = callHighlighterUpdate(editor.session);
testRanges("Range: [0/3] -> [0/5]", [range], "range");
testRanges("Range: [0/3] -> [0/5],Range: [1/3] -> [1/5]", highlightRanges, "highlight");
range = iSearch.addChar('3'); // "123"
range = iSearch.addString('3'); // "123"
highlightRanges = callHighlighterUpdate(editor.session);
testRanges("Range: [0/3] -> [0/6]", [range], "range");
testRanges("Range: [0/3] -> [0/6]", highlightRanges, "highlight");
@ -118,7 +118,7 @@ module.exports = {
"test: forward / backward" : function() {
iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2');
iSearch.addString('1'); iSearch.addString('2');
var range = iSearch.next();
testRanges("Range: [1/3] -> [1/5]", [range], "range");
@ -131,18 +131,18 @@ module.exports = {
"test: cancelSearch" : function() {
iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2');
iSearch.addString('1'); iSearch.addString('2');
var range = iSearch.cancelSearch(true);
testRanges("Range: [0/0] -> [0/0]", [range], "range");
iSearch.addChar('1'); range = iSearch.addChar('2');
iSearch.addString('1'); range = iSearch.addString('2');
testRanges("Range: [0/3] -> [0/5]", [range], "range");
},
"test: failing search keeps pos" : function() {
iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2');
var range = iSearch.addChar('x');
iSearch.addString('1'); iSearch.addString('2');
var range = iSearch.addString('x');
testRanges("", [range], "range");
assert.position(editor.getCursorPosition(), 0, 5);
},
@ -150,14 +150,14 @@ module.exports = {
"test: backwards search" : function() {
editor.moveCursorTo(1,0);
iSearch.activate(editor, true);
iSearch.addChar('1'); var range = iSearch.addChar('2');;
iSearch.addString('1'); var range = iSearch.addString('2');;
testRanges("Range: [0/5] -> [0/3]", [range], "range");
assert.position(editor.getCursorPosition(), 0, 3);
},
"test: forwards then backwards, same result, reoriented range" : function() {
iSearch.activate(editor);
iSearch.addChar('1'); var range = iSearch.addChar('2');;
iSearch.addString('1'); var range = iSearch.addString('2');;
testRanges("Range: [0/3] -> [0/5]", [range], "range");
assert.position(editor.getCursorPosition(), 0, 5);
@ -168,7 +168,7 @@ module.exports = {
"test: reuse prev search via option" : function() {
iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2');;
iSearch.addString('1'); iSearch.addString('2');;
assert.position(editor.getCursorPosition(), 0, 5);
iSearch.deactivate();
@ -179,14 +179,14 @@ module.exports = {
"test: don't extend selection range if selection is empty" : function() {
iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2');;
iSearch.addString('1'); iSearch.addString('2');;
testRanges("Range: [0/5] -> [0/5]", [editor.getSelectionRange()], "sel range");
},
"test: extend selection range if selection exists" : function() {
iSearch.activate(editor);
editor.selection.selectTo(0, 1);
iSearch.addChar('1'); iSearch.addChar('2');;
iSearch.addString('1'); iSearch.addString('2');;
testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
},
@ -195,7 +195,7 @@ module.exports = {
editor.keyBinding.addKeyboardHandler(emacs.handler);
emacs.handler.commands.setMark.exec(editor);
iSearch.activate(editor);
iSearch.addChar('1'); iSearch.addChar('2');;
iSearch.addString('1'); iSearch.addString('2');;
testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range");
}

View file

@ -889,6 +889,27 @@ var Selection = function(session) {
return range;
}
/**
* Saves the current cursor position and calls `func` that can change the cursor
* postion. The result is the range of the starting and eventual cursor position.
* Will reset the cursor position.
* @param {Function} The callback that should change the cursor position
* @returns {Range}
*
**/
this.getRangeOfMovements = function(func) {
var start = this.getCursor();
try {
func.call(null, this);
var end = this.getCursor();
return Range.fromPoints(start,end);
} catch(e) {
return Range.fromPoints(start,start);
} finally {
this.moveCursorToPosition(start);
}
}
this.toJSON = function() {
if (this.rangeCount) {
var data = this.ranges.map(function(r) {