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.$blockScrolling = 0;
this.$search = new Search().set({
this.windowModel = this.renderer.model;
this.windowModel.search = new Search().set({
wrap: true
});
this.windowModel = this.renderer.model;
this.windowController = new WindowController(this.windowModel, this.renderer);
this.commands = new CommandManager(defaultCommands);
@ -897,91 +895,27 @@ var Editor = function(windowView, buffer) {
};
this.replace = function(replacement, options) {
if (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.windowModel.replace(replace, options);
};
this.replaceAll = function(replacement, options) {
if (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.windowModel.replaceAll(replaceAll, options);
};
this.getLastSearchOptions = function() {
return this.$search.getOptions();
return this.windowModel.getLastSearchOptions();
};
this.find = function(needle, options) {
this.clearSelection();
options = options || {};
options.needle = needle;
this.$search.set(options);
this.$find();
},
this.windowModel.find(needle, options);
};
this.findNext = function(options) {
options = options || {};
if (typeof options.backwards == "undefined")
options.backwards = false;
this.$search.set(options);
this.$find();
this.windowModel.findNext(options);
};
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.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.windowModel.findPrevious(options);
};
this.undo = function() {

View file

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

View file

@ -99,11 +99,11 @@ var Mode = function() {
this.highlightSelection = function(windowModel) {
var buffer = windowModel.buffer;
if (!buffer.selectionOccurrences)
buffer.selectionOccurrences = [];
if (!buffer._selectionOccurrences)
buffer._selectionOccurrences = [];
if (buffer.selectionOccurrences.length)
this.clearSelectionHighlight(editor);
if (buffer._selectionOccurrences.length)
this.clearSelectionHighlight(windowModel);
var selection = windowModel.selection.getRange();
if (selection.isEmpty() || selection.isMultiLine())
@ -134,8 +134,6 @@ var Mode = function() {
needle: needle
};
// TODO refactor
/*
var search = windowModel.search;
var currentOptions = search.getOptions();
search.set(newOptions);
@ -144,25 +142,24 @@ var Mode = function() {
ranges.forEach(function(range) {
if (!range.contains(cursor.row, cursor.column)) {
var marker = buffer.addMarker(range, "ace_selected_word", "text");
buffer.selectionOccurrences.push(marker);
buffer._selectionOccurrences.push(marker);
}
});
search.set(currentOptions);
*/
};
this.clearSelectionHighlight = function(windowModel) {
var buffer = windowModel.buffer;
if (!buffer.selectionOccurrences)
if (!buffer._selectionOccurrences)
return;
buffer.selectionOccurrences.forEach(function(marker) {
buffer._selectionOccurrences.forEach(function(marker) {
buffer.removeMarker(marker);
});
buffer.selectionOccurrences = [];
buffer._selectionOccurrences = [];
};
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
*/
var Window = exports.Window = function(theme) {
var Window = exports.Window = function(theme, search) {
this.theme = null;
this.setTheme(theme);
this.search = search;
this.buffer = null;
@ -224,6 +225,95 @@ var Window = exports.Window = function(theme) {
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
this.gotoLine = function(lineNumber, column) {

View file

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