From 887aa24cebd4f3e2c19492e529e673a98420947a Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 01:42:49 -0700 Subject: [PATCH 01/17] [occur] starting with simple occur functionality --- lib/ace/commands/occur_commands.js | 93 +++++++++++++++++++++++++++++ lib/ace/occur.js | 96 ++++++++++++++++++++++++++++++ lib/ace/occur_test.js | 95 +++++++++++++++++++++++++++++ lib/ace/test/all_browser.js | 1 + lib/ace/test/asyncjs/assert.js | 4 +- 5 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 lib/ace/commands/occur_commands.js create mode 100644 lib/ace/occur.js create mode 100644 lib/ace/occur_test.js diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js new file mode 100644 index 00000000..cf332133 --- /dev/null +++ b/lib/ace/commands/occur_commands.js @@ -0,0 +1,93 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var config = require("../config"), + Occur = require("../occur").Occur; + +// These commands can be installed in a normal command handler to start occur: +exports.occurStartCommands = [{ + name: "occur", + exec: function(editor, options) { + if (!options.needle) return; + var handler = new OccurKeyboardHandler(); + editor.keyBinding.addKeyboardHandler(handler); + editor.commands.addCommands(exports.occurCommands); + var occur = new Occur(); + occur.display(editor.session, options); + }, + readOnly: true +}]; + +exports.occurCommands = [{ + name: "occurexit", + exec: function(editor) { + // if (!options.needle) return; + var session = editor.session, occur = session.doc.$occur; + if (occur) occur.displayOriginal(session); + editor.commands.removeCommands(exports.occurCommands); + var handler = editor.getKeyboardHandler(); + if (handler.isOccurHandler) editor.keyBinding.removeKeyboardHandler(handler); + }, + readOnly: true +}]; + +var HashHandler = require("../keyboard/hash_handler").HashHandler; +var oop = require("../lib/oop"); + +function OccurKeyboardHandler() {} + +oop.inherits(OccurKeyboardHandler, HashHandler); + +;(function() { + + this.isOccurHandler = true; + + this.attach = function(editor) { + HashHandler.call(this, exports.iSearchCommands, editor.commands.platform); + this.$editor = editor; + } + + this.detach = function(editor) { + } + + var handleKeyboard$super = this.handleKeyboard; + this.handleKeyboard = function(data, hashId, key, keyCode) { + var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode); + return (cmd && cmd.command) ? cmd : {command: "null"}; + } + +}).call(OccurKeyboardHandler.prototype); + + +exports.OccurKeyboardHandler = OccurKeyboardHandler; + +}); diff --git a/lib/ace/occur.js b/lib/ace/occur.js new file mode 100644 index 00000000..56f07713 --- /dev/null +++ b/lib/ace/occur.js @@ -0,0 +1,96 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var Range = require("./range").Range; +var Search = require("./search").Search; +var Document = require("./document").Document; +var iSearchCommandModule = require("./commands/incremental_search_commands"); +var ISearchKbd = iSearchCommandModule.IncrementalSearchKeyboardHandler; + +/** + * @class Occur + * + * Finds all lines matching a search term in the current docuement and + * displays them instead of the original document. + * + **/ + + +/** + * + * + * Creates a new `Occur` object. + * + * @constructor + **/ +function Occur() { + // this.$options = {wrap: false, skipCurrent: false}; + // this.$keyboardHandler = new ISearchKbd(this); +} + +oop.inherits(Occur, Search); + +(function() { + + this.display = function(session, options) { + this.$originalDoc = session.doc; + var found = this.matchingLines(session, options), + lines = found.map(function(foundLine) { return foundLine.content; }), + occurDoc = new Document(lines); + occurDoc.$occur = this; + session.setDocument(occurDoc); + } + + this.displayOriginal = function(session) { + session.setDocument(this.$originalDoc); + } + + this.matchingLines = function(session, options) { + options = options || {}; + if (!session || !options.needle) return []; + var search = new Search(); + search.set(options); + var ranges = search.findAll(session); + return ranges.map(function(range) { + var row = range.start.row; + return {row: row, content: session.getLine(row)}; + }); + } + +}).call(Occur.prototype); + + +exports.Occur = Occur; + +}); diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js new file mode 100644 index 00000000..ab92e8be --- /dev/null +++ b/lib/ace/occur_test.js @@ -0,0 +1,95 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +if (typeof process !== "undefined") { + require("amd-loader"); +} + +define(function(require, exports, module) { +"use strict"; + +var EditSession = require("./edit_session").EditSession; +var Editor = require("./editor").Editor; +var MockRenderer = require("./test/mockrenderer").MockRenderer; +var Range = require("./range").Range; +var assert = require("./test/assertions"); +var Occur = require("./occur").Occur; +var occurCommands = require("./commands/occur_commands"); +// var OccurKeyboardHandler = occurCommands.OccurKeyboardHandler; + +var editor, occur, session; + +module.exports = { + + name: "ACE occur.js", + + setUp: function() { + session = new EditSession(''); + editor = new Editor(new MockRenderer(), session); + occur = new Occur(); + }, + + "test: find lines matching" : function() { + session.doc.insertLines(0, ['abc', 'def', 'xyz', 'bcx']); + var result = occur.matchingLines(session, {needle: 'bc'}), + expected = [{row: 0, content: 'abc'}, {row: 3, content: 'bcx'}]; + assert.deepEqual(result, expected); + }, + + "test: display occurrences" : function() { + var lines = ['abc', 'def', 'xyz', 'bcx']; + session.doc.insertLines(0, lines); + occur.display(session, {needle: 'bc'}); + assert.equal(session.getValue(), 'abc\nbcx'); + occur.displayOriginal(session); + assert.equal(session.getValue(), lines.join('\n') + '\n'); + }, + + "test: occur command" : function() { + var lines = ['hel', 'lo', '', 'wo', 'rld']; + session.doc.insertLines(0, lines); + editor.commands.addCommands(occurCommands.occurStartCommands); + editor.execCommand('occur', {needle: 'o'}); + assert.equal(session.getValue(), 'lo\nwo'); + assert.ok(editor.getKeyboardHandler().isOccurHandler, 'no occur handler installed'); + assert.ok(editor.commands.byName.occurexit, 'no exitoccur command installed'); + editor.execCommand('occurexit'); + assert.ok(!editor.getKeyboardHandler().isOccurHandler, 'occur handler installed after detach'); + assert.ok(!editor.commands.byName.occurexit, 'exitoccur installed after exiting occur'); + assert.equal(session.getValue(), lines.join('\n') + '\n'); + } + +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec() +} diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index 9a274329..29527221 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -42,6 +42,7 @@ var testNames = [ "ace/mode/folding/xml_test", "ace/mode/folding/coffee_test", "ace/multi_select_test", + "ace/occur_test", "ace/range_test", "ace/range_list_test", "ace/search_test", diff --git a/lib/ace/test/asyncjs/assert.js b/lib/ace/test/asyncjs/assert.js index 6cdc611a..96e3f6e2 100644 --- a/lib/ace/test/asyncjs/assert.js +++ b/lib/ace/test/asyncjs/assert.js @@ -1,5 +1,5 @@ define(function(require, exports, module) { - + // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! @@ -141,7 +141,7 @@ function _deepEqual(actual, expected) { if (actual === expected) { return true; - } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { + } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { if (actual.length != expected.length) return false; for (var i = 0; i < actual.length; i++) { From 2ba388ed04329c6d4f06dcea020cee35996d7dee Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 02:38:06 -0700 Subject: [PATCH 02/17] [occur] command cleanup --- lib/ace/commands/occur_commands.js | 17 ++++++++--------- lib/ace/occur.js | 2 -- lib/ace/occur_test.js | 6 ++---- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js index cf332133..c030ffdb 100644 --- a/lib/ace/commands/occur_commands.js +++ b/lib/ace/commands/occur_commands.js @@ -34,26 +34,27 @@ var config = require("../config"), Occur = require("../occur").Occur; // These commands can be installed in a normal command handler to start occur: -exports.occurStartCommands = [{ +var occurStartCommands = [{ name: "occur", exec: function(editor, options) { if (!options.needle) return; var handler = new OccurKeyboardHandler(); editor.keyBinding.addKeyboardHandler(handler); - editor.commands.addCommands(exports.occurCommands); + editor.commands.addCommands(occurCommands); var occur = new Occur(); occur.display(editor.session, options); }, readOnly: true }]; -exports.occurCommands = [{ +var occurCommands = [{ name: "occurexit", + bindKey: 'esc|Ctrl-G', exec: function(editor) { // if (!options.needle) return; var session = editor.session, occur = session.doc.$occur; if (occur) occur.displayOriginal(session); - editor.commands.removeCommands(exports.occurCommands); + editor.commands.removeCommands(occurCommands); var handler = editor.getKeyboardHandler(); if (handler.isOccurHandler) editor.keyBinding.removeKeyboardHandler(handler); }, @@ -72,12 +73,11 @@ oop.inherits(OccurKeyboardHandler, HashHandler); this.isOccurHandler = true; this.attach = function(editor) { - HashHandler.call(this, exports.iSearchCommands, editor.commands.platform); + HashHandler.call(this, occurCommands, editor.commands.platform); this.$editor = editor; } - this.detach = function(editor) { - } + this.detach = function() {} var handleKeyboard$super = this.handleKeyboard; this.handleKeyboard = function(data, hashId, key, keyCode) { @@ -87,7 +87,6 @@ oop.inherits(OccurKeyboardHandler, HashHandler); }).call(OccurKeyboardHandler.prototype); - -exports.OccurKeyboardHandler = OccurKeyboardHandler; +exports.commands = occurStartCommands; }); diff --git a/lib/ace/occur.js b/lib/ace/occur.js index 56f07713..80b044c6 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -35,8 +35,6 @@ var oop = require("./lib/oop"); var Range = require("./range").Range; var Search = require("./search").Search; var Document = require("./document").Document; -var iSearchCommandModule = require("./commands/incremental_search_commands"); -var ISearchKbd = iSearchCommandModule.IncrementalSearchKeyboardHandler; /** * @class Occur diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index ab92e8be..7116d100 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -41,9 +41,7 @@ var MockRenderer = require("./test/mockrenderer").MockRenderer; var Range = require("./range").Range; var assert = require("./test/assertions"); var Occur = require("./occur").Occur; -var occurCommands = require("./commands/occur_commands"); -// var OccurKeyboardHandler = occurCommands.OccurKeyboardHandler; - +var occurCommands = require("./commands/occur_commands").commands; var editor, occur, session; module.exports = { @@ -75,7 +73,7 @@ module.exports = { "test: occur command" : function() { var lines = ['hel', 'lo', '', 'wo', 'rld']; session.doc.insertLines(0, lines); - editor.commands.addCommands(occurCommands.occurStartCommands); + editor.commands.addCommands(occurCommands); editor.execCommand('occur', {needle: 'o'}); assert.equal(session.getValue(), 'lo\nwo'); assert.ok(editor.getKeyboardHandler().isOccurHandler, 'no occur handler installed'); From 7f1e926f3cf0e9bb9e1c4b7c2aecd8f94f812ab1 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 02:38:27 -0700 Subject: [PATCH 03/17] [occur] highlighting occur doc --- lib/ace/occur.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ace/occur.js b/lib/ace/occur.js index 80b044c6..fd8dbdef 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -68,6 +68,9 @@ oop.inherits(Occur, Search); occurDoc = new Document(lines); occurDoc.$occur = this; session.setDocument(occurDoc); + session.highlight(null); + session.highlight(options.re); + session._emit('changeBackMarker'); } this.displayOriginal = function(session) { From 8102b6579f2301a5afed059fab90b911a7b9447a Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 02:39:00 -0700 Subject: [PATCH 04/17] [occur] fixing occur lines --- lib/ace/occur.js | 12 +++++++----- lib/ace/occur_test.js | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/ace/occur.js b/lib/ace/occur.js index fd8dbdef..fa26410d 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -82,11 +82,13 @@ oop.inherits(Occur, Search); if (!session || !options.needle) return []; var search = new Search(); search.set(options); - var ranges = search.findAll(session); - return ranges.map(function(range) { - var row = range.start.row; - return {row: row, content: session.getLine(row)}; - }); + return search.findAll(session).reduce(function(lines, range) { + var row = range.start.row, + last = lines[lines.length-1]; + return last && last.row === row ? + lines : + lines.concat({row: row, content: session.getLine(row)}); + }, []); } }).call(Occur.prototype); diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index 7116d100..50dfc489 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -55,9 +55,9 @@ module.exports = { }, "test: find lines matching" : function() { - session.doc.insertLines(0, ['abc', 'def', 'xyz', 'bcx']); + session.doc.insertLines(0, ['abc', 'def', 'xyz', 'bcxbc']); var result = occur.matchingLines(session, {needle: 'bc'}), - expected = [{row: 0, content: 'abc'}, {row: 3, content: 'bcx'}]; + expected = [{row: 0, content: 'abc'}, {row: 3, content: 'bcxbc'}]; assert.deepEqual(result, expected); }, From 0aee413754347480ed7b2277a72fdfd053d31d3d Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 03:15:12 -0700 Subject: [PATCH 05/17] [occur] make occur doc react to keyboard evts / highlight it --- lib/ace/commands/occur_commands.js | 4 +++- lib/ace/occur.js | 2 ++ lib/ace/occur_test.js | 13 ++++++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js index c030ffdb..a0106f08 100644 --- a/lib/ace/commands/occur_commands.js +++ b/lib/ace/commands/occur_commands.js @@ -41,6 +41,7 @@ var occurStartCommands = [{ var handler = new OccurKeyboardHandler(); editor.keyBinding.addKeyboardHandler(handler); editor.commands.addCommands(occurCommands); + editor.setReadOnly(true); var occur = new Occur(); occur.display(editor.session, options); }, @@ -55,6 +56,7 @@ var occurCommands = [{ var session = editor.session, occur = session.doc.$occur; if (occur) occur.displayOriginal(session); editor.commands.removeCommands(occurCommands); + editor.setReadOnly(false); var handler = editor.getKeyboardHandler(); if (handler.isOccurHandler) editor.keyBinding.removeKeyboardHandler(handler); }, @@ -82,7 +84,7 @@ oop.inherits(OccurKeyboardHandler, HashHandler); var handleKeyboard$super = this.handleKeyboard; this.handleKeyboard = function(data, hashId, key, keyCode) { var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode); - return (cmd && cmd.command) ? cmd : {command: "null"}; + return (cmd && cmd.command) ? cmd : {command: "null", passEvent: true}; } }).call(OccurKeyboardHandler.prototype); diff --git a/lib/ace/occur.js b/lib/ace/occur.js index fa26410d..9688c909 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -75,6 +75,8 @@ oop.inherits(Occur, Search); this.displayOriginal = function(session) { session.setDocument(this.$originalDoc); + session.highlight(null); + session._emit('changeBackMarker'); } this.matchingLines = function(session, options) { diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index 50dfc489..faadf976 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -71,17 +71,28 @@ module.exports = { }, "test: occur command" : function() { + // setup var lines = ['hel', 'lo', '', 'wo', 'rld']; session.doc.insertLines(0, lines); editor.commands.addCommands(occurCommands); + + // run occur for lines including 'o' editor.execCommand('occur', {needle: 'o'}); assert.equal(session.getValue(), 'lo\nwo'); + + // command install OK? + assert.ok(editor.getReadOnly(), 'occur doc not marked as read only'); assert.ok(editor.getKeyboardHandler().isOccurHandler, 'no occur handler installed'); assert.ok(editor.commands.byName.occurexit, 'no exitoccur command installed'); + + // exit occur editor.execCommand('occurexit'); + assert.equal(session.getValue(), lines.join('\n') + '\n'); + + // editor state cleaned up? + assert.ok(!editor.getReadOnly(), 'original doc is marked as read only'); assert.ok(!editor.getKeyboardHandler().isOccurHandler, 'occur handler installed after detach'); assert.ok(!editor.commands.byName.occurexit, 'exitoccur installed after exiting occur'); - assert.equal(session.getValue(), lines.join('\n') + '\n'); } }; From ecf258f2a04f6630c2ff52e1ca5c42f7ed75f313 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 03:15:31 -0700 Subject: [PATCH 06/17] oop.mixin returns object --- lib/ace/lib/oop.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ace/lib/oop.js b/lib/ace/lib/oop.js index f9ba6fe8..f3dbb1d9 100644 --- a/lib/ace/lib/oop.js +++ b/lib/ace/lib/oop.js @@ -45,6 +45,7 @@ exports.mixin = function(obj, mixin) { for (var key in mixin) { obj[key] = mixin[key]; } + return obj; }; exports.implement = function(proto, mixin) { From 148326403335935781b7208d1f799bccc77f3a97 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 03:15:50 -0700 Subject: [PATCH 07/17] [occur] options fix --- lib/ace/occur.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/occur.js b/lib/ace/occur.js index 9688c909..fd4fdbd9 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -80,7 +80,7 @@ oop.inherits(Occur, Search); } this.matchingLines = function(session, options) { - options = options || {}; + options = oop.mixin({}, options); if (!session || !options.needle) return []; var search = new Search(); search.set(options); From 204e6b5ab003cf35bbfafc737671f57772f7dfeb Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 04:11:34 -0700 Subject: [PATCH 08/17] [occur] entering and exiting occur: position is translated --- lib/ace/commands/occur_commands.js | 16 +++++++++++++++ lib/ace/occur.js | 33 ++++++++++++++++++++++++++++++ lib/ace/occur_test.js | 27 ++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js index a0106f08..b8669203 100644 --- a/lib/ace/commands/occur_commands.js +++ b/lib/ace/commands/occur_commands.js @@ -38,12 +38,15 @@ var occurStartCommands = [{ name: "occur", exec: function(editor, options) { if (!options.needle) return; + var pos = editor.getCursorPosition(); var handler = new OccurKeyboardHandler(); editor.keyBinding.addKeyboardHandler(handler); editor.commands.addCommands(occurCommands); editor.setReadOnly(true); var occur = new Occur(); occur.display(editor.session, options); + pos = occur.originalToOccurPosition(editor.session, pos); + editor.moveCursorToPosition(pos); }, readOnly: true }]; @@ -61,6 +64,19 @@ var occurCommands = [{ if (handler.isOccurHandler) editor.keyBinding.removeKeyboardHandler(handler); }, readOnly: true +}, { + name: "occuraccept", + bindKey: 'enter', + exec: function(editor) { + var occur = editor.session.doc.$occur, + pos = editor.getCursorPosition(); + if (occur) { + pos = occur.occurToOriginalPosition(editor.session, pos); + } + editor.commands.byName.occurexit.exec(editor); + editor.moveCursorToPosition(pos); + }, + readOnly: true }]; var HashHandler = require("../keyboard/hash_handler").HashHandler; diff --git a/lib/ace/occur.js b/lib/ace/occur.js index fd4fdbd9..6ab695dd 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -67,6 +67,7 @@ oop.inherits(Occur, Search); lines = found.map(function(foundLine) { return foundLine.content; }), occurDoc = new Document(lines); occurDoc.$occur = this; + occurDoc.$occurMatchingLines = found; session.setDocument(occurDoc); session.highlight(null); session.highlight(options.re); @@ -79,6 +80,38 @@ oop.inherits(Occur, Search); session._emit('changeBackMarker'); } + /** + * Translates the position from the original document to the occur lines in + * the document or the beginning if the doc {row: 0, column: 0} if not + * found. + * @param {EditSession} session The occur session + * @param {Object} pos The position in the original document + * @return {Object} position in occur doc + **/ + this.originalToOccurPosition = function(session, pos) { + var lines = session.getDocument().$occurMatchingLines, + nullPos = {row: 0, column: 0}; + if (!lines) return nullPos; + for (var i = 0; i < lines.length; i++) { + if (lines[i].row === pos.row) return {row: i, column: pos.column} + } + return nullPos; + } + + /** + * Translates the position from the occur document to the original document + * or `pos` if not found. + * @param {EditSession} session The occur session + * @param {Object} pos The position in the occur session document + * @return {Object} position + **/ + this.occurToOriginalPosition = function(session, pos) { + var lines = session.getDocument().$occurMatchingLines; + if (!lines || !lines[pos.row]) return pos; + debugger + return {row: lines[pos.row].row, column: pos.column}; + } + this.matchingLines = function(session, options) { options = oop.mixin({}, options); if (!session || !options.needle) return []; diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index faadf976..73d8d831 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -70,6 +70,14 @@ module.exports = { assert.equal(session.getValue(), lines.join('\n') + '\n'); }, + "test: original position from occur doc" : function() { + session.doc.insertLines(0, ['abc', 'def', 'xyz', 'bcx']); + occur.display(session, {needle: 'bc'}); + assert.equal(session.getValue(), 'abc\nbcx'); + var pos = occur.occurToOriginalPosition(session, {row: 1, column: 2}); + assert.position(pos, 3, 2); + }, + "test: occur command" : function() { // setup var lines = ['hel', 'lo', '', 'wo', 'rld']; @@ -93,6 +101,25 @@ module.exports = { assert.ok(!editor.getReadOnly(), 'original doc is marked as read only'); assert.ok(!editor.getKeyboardHandler().isOccurHandler, 'occur handler installed after detach'); assert.ok(!editor.commands.byName.occurexit, 'exitoccur installed after exiting occur'); + }, + + "test: occur navigation" : function() { + // setup + var lines = ['hel', 'lo', '', 'wo', 'rld']; + session.doc.insertLines(0, lines); + editor.commands.addCommands(occurCommands); + editor.moveCursorToPosition({row: 1, column: 1}); + + // run occur for lines including 'o' + editor.execCommand('occur', {needle: 'o'}); + assert.equal(session.getValue(), 'lo\nwo'); + assert.position(editor.getCursorPosition(), 0, 1, 'original -> occur pos'); + + // move to second line and accept + editor.moveCursorToPosition({row: 1, column: 1}); + editor.execCommand('occuraccept'); + + assert.position(editor.getCursorPosition(), 3, 1, 'occur -> original pos'); } }; From 313c4f77f74395bc50eb8d808875afa8c07867fc Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 04:39:45 -0700 Subject: [PATCH 09/17] [occur] cleanup --- lib/ace/commands/occur_commands.js | 49 ++++++++++++++--------------- lib/ace/occur.js | 50 ++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 32 deletions(-) diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js index b8669203..1d4a97ec 100644 --- a/lib/ace/commands/occur_commands.js +++ b/lib/ace/commands/occur_commands.js @@ -37,16 +37,8 @@ var config = require("../config"), var occurStartCommands = [{ name: "occur", exec: function(editor, options) { - if (!options.needle) return; - var pos = editor.getCursorPosition(); - var handler = new OccurKeyboardHandler(); - editor.keyBinding.addKeyboardHandler(handler); - editor.commands.addCommands(occurCommands); - editor.setReadOnly(true); - var occur = new Occur(); - occur.display(editor.session, options); - pos = occur.originalToOccurPosition(editor.session, pos); - editor.moveCursorToPosition(pos); + var occurSessionActive = new Occur().enter(editor, options); + if (occurSessionActive) OccurKeyboardHandler.installIn(editor); }, readOnly: true }]; @@ -55,26 +47,20 @@ var occurCommands = [{ name: "occurexit", bindKey: 'esc|Ctrl-G', exec: function(editor) { - // if (!options.needle) return; - var session = editor.session, occur = session.doc.$occur; - if (occur) occur.displayOriginal(session); - editor.commands.removeCommands(occurCommands); - editor.setReadOnly(false); - var handler = editor.getKeyboardHandler(); - if (handler.isOccurHandler) editor.keyBinding.removeKeyboardHandler(handler); + var occur = editor.session.getDocument().$occur; + if (!occur) return; + occur.exit(editor, {}); + OccurKeyboardHandler.uninstallFrom(editor); }, readOnly: true }, { name: "occuraccept", bindKey: 'enter', exec: function(editor) { - var occur = editor.session.doc.$occur, - pos = editor.getCursorPosition(); - if (occur) { - pos = occur.occurToOriginalPosition(editor.session, pos); - } - editor.commands.byName.occurexit.exec(editor); - editor.moveCursorToPosition(pos); + var occur = editor.session.getDocument().$occur; + if (!occur) return; + occur.exit(editor, {translatePosition: true}); + OccurKeyboardHandler.uninstallFrom(editor); }, readOnly: true }]; @@ -82,6 +68,7 @@ var occurCommands = [{ var HashHandler = require("../keyboard/hash_handler").HashHandler; var oop = require("../lib/oop"); + function OccurKeyboardHandler() {} oop.inherits(OccurKeyboardHandler, HashHandler); @@ -95,8 +82,6 @@ oop.inherits(OccurKeyboardHandler, HashHandler); this.$editor = editor; } - this.detach = function() {} - var handleKeyboard$super = this.handleKeyboard; this.handleKeyboard = function(data, hashId, key, keyCode) { var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode); @@ -105,6 +90,18 @@ oop.inherits(OccurKeyboardHandler, HashHandler); }).call(OccurKeyboardHandler.prototype); +OccurKeyboardHandler.installIn = function(editor) { + var handler = new this(); + editor.keyBinding.addKeyboardHandler(handler); + editor.commands.addCommands(occurCommands); +} + +OccurKeyboardHandler.uninstallFrom = function(editor) { + editor.commands.removeCommands(occurCommands); + var handler = editor.getKeyboardHandler(); + if (handler.isOccurHandler) editor.keyBinding.removeKeyboardHandler(handler); +} + exports.commands = occurStartCommands; }); diff --git a/lib/ace/occur.js b/lib/ace/occur.js index 6ab695dd..6b7b0558 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -39,8 +39,9 @@ var Document = require("./document").Document; /** * @class Occur * - * Finds all lines matching a search term in the current docuement and - * displays them instead of the original document. + * Finds all lines matching a search term in the current [[Document + * `Document`]] and displays them instead of the original `Document`. Keeps + * track of the mapping between the occur doc and the original doc. * **/ @@ -52,15 +53,52 @@ var Document = require("./document").Document; * * @constructor **/ -function Occur() { - // this.$options = {wrap: false, skipCurrent: false}; - // this.$keyboardHandler = new ISearchKbd(this); -} +function Occur() {} oop.inherits(Occur, Search); (function() { + /** + * Enables occur mode. expects that `options.needle` is a search term. + * This search term is used to filter out all the lines that include it + * and these are then used as the content of a new [[Document + * `Document`]]. The current cursor position of editor will be translated + * so that the cursor is on the matching row/column as it was before. + * @param {Editor} editor + * @param {Object} options options.needle should be a String + * @return {Boolean} Whether occur activation was successful + * + **/ + this.enter = function(editor, options) { + if (!options.needle) return false; + var pos = editor.getCursorPosition(); + editor.setReadOnly(true); + this.display(editor.session, options); + var translatedPos = this.originalToOccurPosition(editor.session, pos); + editor.moveCursorToPosition(translatedPos); + return true; + } + + /** + * Disables occur mode. Resets the [[Sessions `EditSession`]] [[Document + * `Document`]] back to the original doc. If options.translatePosition is + * truthy also maps the [[Editors `Editor`]] cursor position accordingly. + * @param {Editor} editor + * @param {Object} options options.translatePosition + * @return {Boolean} Whether occur deactivation was successful + * + **/ + this.exit = function(editor, options) { + var session = editor.session, + pos = options.translatePosition && editor.getCursorPosition(), + translatedPos = pos && this.occurToOriginalPosition(editor.session, pos); + this.displayOriginal(session); + editor.setReadOnly(false); + if (translatedPos) editor.moveCursorToPosition(translatedPos); + return true; + } + this.display = function(session, options) { this.$originalDoc = session.doc; var found = this.matchingLines(session, options), From fe3e92a3f940602ec384047e972fbcc9dd4b33bc Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 04:40:11 -0700 Subject: [PATCH 10/17] fix for setReadOnly --- lib/ace/editor.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 92a10add..ce36ae47 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -1457,7 +1457,7 @@ var Editor = function(renderer, session) { } else { var ranges = selection.rangeList.ranges; selection.rangeList.detach(this.session); - + for (var i = ranges.length; i--; ) { var rangeIndex = i; var rows = ranges[i].collapseRows(); @@ -1471,7 +1471,7 @@ var Editor = function(renderer, session) { break; } i++; - + var linesMoved = mover.call(this, first, last); while (rangeIndex >= i) { ranges[rangeIndex].moveBy(linesMoved, 0); @@ -2210,7 +2210,8 @@ config.defineOptions(Editor.prototype, "editor", { readOnly: { set: function(readOnly) { this.textInput.setReadOnly(readOnly); - this.renderer.$cursorLayer.setBlinking(!readOnly); + var cursorLayer = this.renderer.$cursorLayer; + cursorLayer && cursorLayer.setBlinking(!readOnly); }, initialValue: false }, From f351c9de387cd20967d69f80152af42ef9953a2d Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 05:32:47 -0700 Subject: [PATCH 11/17] [occur] allowing other commands --- lib/ace/commands/occur_commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js index 1d4a97ec..1fbcad77 100644 --- a/lib/ace/commands/occur_commands.js +++ b/lib/ace/commands/occur_commands.js @@ -85,7 +85,7 @@ oop.inherits(OccurKeyboardHandler, HashHandler); var handleKeyboard$super = this.handleKeyboard; this.handleKeyboard = function(data, hashId, key, keyCode) { var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode); - return (cmd && cmd.command) ? cmd : {command: "null", passEvent: true}; + return (cmd && cmd.command) ? cmd : undefined; } }).call(OccurKeyboardHandler.prototype); From 6f68042545ce8dbb69de4b8f0d70eabd566ab328 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 18:04:12 -0700 Subject: [PATCH 12/17] [occur] highlighting occur search term in occur mode --- lib/ace/css/editor.css | 8 ++++++++ lib/ace/occur.js | 30 +++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index 81f8fbe6..0716003f 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -209,6 +209,14 @@ box-sizing: border-box; } +.ace_marker-layer .ace_occur-highlight { + position: absolute; + z-index: 4; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + .ace_line .ace_fold { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; diff --git a/lib/ace/occur.js b/lib/ace/occur.js index 6b7b0558..a69d6ec6 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -35,6 +35,7 @@ var oop = require("./lib/oop"); var Range = require("./range").Range; var Search = require("./search").Search; var Document = require("./document").Document; +var SearchHighlight = require("./search_highlight").SearchHighlight; /** * @class Occur @@ -99,6 +100,13 @@ oop.inherits(Occur, Search); return true; } + this.highlight = function(sess, regexp) { + var hl = sess.$occurHighlight = sess.$occurHighlight || sess.addDynamicMarker( + new SearchHighlight(null, "ace_occur-highlight", "text")); + hl.setRegexp(regexp); + sess._emit("changeBackMarker"); // force highlight layer redraw + } + this.display = function(session, options) { this.$originalDoc = session.doc; var found = this.matchingLines(session, options), @@ -107,14 +115,13 @@ oop.inherits(Occur, Search); occurDoc.$occur = this; occurDoc.$occurMatchingLines = found; session.setDocument(occurDoc); - session.highlight(null); - session.highlight(options.re); + this.highlight(session, options.re); session._emit('changeBackMarker'); } this.displayOriginal = function(session) { session.setDocument(this.$originalDoc); - session.highlight(null); + this.highlight(session, null); session._emit('changeBackMarker'); } @@ -166,6 +173,23 @@ oop.inherits(Occur, Search); }).call(Occur.prototype); +var dom = require('./lib/dom'); +(function patchHighlightMarkerStyling() { + var id = 'incremental-occur-highlighting', + css = 'div.ace_occur-highlight {\n' + + " border-radius: 4px;\n" + + "border: 8px solid rgba(87, 255, 8, 0.25);\n" + + "box-shadow: 0 0 4px rgb(91, 255, 50);\n" + + "}\n" + + '.ace_dark div.ace_occur-highlight {\n' + + "border: 8px solid rgb(80, 140, 85);\n" + + "box-shadow: 0 0 4px rgb(60, 120, 70);\n" + + '}\n'; + dom.importCssString(css, id); +})(); + +window.Occur = Occur +window.Document = Document exports.Occur = Occur; From 4b0b579bf4b0c13adc1322a8d4438bf83bb72113 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 18:22:45 -0700 Subject: [PATCH 13/17] [occur] towards better occur session display --- lib/ace/occur.js | 30 +++++++++++++-------------- lib/ace/occur_test.js | 47 ++++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/lib/ace/occur.js b/lib/ace/occur.js index a69d6ec6..369417e9 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -74,8 +74,7 @@ oop.inherits(Occur, Search); this.enter = function(editor, options) { if (!options.needle) return false; var pos = editor.getCursorPosition(); - editor.setReadOnly(true); - this.display(editor.session, options); + this.display(editor, options); var translatedPos = this.originalToOccurPosition(editor.session, pos); editor.moveCursorToPosition(translatedPos); return true; @@ -94,8 +93,7 @@ oop.inherits(Occur, Search); var session = editor.session, pos = options.translatePosition && editor.getCursorPosition(), translatedPos = pos && this.occurToOriginalPosition(editor.session, pos); - this.displayOriginal(session); - editor.setReadOnly(false); + this.displayOriginal(editor); if (translatedPos) editor.moveCursorToPosition(translatedPos); return true; } @@ -107,22 +105,24 @@ oop.inherits(Occur, Search); sess._emit("changeBackMarker"); // force highlight layer redraw } - this.display = function(session, options) { - this.$originalDoc = session.doc; - var found = this.matchingLines(session, options), + this.display = function(editor, options) { + // this.setSession(session || new EditSession("")) + this.$originalDoc = editor.session.getDocument(); + var found = this.matchingLines(editor.session, options), lines = found.map(function(foundLine) { return foundLine.content; }), - occurDoc = new Document(lines); + occurDoc = new Document(''); occurDoc.$occur = this; occurDoc.$occurMatchingLines = found; - session.setDocument(occurDoc); - this.highlight(session, options.re); - session._emit('changeBackMarker'); + editor.session.setDocument(occurDoc); + occurDoc.insertLines(0, lines); + this.highlight(editor.session, options.re); + editor.session._emit('changeBackMarker'); } - this.displayOriginal = function(session) { - session.setDocument(this.$originalDoc); - this.highlight(session, null); - session._emit('changeBackMarker'); + this.displayOriginal = function(editor) { + editor.session.setDocument(this.$originalDoc); + this.highlight(editor.session, null); + editor.session._emit('changeBackMarker'); } /** diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index 73d8d831..df4ada48 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -42,77 +42,78 @@ var Range = require("./range").Range; var assert = require("./test/assertions"); var Occur = require("./occur").Occur; var occurCommands = require("./commands/occur_commands").commands; -var editor, occur, session; +var editor, occur; module.exports = { name: "ACE occur.js", setUp: function() { - session = new EditSession(''); + var session = new EditSession(''); editor = new Editor(new MockRenderer(), session); occur = new Occur(); }, "test: find lines matching" : function() { - session.doc.insertLines(0, ['abc', 'def', 'xyz', 'bcxbc']); - var result = occur.matchingLines(session, {needle: 'bc'}), + editor.session.insert({row: 0, column: 0}, 'abc\ndef\nxyz\nbcxbc'); + var result = occur.matchingLines(editor.session, {needle: 'bc'}), expected = [{row: 0, content: 'abc'}, {row: 3, content: 'bcxbc'}]; assert.deepEqual(result, expected); }, "test: display occurrences" : function() { - var lines = ['abc', 'def', 'xyz', 'bcx']; - session.doc.insertLines(0, lines); - occur.display(session, {needle: 'bc'}); - assert.equal(session.getValue(), 'abc\nbcx'); - occur.displayOriginal(session); - assert.equal(session.getValue(), lines.join('\n') + '\n'); + var text = 'abc\ndef\nxyz\nbcx\n'; + editor.session.insert({row: 0, column: 0}, text); + occur.display(editor, {needle: 'bc'}); + assert.equal(editor.getValue(), 'abc\nbcx\n'); + occur.displayOriginal(editor); + assert.equal(editor.getValue(), text); }, "test: original position from occur doc" : function() { - session.doc.insertLines(0, ['abc', 'def', 'xyz', 'bcx']); - occur.display(session, {needle: 'bc'}); - assert.equal(session.getValue(), 'abc\nbcx'); - var pos = occur.occurToOriginalPosition(session, {row: 1, column: 2}); + var text = 'abc\ndef\nxyz\nbcx\n'; + editor.session.insert({row: 0, column: 0}, text); + occur.display(editor, {needle: 'bc'}); + assert.equal(editor.getValue(), 'abc\nbcx\n'); + var pos = occur.occurToOriginalPosition(editor.session, {row: 1, column: 2}); assert.position(pos, 3, 2); }, "test: occur command" : function() { // setup - var lines = ['hel', 'lo', '', 'wo', 'rld']; - session.doc.insertLines(0, lines); + var text = 'hel\nlo\n\nwo\nrld\n'; + editor.session.insert({row: 0, column: 0}, text); editor.commands.addCommands(occurCommands); // run occur for lines including 'o' editor.execCommand('occur', {needle: 'o'}); - assert.equal(session.getValue(), 'lo\nwo'); + assert.equal(editor.getValue(), 'lo\nwo\n'); // command install OK? - assert.ok(editor.getReadOnly(), 'occur doc not marked as read only'); + // assert.ok(editor.getReadOnly(), 'occur doc not marked as read only'); assert.ok(editor.getKeyboardHandler().isOccurHandler, 'no occur handler installed'); assert.ok(editor.commands.byName.occurexit, 'no exitoccur command installed'); // exit occur editor.execCommand('occurexit'); - assert.equal(session.getValue(), lines.join('\n') + '\n'); + assert.equal(editor.getValue(), text); // editor state cleaned up? - assert.ok(!editor.getReadOnly(), 'original doc is marked as read only'); + // assert.ok(!editor.getReadOnly(), 'original doc is marked as read only'); assert.ok(!editor.getKeyboardHandler().isOccurHandler, 'occur handler installed after detach'); assert.ok(!editor.commands.byName.occurexit, 'exitoccur installed after exiting occur'); }, "test: occur navigation" : function() { // setup - var lines = ['hel', 'lo', '', 'wo', 'rld']; - session.doc.insertLines(0, lines); + var text = 'hel\nlo\n\nwo\nrld\n'; + editor.session.insert({row: 0, column: 0}, text); editor.commands.addCommands(occurCommands); editor.moveCursorToPosition({row: 1, column: 1}); // run occur for lines including 'o' editor.execCommand('occur', {needle: 'o'}); - assert.equal(session.getValue(), 'lo\nwo'); + assert.equal(editor.getValue(), 'lo\nwo\n'); assert.position(editor.getCursorPosition(), 0, 1, 'original -> occur pos'); // move to second line and accept From 96bca7ed950cd757b1b86e36e1e113defeab5b2c Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 18:39:52 -0700 Subject: [PATCH 14/17] [occur] proper session replacement --- lib/ace/commands/occur_commands.js | 4 +-- lib/ace/occur.js | 39 ++++++++++++++---------------- lib/ace/occur_test.js | 15 ++++++------ 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js index 1fbcad77..c93c4da3 100644 --- a/lib/ace/commands/occur_commands.js +++ b/lib/ace/commands/occur_commands.js @@ -47,7 +47,7 @@ var occurCommands = [{ name: "occurexit", bindKey: 'esc|Ctrl-G', exec: function(editor) { - var occur = editor.session.getDocument().$occur; + var occur = editor.session.$occur; if (!occur) return; occur.exit(editor, {}); OccurKeyboardHandler.uninstallFrom(editor); @@ -57,7 +57,7 @@ var occurCommands = [{ name: "occuraccept", bindKey: 'enter', exec: function(editor) { - var occur = editor.session.getDocument().$occur; + var occur = editor.session.$occur; if (!occur) return; occur.exit(editor, {translatePosition: true}); OccurKeyboardHandler.uninstallFrom(editor); diff --git a/lib/ace/occur.js b/lib/ace/occur.js index 369417e9..1792a3a0 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -34,7 +34,7 @@ define(function(require, exports, module) { var oop = require("./lib/oop"); var Range = require("./range").Range; var Search = require("./search").Search; -var Document = require("./document").Document; +var EditSession = require("./edit_session").EditSession; var SearchHighlight = require("./search_highlight").SearchHighlight; /** @@ -74,7 +74,7 @@ oop.inherits(Occur, Search); this.enter = function(editor, options) { if (!options.needle) return false; var pos = editor.getCursorPosition(); - this.display(editor, options); + this.displayOccurContent(editor, options); var translatedPos = this.originalToOccurPosition(editor.session, pos); editor.moveCursorToPosition(translatedPos); return true; @@ -90,10 +90,9 @@ oop.inherits(Occur, Search); * **/ this.exit = function(editor, options) { - var session = editor.session, - pos = options.translatePosition && editor.getCursorPosition(), + var pos = options.translatePosition && editor.getCursorPosition(), translatedPos = pos && this.occurToOriginalPosition(editor.session, pos); - this.displayOriginal(editor); + this.displayOriginalContent(editor); if (translatedPos) editor.moveCursorToPosition(translatedPos); return true; } @@ -105,24 +104,23 @@ oop.inherits(Occur, Search); sess._emit("changeBackMarker"); // force highlight layer redraw } - this.display = function(editor, options) { + this.displayOccurContent = function(editor, options) { // this.setSession(session || new EditSession("")) - this.$originalDoc = editor.session.getDocument(); + this.$originalSession = editor.session; var found = this.matchingLines(editor.session, options), lines = found.map(function(foundLine) { return foundLine.content; }), - occurDoc = new Document(''); - occurDoc.$occur = this; - occurDoc.$occurMatchingLines = found; - editor.session.setDocument(occurDoc); - occurDoc.insertLines(0, lines); - this.highlight(editor.session, options.re); - editor.session._emit('changeBackMarker'); + occurSession = new EditSession(lines.join('\n')); + occurSession.$occur = this; + occurSession.$occurMatchingLines = found; + editor.setSession(occurSession); + this.highlight(occurSession, options.re); + occurSession._emit('changeBackMarker'); } - this.displayOriginal = function(editor) { - editor.session.setDocument(this.$originalDoc); - this.highlight(editor.session, null); - editor.session._emit('changeBackMarker'); + this.displayOriginalContent = function(editor) { + editor.setSession(this.$originalSession); + this.highlight(this.$originalSession, null); + this.$originalSession._emit('changeBackMarker'); } /** @@ -134,7 +132,7 @@ oop.inherits(Occur, Search); * @return {Object} position in occur doc **/ this.originalToOccurPosition = function(session, pos) { - var lines = session.getDocument().$occurMatchingLines, + var lines = session.$occurMatchingLines, nullPos = {row: 0, column: 0}; if (!lines) return nullPos; for (var i = 0; i < lines.length; i++) { @@ -151,9 +149,8 @@ oop.inherits(Occur, Search); * @return {Object} position **/ this.occurToOriginalPosition = function(session, pos) { - var lines = session.getDocument().$occurMatchingLines; + var lines = session.$occurMatchingLines; if (!lines || !lines[pos.row]) return pos; - debugger return {row: lines[pos.row].row, column: pos.column}; } diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index df4ada48..0b5744d5 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -64,17 +64,17 @@ module.exports = { "test: display occurrences" : function() { var text = 'abc\ndef\nxyz\nbcx\n'; editor.session.insert({row: 0, column: 0}, text); - occur.display(editor, {needle: 'bc'}); - assert.equal(editor.getValue(), 'abc\nbcx\n'); - occur.displayOriginal(editor); + occur.displayOccurContent(editor, {needle: 'bc'}); + assert.equal(editor.getValue(), 'abc\nbcx'); + occur.displayOriginalContent(editor); assert.equal(editor.getValue(), text); }, "test: original position from occur doc" : function() { var text = 'abc\ndef\nxyz\nbcx\n'; editor.session.insert({row: 0, column: 0}, text); - occur.display(editor, {needle: 'bc'}); - assert.equal(editor.getValue(), 'abc\nbcx\n'); + occur.displayOccurContent(editor, {needle: 'bc'}); + assert.equal(editor.getValue(), 'abc\nbcx'); var pos = occur.occurToOriginalPosition(editor.session, {row: 1, column: 2}); assert.position(pos, 3, 2); }, @@ -87,8 +87,7 @@ module.exports = { // run occur for lines including 'o' editor.execCommand('occur', {needle: 'o'}); - assert.equal(editor.getValue(), 'lo\nwo\n'); - + assert.equal(editor.getValue(), 'lo\nwo'); // command install OK? // assert.ok(editor.getReadOnly(), 'occur doc not marked as read only'); assert.ok(editor.getKeyboardHandler().isOccurHandler, 'no occur handler installed'); @@ -113,7 +112,7 @@ module.exports = { // run occur for lines including 'o' editor.execCommand('occur', {needle: 'o'}); - assert.equal(editor.getValue(), 'lo\nwo\n'); + assert.equal(editor.getValue(), 'lo\nwo'); assert.position(editor.getCursorPosition(), 0, 1, 'original -> occur pos'); // move to second line and accept From d75845f3aae6183aae951e659fdb27f74870982e Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 19:00:42 -0700 Subject: [PATCH 15/17] [occur] fixing recursive occurs --- lib/ace/commands/occur_commands.js | 7 ++++--- lib/ace/occur_test.js | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/ace/commands/occur_commands.js b/lib/ace/commands/occur_commands.js index c93c4da3..88e05eda 100644 --- a/lib/ace/commands/occur_commands.js +++ b/lib/ace/commands/occur_commands.js @@ -37,8 +37,9 @@ var config = require("../config"), var occurStartCommands = [{ name: "occur", exec: function(editor, options) { + var alreadyInOccur = !!editor.session.$occur; var occurSessionActive = new Occur().enter(editor, options); - if (occurSessionActive) OccurKeyboardHandler.installIn(editor); + if (occurSessionActive && !alreadyInOccur) OccurKeyboardHandler.installIn(editor); }, readOnly: true }]; @@ -50,7 +51,7 @@ var occurCommands = [{ var occur = editor.session.$occur; if (!occur) return; occur.exit(editor, {}); - OccurKeyboardHandler.uninstallFrom(editor); + if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor); }, readOnly: true }, { @@ -60,7 +61,7 @@ var occurCommands = [{ var occur = editor.session.$occur; if (!occur) return; occur.exit(editor, {translatePosition: true}); - OccurKeyboardHandler.uninstallFrom(editor); + if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor); }, readOnly: true }]; diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index 0b5744d5..88b67f5b 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -120,6 +120,29 @@ module.exports = { editor.execCommand('occuraccept'); assert.position(editor.getCursorPosition(), 3, 1, 'occur -> original pos'); + }, + + "test: recursive occur" : function() { + // setup + var text = 'x\nabc1\nx\nabc2\n'; + editor.session.insert({row: 0, column: 0}, text); + editor.commands.addCommands(occurCommands); + + // orig -> occur1 + editor.execCommand('occur', {needle: 'abc'}); + assert.equal(editor.getValue(), 'abc1\nabc2', "orig -> occur1"); + + // occur1 -> occur2 + editor.execCommand('occur', {needle: '2'}); + assert.equal(editor.getValue(), 'abc2', "occur1 -> occur2"); + + // occur2 -> occur1 + editor.execCommand('occurexit'); + assert.equal(editor.getValue(), 'abc1\nabc2', "occur2 -> occur1"); + + // occur1 -> orig + editor.execCommand('occurexit'); + assert.equal(editor.getValue(), text, "occur1 -> orig"); } }; From 5d28dbfb44154fae134362382a86cce2dcdbd517 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 19:01:12 -0700 Subject: [PATCH 16/17] [occur] keep highlights when exiting recursive occur session --- lib/ace/occur.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ace/occur.js b/lib/ace/occur.js index 1792a3a0..f45ddd1d 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -119,8 +119,6 @@ oop.inherits(Occur, Search); this.displayOriginalContent = function(editor) { editor.setSession(this.$originalSession); - this.highlight(this.$originalSession, null); - this.$originalSession._emit('changeBackMarker'); } /** From b974de5e0a0d05f74e55d43d96f057051fb02b74 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sun, 17 Mar 2013 19:08:44 -0700 Subject: [PATCH 17/17] [occur] removing debug code --- lib/ace/occur.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/ace/occur.js b/lib/ace/occur.js index f45ddd1d..902e025a 100644 --- a/lib/ace/occur.js +++ b/lib/ace/occur.js @@ -183,9 +183,6 @@ var dom = require('./lib/dom'); dom.importCssString(css, id); })(); -window.Occur = Occur -window.Document = Document - exports.Occur = Occur; });