diff --git a/lib/ace/editor.js b/lib/ace/editor.js index d0ce2554..12b91ccc 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -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() { diff --git a/lib/ace/editor_highlight_selected_word_test.js b/lib/ace/editor_highlight_selected_word_test.js index 78ce465c..e32f5523 100644 --- a/lib/ace/editor_highlight_selected_word_test.js +++ b/lib/ace/editor_highlight_selected_word_test.js @@ -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); } }; diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 2c7d5c40..01a587ff 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -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) { diff --git a/lib/ace/model/window.js b/lib/ace/model/window.js index 06a69bee..ce001a71 100644 --- a/lib/ace/model/window.js +++ b/lib/ace/model/window.js @@ -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) { diff --git a/lib/ace/view/window_view_mock.js b/lib/ace/view/window_view_mock.js index d93a9d93..fde3b013 100644 --- a/lib/ace/view/window_view_mock.js +++ b/lib/ace/view/window_view_mock.js @@ -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() {}; })