/* ***** 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 EditSession = require("./edit_session").EditSession; var SearchHighlight = require("./search_highlight").SearchHighlight; /** * @class Occur * * 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. * **/ /** * Creates a new `Occur` object. * * @constructor **/ 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(); this.displayOccurContent(editor, 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 pos = options.translatePosition && editor.getCursorPosition(); var translatedPos = pos && this.occurToOriginalPosition(editor.session, pos); this.displayOriginalContent(editor); if (translatedPos) editor.moveCursorToPosition(translatedPos); 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.displayOccurContent = function(editor, options) { // this.setSession(session || new EditSession("")) this.$originalSession = editor.session; var found = this.matchingLines(editor.session, options); var lines = found.map(function(foundLine) { return foundLine.content; }); var occurSession = new EditSession(lines.join('\n')); occurSession.$occur = this; occurSession.$occurMatchingLines = found; editor.setSession(occurSession); this.highlight(occurSession, options.re); occurSession._emit('changeBackMarker'); } this.displayOriginalContent = function(editor) { editor.setSession(this.$originalSession); } /** * 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.$occurMatchingLines; var 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.$occurMatchingLines; if (!lines || !lines[pos.row]) return pos; return {row: lines[pos.row].row, column: pos.column}; } this.matchingLines = function(session, options) { options = oop.mixin({}, options); if (!session || !options.needle) return []; var search = new Search(); search.set(options); return search.findAll(session).reduce(function(lines, range) { var row = range.start.row; var last = lines[lines.length-1]; return last && last.row === row ? lines : lines.concat({row: row, content: session.getLine(row)}); }, []); } }).call(Occur.prototype); var dom = require('./lib/dom'); dom.importCssString(".ace_occur-highlight {\n\ border-radius: 4px;\n\ background-color: rgba(87, 255, 8, 0.25);\n\ position: absolute;\n\ z-index: 4;\n\ -moz-box-sizing: border-box;\n\ -webkit-box-sizing: border-box;\n\ box-sizing: border-box;\n\ box-shadow: 0 0 4px rgb(91, 255, 50);\n\ }\n\ .ace_dark .ace_occur-highlight {\n\ background-color: rgb(80, 140, 85);\n\ box-shadow: 0 0 4px rgb(60, 120, 70);\n\ }\n", "incremental-occur-highlighting"); exports.Occur = Occur; });