move search code to the window model

This commit is contained in:
Fabian Jakobs 2011-08-01 19:29:07 +02:00
commit 6d40f616d5
5 changed files with 157 additions and 128 deletions

View file

@ -74,12 +74,10 @@ var Editor = function(windowView, buffer) {
this.$mouseHandler = new MouseHandler(this); this.$mouseHandler = new MouseHandler(this);
} }
this.$blockScrolling = 0; this.windowModel = this.renderer.model;
this.$search = new Search().set({ this.windowModel.search = new Search().set({
wrap: true wrap: true
}); });
this.windowModel = this.renderer.model;
this.windowController = new WindowController(this.windowModel, this.renderer); this.windowController = new WindowController(this.windowModel, this.renderer);
this.commands = new CommandManager(defaultCommands); this.commands = new CommandManager(defaultCommands);
@ -897,91 +895,27 @@ var Editor = function(windowView, buffer) {
}; };
this.replace = function(replacement, options) { this.replace = function(replacement, options) {
if (options) this.windowModel.replace(replace, options);
this.$search.set(options); };
var range = this.$search.find(this.session);
if (!range)
return;
this.$tryReplace(range, replacement);
if (range !== null)
this.selection.setSelectionRange(range);
},
this.replaceAll = function(replacement, options) { this.replaceAll = function(replacement, options) {
if (options) { this.windowModel.replaceAll(replaceAll, options);
this.$search.set(options);
}
var ranges = this.$search.findAll(this.session);
if (!ranges.length)
return;
var selection = this.getSelectionRange();
this.clearSelection();
this.selection.moveCursorTo(0, 0);
this.$blockScrolling += 1;
for (var i = ranges.length - 1; i >= 0; --i)
this.$tryReplace(ranges[i], replacement);
this.selection.setSelectionRange(selection);
this.$blockScrolling -= 1;
},
this.$tryReplace = function(range, replacement) {
var input = this.session.getTextRange(range);
var replacement = this.$search.replace(input, replacement);
if (replacement !== null) {
range.end = this.session.replace(range, replacement);
return range;
} else {
return null;
}
}; };
this.getLastSearchOptions = function() { this.getLastSearchOptions = function() {
return this.$search.getOptions(); return this.windowModel.getLastSearchOptions();
}; };
this.find = function(needle, options) { this.find = function(needle, options) {
this.clearSelection(); this.windowModel.find(needle, options);
options = options || {}; };
options.needle = needle;
this.$search.set(options);
this.$find();
},
this.findNext = function(options) { this.findNext = function(options) {
options = options || {}; this.windowModel.findNext(options);
if (typeof options.backwards == "undefined")
options.backwards = false;
this.$search.set(options);
this.$find();
}; };
this.findPrevious = function(options) { this.findPrevious = function(options) {
options = options || {}; this.windowModel.findPrevious(options);
if (typeof options.backwards == "undefined")
options.backwards = true;
this.$search.set(options);
this.$find();
};
this.$find = function(backwards) {
if (!this.selection.isEmpty()) {
this.$search.set({needle: this.session.getTextRange(this.getSelectionRange())});
}
if (typeof backwards != "undefined")
this.$search.set({backwards: backwards});
var range = this.$search.find(this.session);
if (range) {
this.gotoLine(range.end.row+1, range.end.column);
this.selection.setSelectionRange(range);
}
}; };
this.undo = function() { this.undo = function() {

View file

@ -38,15 +38,16 @@
if (typeof process !== "undefined") { if (typeof process !== "undefined") {
require("../../support/paths"); require("../../support/paths");
require("ace/test/mockdom");
} }
define(function(require, exports, module) { define(function(require, exports, module) {
var Buffer = require("ace/model/buffer").Buffer; var Buffer = require("ace/model/buffer").Buffer;
var Editor = require("ace/editor").Editor; var Window = require("ace/model/window").Window;
var MockRenderer = require("ace/view/window_view_mock").MockRenderer; var WindowController = require("ace/window_controller").WindowController;
var TextMode = require("ace/mode/text").Mode; var WindowViewMock = require("ace/view/window_view_mock").WindowViewMock;
var Search = require("ace/search").Search;
var assert = require("ace/test/assertions"); var assert = require("ace/test/assertions");
var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
@ -71,37 +72,41 @@ var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
"consectetur"; "consectetur";
module.exports = { module.exports = {
setUp: function(next) { setUp: function(next) {
this.session = new Buffer(lipsum); this.buffer = new Buffer(lipsum);
this.editor = new Editor(new MockRenderer(), this.session); this.selection = this.buffer.getSelection();
this.selection = this.session.getSelection(); this.search = new Search();
this.search = this.editor.$search; this.win = new Window({}, this.search);
this.winController = new WindowController(this.win, new WindowViewMock());
this.win.setBuffer(this.buffer);
next(); next();
}, },
"test: highlight selected words by default": function() { "test: highlight selected words by default": function() {
assert.equal(this.editor.getHighlightSelectedWord(), true); assert.equal(this.win.getHighlightSelectedWord(), true);
}, },
"test: highlight a word": function() { "test: highlight a word": function() {
this.editor.moveCursorTo(0, 9); this.win.moveCursorTo(0, 9);
this.selection.selectWord(); this.selection.selectWord();
var range = this.selection.getRange(); var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "ipsum"); assert.equal(this.buffer.getTextRange(range), "ipsum");
assert.equal(this.session.$selectionOccurrences.length, 1); assert.equal(this.buffer._selectionOccurrences.length, 1);
}, },
"test: highlight a word and clear highlight": function() { "test: highlight a word and clear highlight": function() {
this.editor.moveCursorTo(0, 8); this.win.moveCursorTo(0, 8);
this.selection.selectWord(); this.selection.selectWord();
var range = this.selection.getRange(); var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "ipsum"); assert.equal(this.buffer.getTextRange(range), "ipsum");
assert.equal(this.session.$selectionOccurrences.length, 1); assert.equal(this.buffer._selectionOccurrences.length, 1);
this.session.getMode().clearSelectionHighlight(this.editor); this.buffer.getMode().clearSelectionHighlight(this.win);
assert.equal(this.session.$selectionOccurrences.length, 0); assert.equal(this.buffer._selectionOccurrences.length, 0);
}, },
"test: highlight another word": function() { "test: highlight another word": function() {
@ -109,27 +114,27 @@ module.exports = {
this.selection.selectWord(); this.selection.selectWord();
var range = this.selection.getRange(); var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "dolor"); assert.equal(this.buffer.getTextRange(range), "dolor");
assert.equal(this.session.$selectionOccurrences.length, 3); assert.equal(this.buffer._selectionOccurrences.length, 3);
}, },
"test: no selection, no highlight": function() { "test: no selection, no highlight": function() {
this.selection.clearSelection(); this.selection.clearSelection();
assert.equal(this.session.$selectionOccurrences.length, 0); assert.equal(this.buffer._selectionOccurrences.length, 0);
}, },
"test: select a word, no highlight": function() { "test: select a word, no highlight": function() {
this.editor.setHighlightSelectedWord(false); this.win.setHighlightSelectedWord(false);
this.selection.moveCursorTo(0, 14); this.selection.moveCursorTo(0, 14);
this.selection.selectWord(); this.selection.selectWord();
var range = this.selection.getRange(); var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "dolor"); assert.equal(this.buffer.getTextRange(range), "dolor");
assert.equal(this.session.$selectionOccurrences.length, 0); assert.equal(this.buffer._selectionOccurrences.length, 0);
}, },
"test: select a word with no matches": function() { "test: select a word with no matches": function() {
this.editor.setHighlightSelectedWord(true); this.win.setHighlightSelectedWord(true);
var currentOptions = this.search.getOptions(); var currentOptions = this.search.getOptions();
var newOptions = { var newOptions = {
@ -140,15 +145,15 @@ module.exports = {
}; };
this.search.set(newOptions); this.search.set(newOptions);
var match = this.search.find(this.session); var match = this.search.find(this.buffer);
assert.notEqual(match, null, "found a match for 'Mauris'"); assert.notEqual(match, null, "found a match for 'Mauris'");
this.search.set(currentOptions); this.search.set(currentOptions);
this.selection.setSelectionRange(match); this.selection.setSelectionRange(match);
assert.equal(this.session.getTextRange(match), "Mauris"); assert.equal(this.buffer.getTextRange(match), "Mauris");
assert.equal(this.session.$selectionOccurrences.length, 0); assert.equal(this.buffer._selectionOccurrences.length, 0);
}, },
"test: partial word selection 1": function() { "test: partial word selection 1": function() {
@ -157,8 +162,8 @@ module.exports = {
this.selection.selectLeft(); this.selection.selectLeft();
var range = this.selection.getRange(); var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "dolo"); assert.equal(this.buffer.getTextRange(range), "dolo");
assert.equal(this.session.$selectionOccurrences.length, 0); assert.equal(this.buffer._selectionOccurrences.length, 0);
}, },
"test: partial word selection 2": function() { "test: partial word selection 2": function() {
@ -167,8 +172,8 @@ module.exports = {
this.selection.selectRight(); this.selection.selectRight();
var range = this.selection.getRange(); var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "dolor "); assert.equal(this.buffer.getTextRange(range), "dolor ");
assert.equal(this.session.$selectionOccurrences.length, 0); assert.equal(this.buffer._selectionOccurrences.length, 0);
}, },
"test: partial word selection 3": function() { "test: partial word selection 3": function() {
@ -178,8 +183,8 @@ module.exports = {
this.selection.shiftSelection(1); this.selection.shiftSelection(1);
var range = this.selection.getRange(); var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "olor"); assert.equal(this.buffer.getTextRange(range), "olor");
assert.equal(this.session.$selectionOccurrences.length, 0); assert.equal(this.buffer._selectionOccurrences.length, 0);
}, },
"test: select last word": function() { "test: select last word": function() {
@ -195,7 +200,7 @@ module.exports = {
}; };
this.search.set(newOptions); this.search.set(newOptions);
var match = this.search.find(this.session); var match = this.search.find(this.buffer);
assert.notEqual(match, null, "found a match for 'consectetur'"); assert.notEqual(match, null, "found a match for 'consectetur'");
assert.position(match.start, 1, 0); assert.position(match.start, 1, 0);
@ -203,8 +208,8 @@ module.exports = {
this.selection.setSelectionRange(match); this.selection.setSelectionRange(match);
assert.equal(this.session.getTextRange(match), "consectetur"); assert.equal(this.buffer.getTextRange(match), "consectetur");
assert.equal(this.session.$selectionOccurrences.length, 2); assert.equal(this.buffer._selectionOccurrences.length, 2);
} }
}; };

View file

@ -99,11 +99,11 @@ var Mode = function() {
this.highlightSelection = function(windowModel) { this.highlightSelection = function(windowModel) {
var buffer = windowModel.buffer; var buffer = windowModel.buffer;
if (!buffer.selectionOccurrences) if (!buffer._selectionOccurrences)
buffer.selectionOccurrences = []; buffer._selectionOccurrences = [];
if (buffer.selectionOccurrences.length) if (buffer._selectionOccurrences.length)
this.clearSelectionHighlight(editor); this.clearSelectionHighlight(windowModel);
var selection = windowModel.selection.getRange(); var selection = windowModel.selection.getRange();
if (selection.isEmpty() || selection.isMultiLine()) if (selection.isEmpty() || selection.isMultiLine())
@ -134,8 +134,6 @@ var Mode = function() {
needle: needle needle: needle
}; };
// TODO refactor
/*
var search = windowModel.search; var search = windowModel.search;
var currentOptions = search.getOptions(); var currentOptions = search.getOptions();
search.set(newOptions); search.set(newOptions);
@ -144,25 +142,24 @@ var Mode = function() {
ranges.forEach(function(range) { ranges.forEach(function(range) {
if (!range.contains(cursor.row, cursor.column)) { if (!range.contains(cursor.row, cursor.column)) {
var marker = buffer.addMarker(range, "ace_selected_word", "text"); var marker = buffer.addMarker(range, "ace_selected_word", "text");
buffer.selectionOccurrences.push(marker); buffer._selectionOccurrences.push(marker);
} }
}); });
search.set(currentOptions); search.set(currentOptions);
*/
}; };
this.clearSelectionHighlight = function(windowModel) { this.clearSelectionHighlight = function(windowModel) {
var buffer = windowModel.buffer; var buffer = windowModel.buffer;
if (!buffer.selectionOccurrences) if (!buffer._selectionOccurrences)
return; return;
buffer.selectionOccurrences.forEach(function(marker) { buffer._selectionOccurrences.forEach(function(marker) {
buffer.removeMarker(marker); buffer.removeMarker(marker);
}); });
buffer.selectionOccurrences = []; buffer._selectionOccurrences = [];
}; };
this.createModeDelegates = function (mapping) { this.createModeDelegates = function (mapping) {

View file

@ -45,9 +45,10 @@ var EventEmitter = require("ace/lib/event_emitter").EventEmitter;
/** /**
* A window represents the viewport of a buffer * A window represents the viewport of a buffer
*/ */
var Window = exports.Window = function(theme) { var Window = exports.Window = function(theme, search) {
this.theme = null; this.theme = null;
this.setTheme(theme); this.setTheme(theme);
this.search = search;
this.buffer = null; this.buffer = null;
@ -224,6 +225,95 @@ var Window = exports.Window = function(theme) {
this.selection.moveCursorToPosition(pos); this.selection.moveCursorToPosition(pos);
}; };
// SEARCH
this.replace = function(replacement, options) {
if (options)
this.search.set(options);
var range = this.search.find(this.buffer);
if (!range)
return;
this._tryReplace(range, replacement);
if (range !== null)
this.selection.setSelectionRange(range);
};
this.replaceAll = function(replacement, options) {
if (options)
this._search.set(options);
var ranges = this.search.findAll(this.buffer);
if (!ranges.length)
return;
var selection = this.getSelectionRange();
this.clearSelection();
this.selection.moveCursorTo(0, 0);
this._blockScrolling += 1;
for (var i = ranges.length - 1; i >= 0; --i)
this._tryReplace(ranges[i], replacement);
this.selection.setSelectionRange(selection);
this._blockScrolling -= 1;
};
this._tryReplace = function(range, replacement) {
var input = this.buffer.getTextRange(range);
var replacement = this.search.replace(input, replacement);
if (replacement !== null) {
range.end = this.buffer.replace(range, replacement);
return range;
} else {
return null;
}
};
this.getLastSearchOptions = function() {
return this.search.getOptions();
};
this.find = function(needle, options) {
this.clearSelection();
options = options || {};
options.needle = needle;
this.search.set(options);
this._find();
};
this.findNext = function(options) {
options = options || {};
if (typeof options.backwards == "undefined")
options.backwards = false;
this.search.set(options);
this._find();
};
this.findPrevious = function(options) {
options = options || {};
if (typeof options.backwards == "undefined")
options.backwards = true;
this.search.set(options);
this._find();
};
this._find = function(backwards) {
if (!this.selection.isEmpty()) {
this.search.set({needle: this.buffer.getTextRange(this.getSelectionRange())});
}
if (typeof backwards != "undefined")
this.search.set({backwards: backwards});
var range = this.search.find(this.session);
if (range) {
this.gotoLine(range.end.row+1, range.end.column);
this.selection.setSelectionRange(range);
}
};
// NAVIGATION // NAVIGATION
this.gotoLine = function(lineNumber, column) { this.gotoLine = function(lineNumber, column) {

View file

@ -40,10 +40,10 @@ define(function(require, exports, module) {
var Window = require("ace/model/window").Window; var Window = require("ace/model/window").Window;
exports.MockRenderer = exports.WindowViewMock = WindowViewMock = function(visibleRowCount) { exports.MockRenderer = exports.WindowViewMock = WindowViewMock = function() {
this.container = document.createElement("div"); this.container = {};
this.isWindowViewMock = true; this.isWindowViewMock = true;
this.model = new Window(); this.model = new Window({});
}; };
WindowViewMock.prototype.getContainerElement = function() { WindowViewMock.prototype.getContainerElement = function() {
@ -93,7 +93,10 @@ WindowViewMock.prototype.getSession = function(session) {
"visualizeFocus", "visualizeFocus",
"setAnnotations", "setAnnotations",
"updateScrollLeft", "updateScrollLeft",
"updateScrollTop" "updateScrollTop",
"updateWidth",
"updateHeight",
"on"
].forEach(function(name) { ].forEach(function(name) {
WindowViewMock.prototype[name] = function() {}; WindowViewMock.prototype[name] = function() {};
}) })