/
githubmirror
/
brackets
Обзор
Документация
Войти
/
githubmirror
/
brackets
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/extensions/default/CodeFolding/main.js
466 строк
19 KB
Patrick Oladimeji
removed unused variable
17 апр 2017, 02:26
17 апр 2017, 02:26
a16d58e
Код
Авторство
О чём код?
/* * Copyright (c) 2013 Patrick Oladimeji. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ /** * Code folding extension for brackets * @author Patrick Oladimeji * @date 10/24/13 9:35:26 AM */ define(function (require, exports, module) { "use strict"; var CodeMirror = brackets.getModule("thirdparty/CodeMirror/lib/codemirror"), Strings = brackets.getModule("strings"), AppInit = brackets.getModule("utils/AppInit"), CommandManager = brackets.getModule("command/CommandManager"), DocumentManager = brackets.getModule("document/DocumentManager"), Editor = brackets.getModule("editor/Editor").Editor, EditorManager = brackets.getModule("editor/EditorManager"), ProjectManager = brackets.getModule("project/ProjectManager"), ViewStateManager = brackets.getModule("view/ViewStateManager"), KeyBindingManager = brackets.getModule("command/KeyBindingManager"), ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), Menus = brackets.getModule("command/Menus"), prefs = require("Prefs"), COLLAPSE_ALL = "codefolding.collapse.all", COLLAPSE = "codefolding.collapse", EXPAND = "codefolding.expand", EXPAND_ALL = "codefolding.expand.all", GUTTER_NAME = "CodeMirror-foldgutter", CODE_FOLDING_GUTTER_PRIORITY = Editor.CODE_FOLDING_GUTTER_PRIORITY, codeFoldingMenuDivider = "codefolding.divider", collapseKey = "Ctrl-Alt-[", expandKey = "Ctrl-Alt-]", collapseAllKey = "Alt-1", expandAllKey = "Shift-Alt-1", collapseAllKeyMac = "Cmd-1", expandAllKeyMac = "Cmd-Shift-1"; ExtensionUtils.loadStyleSheet(module, "main.less"); // Load CodeMirror addons brackets.getModule(["thirdparty/CodeMirror/addon/fold/brace-fold"]); brackets.getModule(["thirdparty/CodeMirror/addon/fold/comment-fold"]); brackets.getModule(["thirdparty/CodeMirror/addon/fold/markdown-fold"]); // Still using slightly modified versions of the foldcode.js and foldgutter.js since we // need to modify the gutter click handler to take care of some collapse and expand features // e.g. collapsing all children when 'alt' key is pressed var foldGutter = require("foldhelpers/foldgutter"), foldCode = require("foldhelpers/foldcode"), indentFold = require("foldhelpers/indentFold"), handlebarsFold = require("foldhelpers/handlebarsFold"), selectionFold = require("foldhelpers/foldSelected"); /** Set to true when init() has run; set back to false after deinit() has run */ var _isInitialized = false; /** Used to keep track of files for which line folds have been restored.*/ /** * Restores the linefolds in the editor using values fetched from the preference store * Checks the document to ensure that changes have not been made (e.g., in a different editor) * to invalidate the saved line folds. * Selection Folds are found by comparing the line folds in the preference store with the * selection ranges in the viewState of the current document. Any selection range in the view state * that is folded in the prefs will be folded. Unlike other fold range finder, the only validation * on selection folds is to check that they satisfy the minimum fold range. * @param {Editor} editor the editor whose saved line folds should be restored */ function restoreLineFolds(editor) { /** * Checks if the range from and to Pos is the same as the selection start and end Pos * @param {Object} range {from, to} where from and to are CodeMirror.Pos objects * @param {Object} selection {start, end} where start and end are CodeMirror.Pos objects * @returns {Boolean} true if the range and selection span the same region and false otherwise */ function rangeEqualsSelection(range, selection) { return range.from.line === selection.start.line && range.from.ch === selection.start.ch && range.to.line === selection.end.line && range.to.ch === selection.end.ch; } /** * Checks if the range is equal to one of the selections in the viewState * @param {Object} range {from, to} where from and to are CodeMirror.Pos objects. * @param {Object} viewState The current editor's ViewState object * @returns {Boolean} true if the range is found in the list of selections or false if not. */ function isInViewStateSelection(range, viewState) { if (!viewState || !viewState.selections) { return false; } return viewState.selections.some(function (selection) { return rangeEqualsSelection(range, selection); }); } var saveFolds = prefs.getSetting("saveFoldStates"); if (!editor || !saveFolds) { if (editor) { editor._codeMirror._lineFolds = editor._codeMirror._lineFolds || {}; } return; } var cm = editor._codeMirror; var viewState = ViewStateManager.getViewState(editor.document.file); var path = editor.document.file.fullPath; var folds = cm._lineFolds || prefs.getFolds(path) || {}; //separate out selection folds from non-selection folds var nonSelectionFolds = {}, selectionFolds = {}, range; Object.keys(folds).forEach(function (line) { range = folds[line]; if (isInViewStateSelection(range, viewState)) { selectionFolds[line] = range; } else { nonSelectionFolds[line] = range; } }); nonSelectionFolds = cm.getValidFolds(nonSelectionFolds); //add the selection folds Object.keys(selectionFolds).forEach(function (line) { nonSelectionFolds[line] = selectionFolds[line]; }); cm._lineFolds = nonSelectionFolds; prefs.setFolds(path, cm._lineFolds); Object.keys(cm._lineFolds).forEach(function (line) { cm.foldCode(Number(line), {range: cm._lineFolds[line]}); }); } /** * Saves the line folds in the editor using the preference storage * @param {Editor} editor the editor whose line folds should be saved */ function saveLineFolds(editor) { var saveFolds = prefs.getSetting("saveFoldStates"); if (!editor || !saveFolds) { return; } var folds = editor._codeMirror._lineFolds || {}; var path = editor.document.file.fullPath; if (Object.keys(folds).length) { prefs.setFolds(path, folds); } else { prefs.setFolds(path, undefined); } } /** * Event handler for gutter click. Manages folding and unfolding code regions. If the Alt key * is pressed while clicking the fold gutter, child code fragments are also folded/unfolded * up to a level defined in the `maxFoldLevel' preference. * @param {!CodeMirror} cm the CodeMirror object * @param {number} line the line number for the clicked gutter * @param {string} gutter the name of the gutter element clicked * @param {!KeyboardEvent} event the underlying dom event triggered for the gutter click */ function onGutterClick(cm, line, gutter, event) { var opts = cm.state.foldGutter.options, pos = CodeMirror.Pos(line); if (gutter !== opts.gutter) { return; } var range; var _lineFolds = cm._lineFolds; if (cm.isFolded(line)) { if (event.altKey) { // unfold code including children range = _lineFolds[line]; CodeMirror.commands.unfoldAll(cm, range.from.line, range.to.line); } else { cm.unfoldCode(line, {range: _lineFolds[line]}); } } else { if (event.altKey) { range = CodeMirror.fold.auto(cm, pos); if (range) { CodeMirror.commands.foldToLevel(cm, range.from.line, range.to.line); } } else { cm.foldCode(line); } } } /** * Collapses the code region nearest the current cursor position. * Nearest is found by searching from the current line and moving up the document until an * opening code-folding region is found. */ function collapseCurrent() { var editor = EditorManager.getFocusedEditor(); if (!editor) { return; } var cm = editor._codeMirror; var cursor = editor.getCursorPos(), i; // Move cursor up until a collapsible line is found for (i = cursor.line; i >= 0; i--) { if (cm.foldCode(i)) { editor.setCursorPos(i); return; } } } /** * Expands the code region at the current cursor position. */ function expandCurrent() { var editor = EditorManager.getFocusedEditor(); if (editor) { var cursor = editor.getCursorPos(), cm = editor._codeMirror; cm.unfoldCode(cursor.line); } } /** * Collapses all foldable regions in the current document. Folding is done up to a level 'n' * which is defined in the `maxFoldLevel` preference. Levels refer to fold heirarchies e.g., for the following * code fragment, the function is level 1, the if statement is level 2 and the forEach is level 3 * * function sample() { * if (debug) { * logMessages.forEach(function (m) { * console.debug(m); * }); * } * } */ function collapseAll() { var editor = EditorManager.getFocusedEditor(); if (editor) { var cm = editor._codeMirror; CodeMirror.commands.foldToLevel(cm); } } /** * Expands all folded regions in the current document */ function expandAll() { var editor = EditorManager.getFocusedEditor(); if (editor) { var cm = editor._codeMirror; CodeMirror.commands.unfoldAll(cm); } } function clearGutter(editor) { var cm = editor._codeMirror; var BLANK_GUTTER_CLASS = "CodeMirror-foldgutter-blank"; editor.clearGutter(GUTTER_NAME); var blank = window.document.createElement("div"); blank.className = BLANK_GUTTER_CLASS; var vp = cm.getViewport(); cm.operation(function () { cm.eachLine(vp.from, vp.to, function (line) { editor.setGutterMarker(line.lineNo(), GUTTER_NAME, blank); }); }); } /** * Renders and sets up event listeners the code-folding gutter. * @param {Editor} editor the editor on which to initialise the fold gutter */ function setupGutterEventListeners(editor) { var cm = editor._codeMirror; $(editor.getRootElement()).addClass("folding-enabled"); cm.setOption("foldGutter", {onGutterClick: onGutterClick}); $(cm.getGutterElement()).on({ mouseenter: function () { if (prefs.getSetting("hideUntilMouseover")) { foldGutter.updateInViewport(cm); } else { $(editor.getRootElement()).addClass("over-gutter"); } }, mouseleave: function () { if (prefs.getSetting("hideUntilMouseover")) { clearGutter(editor); } else { $(editor.getRootElement()).removeClass("over-gutter"); } } }); } /** * Remove the fold gutter for a given CodeMirror instance. * @param {Editor} editor the editor instance whose gutter should be removed */ function removeGutters(editor) { Editor.unregisterGutter(GUTTER_NAME); $(editor.getRootElement()).removeClass("folding-enabled"); CodeMirror.defineOption("foldGutter", false, null); } /** * Add gutter and restore saved expand/collapse state. * @param {Editor} editor the editor instance where gutter should be added. */ function enableFoldingInEditor(editor) { restoreLineFolds(editor); setupGutterEventListeners(editor); editor._codeMirror.refresh(); } /** * When a brand new editor is seen, initialise fold-gutter and restore line folds in it. * Save line folds in departing editor in case it's getting closed. * @param {object} event the event object * @param {Editor} current the current editor * @param {Editor} previous the previous editor */ function onActiveEditorChanged(event, current, previous) { if (current && !current._codeMirror._lineFolds) { enableFoldingInEditor(current); } if (previous) { saveLineFolds(previous); } } /** * Saves the line folds in the current full editor before it is closed. */ function saveBeforeClose() { // We've already saved all other open editors when they go active->inactive saveLineFolds(EditorManager.getActiveEditor()); } /** * Remove code-folding functionality */ function deinit() { _isInitialized = false; KeyBindingManager.removeBinding(collapseKey); KeyBindingManager.removeBinding(expandKey); KeyBindingManager.removeBinding(collapseAllKey); KeyBindingManager.removeBinding(expandAllKey); KeyBindingManager.removeBinding(collapseAllKeyMac); KeyBindingManager.removeBinding(expandAllKeyMac); //remove menus Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuDivider(codeFoldingMenuDivider.id); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(COLLAPSE); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(EXPAND); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(COLLAPSE_ALL); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).removeMenuItem(EXPAND_ALL); EditorManager.off(".CodeFolding"); DocumentManager.off(".CodeFolding"); ProjectManager.off(".CodeFolding"); // Remove gutter & revert collapsed sections in all currently open editors Editor.forEveryEditor(function (editor) { CodeMirror.commands.unfoldAll(editor._codeMirror); }); removeGutters(); } /** * Enable code-folding functionality */ function init() { _isInitialized = true; foldCode.init(); foldGutter.init(); // Many CodeMirror modes specify which fold helper should be used for that language. For a few that // don't, we register helpers explicitly here. We also register a global helper for generic indent-based // folding, which cuts across all languages if enabled via preference. CodeMirror.registerGlobalHelper("fold", "selectionFold", function (mode, cm) { return prefs.getSetting("makeSelectionsFoldable"); }, selectionFold); CodeMirror.registerGlobalHelper("fold", "indent", function (mode, cm) { return prefs.getSetting("alwaysUseIndentFold"); }, indentFold); CodeMirror.registerHelper("fold", "handlebars", handlebarsFold); CodeMirror.registerHelper("fold", "htmlhandlebars", handlebarsFold); CodeMirror.registerHelper("fold", "htmlmixed", handlebarsFold); EditorManager.on("activeEditorChange.CodeFolding", onActiveEditorChanged); DocumentManager.on("documentRefreshed.CodeFolding", function (event, doc) { restoreLineFolds(doc._masterEditor); }); ProjectManager.on("beforeProjectClose.CodeFolding beforeAppClose.CodeFolding", saveBeforeClose); //create menus codeFoldingMenuDivider = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuDivider(); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(COLLAPSE_ALL); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(EXPAND_ALL); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(COLLAPSE); Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(EXPAND); //register keybindings KeyBindingManager.addBinding(COLLAPSE_ALL, [ {key: collapseAllKey}, {key: collapseAllKeyMac, platform: "mac"} ]); KeyBindingManager.addBinding(EXPAND_ALL, [ {key: expandAllKey}, {key: expandAllKeyMac, platform: "mac"} ]); KeyBindingManager.addBinding(COLLAPSE, collapseKey); KeyBindingManager.addBinding(EXPAND, expandKey); // Add gutters & restore saved expand/collapse state in all currently open editors Editor.registerGutter(GUTTER_NAME, CODE_FOLDING_GUTTER_PRIORITY); Editor.forEveryEditor(function (editor) { enableFoldingInEditor(editor); }); } /** * Register change listener for the preferences file. */ function watchPrefsForChanges() { prefs.prefsObject.on("change", function (e, data) { if (data.ids.indexOf("enabled") > -1) { // Check if enabled state mismatches whether code-folding is actually initialized (can't assume // since preference change events can occur when the value hasn't really changed) var isEnabled = prefs.getSetting("enabled"); if (isEnabled && !_isInitialized) { init(); } else if (!isEnabled && _isInitialized) { deinit(); } } }); } AppInit.htmlReady(function () { CommandManager.register(Strings.COLLAPSE_ALL, COLLAPSE_ALL, collapseAll); CommandManager.register(Strings.EXPAND_ALL, EXPAND_ALL, expandAll); CommandManager.register(Strings.COLLAPSE_CURRENT, COLLAPSE, collapseCurrent); CommandManager.register(Strings.EXPAND_CURRENT, EXPAND, expandCurrent); if (prefs.getSetting("enabled")) { init(); } watchPrefsForChanges(); }); });