mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
191 lines
7.2 KiB
JavaScript
191 lines
7.2 KiB
JavaScript
|
/* ***** 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;
|
||
|
|
||
|
});
|