From 43df078a8b20e4f7df53756fdd3f772887ac6e5a Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Fri, 2 Jun 2017 10:39:55 +0530 Subject: [PATCH 01/15] First commit - sequential navigation in edit history --- src/editor/Editor.js | 3 + .../NavigationProvider.js | 215 ++++++++++++++++++ .../NavigationAndHistory/keyboard.json | 10 + .../default/NavigationAndHistory/main.js | 4 +- src/nls/root/strings.js | 2 + 5 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 src/extensions/default/NavigationAndHistory/NavigationProvider.js diff --git a/src/editor/Editor.js b/src/editor/Editor.js index e7f5170c63c..2060fc4d838 100644 --- a/src/editor/Editor.js +++ b/src/editor/Editor.js @@ -1017,6 +1017,9 @@ define(function (require, exports, module) { this._codeMirror.on("cursorActivity", function (instance) { self.trigger("cursorActivity", self); }); + this._codeMirror.on("beforeSelectionChange", function (instance, selectionObj) { + self.trigger("beforeSelectionChange", selectionObj); + }); this._codeMirror.on("scroll", function (instance) { // If this editor is visible, close all dropdowns on scroll. // (We don't want to do this if we're just scrolling in a non-visible editor diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js new file mode 100644 index 00000000000..2535c97e5e9 --- /dev/null +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2016 - present Adobe Systems Incorporated. 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. + * + */ + +define(function (require, exports, module) { + "use strict"; + + var Strings = brackets.getModule("strings"), + MainViewManager = brackets.getModule("view/MainViewManager"), + DocumentManager = brackets.getModule("document/DocumentManager"), + DocumentCommandHandlers = brackets.getModule("document/DocumentCommandHandlers"), + EditorManager = brackets.getModule("editor/EditorManager"), + Editor = brackets.getModule("editor/Editor"), + ProjectManager = brackets.getModule("project/ProjectManager"), + CommandManager = brackets.getModule("command/CommandManager"), + Commands = brackets.getModule("command/Commands"), + Menus = brackets.getModule("command/Menus"), + KeyBindingManager = brackets.getModule("command/KeyBindingManager"); + + var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); + + // Command constants for navigation history + var NAVIGATION_JUMP_BACK = "navigation.jump.back", + NAVIGATION_JUMP_FWD = "navigation.jump.fwd"; + + var NAV_FRAME_CAPTURE_LATENCY = 3000; + + + /* + * Contains list of most recently opened files and their last known cursor position + * @private + * @type {Array.} + */ + var jumpToPosStack = [], + jumpedPosStack = [], + captureTimer, + activePosNotSynched = false, + jumpInProgress, + command_JumpBack, + command_JumpFwd, + cmMarkers = {}; + + + function NavigationFrame(editor, selectionObj) { + this.cm = editor._codeMirror; + this.file = editor.document.file._path; + this.paneId = editor._paneId; + this.uId = (new Date()).getTime() + ""; + this.selections = []; + this.bookMarkIds = []; + this._createMarkers(selectionObj.ranges); + this._bindEditor(editor); + } + + NavigationFrame.prototype._bindEditor = function (editor) { + var self = this; + editor.on("beforeDestroy", function () { + self._backupSelectionRanges(); + self.cm = null; + self.bookMarkIds = null; + }); + } + + NavigationFrame.prototype._createMarkers = function (ranges) { + var range, index, bookMark; + this.bookMarkIds = []; + for (index in ranges) { + range = ranges[index]; + if (range.anchor.line === range.head.line && range.anchor.ch === range.head.ch) { + bookMark = this.cm.setBookmark(range.anchor, range.head); + this.bookMarkIds.push(bookMark.id); + } else { + this.cm.markText(range.anchor, range.head, {className: (this.uId + "")}); + } + } + }; + + NavigationFrame.prototype._backupSelectionRanges = function () { + if (!this.cm) { + return; + } + + this.selections = []; + var marker, selection, index; + var self = this; + var markers = this.cm.getAllMarks().filter(function (entry) { + if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { + return entry; + } + }) + for (index in markers) { + marker = markers[index]; + selection = marker.find(); + if (marker.type === "bookmark") { + this.selections.push({start: selection, end: selection}); + } else { + this.selections.push({start: selection.from, end: selection.to}); + } + } + }; + + NavigationFrame.prototype.goTo = function () { + var self = this; + this._backupSelectionRanges(); + jumpInProgress = true; + CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { + EditorManager.getCurrentFullEditor().setSelections(self.selections, true); + command_JumpFwd.setEnabled(true); + }).always(function () { + jumpInProgress = false; + }); + }; + + function _recordJumpDef(event, selectionObj) { + if (jumpInProgress) { + return; + } + jumpedPosStack = []; + if (selectionObj.origin !== "+move" && (window.event && window.event.type !== "input")) { + if (captureTimer) { + window.clearTimeout(captureTimer); + captureTimer = null; + } + captureTimer = window.setTimeout(function () { + jumpToPosStack.push(new NavigationFrame(event.target, selectionObj)); + command_JumpFwd.setEnabled(false); + if (jumpToPosStack.length > 1) { + command_JumpBack.setEnabled(true); + } + activePosNotSynched = false; + }, NAV_FRAME_CAPTURE_LATENCY); + } else { + activePosNotSynched = true; + } + } + + function _jumpToPosBack() { + if (!jumpedPosStack.length) { + if (activePosNotSynched) { + jumpToPosStack.push(new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()})); + } else { + jumpedPosStack.push(jumpToPosStack.pop()); + } + } + var navFrame = jumpToPosStack.pop(); + if (navFrame) { + jumpedPosStack.push(navFrame); + navFrame.goTo(); + } + } + + function _jumpToPosFwd() { + var navFrame = jumpedPosStack.pop(); + if (navFrame) { + jumpToPosStack.push(navFrame); + navFrame.goTo(); + } + } + + /** + * Handle Active Editor change to update navigation information + * @private + */ + function _handleActiveEditorChange(event, current, previous) { + if (current && current._paneId) { // Handle only full editors + current.on("beforeSelectionChange", _recordJumpDef); + } + + if (previous && previous._paneId) { + previous.off("beforeSelectionChange", _recordJumpDef); + } + } + + function _handleProjectOpen() { + jumpToPosStack = []; + jumpedPosStack = []; + } + + function init() { + CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _jumpToPosBack); + CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _jumpToPosFwd); + command_JumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); + command_JumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); + command_JumpBack.setEnabled(false); + command_JumpFwd.setEnabled(false); + KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); + KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); + var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU); + menu.addMenuItem(NAVIGATION_JUMP_BACK, "", Menus.AFTER, Commands.NAVIGATE_PREV_DOC); + menu.addMenuItem(NAVIGATION_JUMP_FWD, "", Menus.AFTER, NAVIGATION_JUMP_BACK); + EditorManager.on("activeEditorChange", _handleActiveEditorChange); + ProjectManager.on("projectOpen", _handleProjectOpen); + } + + exports.init = init; +}); diff --git a/src/extensions/default/NavigationAndHistory/keyboard.json b/src/extensions/default/NavigationAndHistory/keyboard.json index b32d95c98d3..9957386d844 100644 --- a/src/extensions/default/NavigationAndHistory/keyboard.json +++ b/src/extensions/default/NavigationAndHistory/keyboard.json @@ -27,5 +27,15 @@ "key": "Cmd-Shift-[", "platform": "mac" } + ], + "navigation.jump.back": [ + { + "key": "Alt-I" + } + ], + "navigation.jump.fwd": [ + { + "key": "Alt-Shift-I" + } ] } diff --git a/src/extensions/default/NavigationAndHistory/main.js b/src/extensions/default/NavigationAndHistory/main.js index ebe702f0bdc..18bb091fba5 100644 --- a/src/extensions/default/NavigationAndHistory/main.js +++ b/src/extensions/default/NavigationAndHistory/main.js @@ -45,7 +45,8 @@ define(function (require, exports, module) { PreferencesManager = brackets.getModule("preferences/PreferencesManager"), KeyBindingManager = brackets.getModule("command/KeyBindingManager"), ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), - Mustache = brackets.getModule("thirdparty/mustache/mustache"); + Mustache = brackets.getModule("thirdparty/mustache/mustache"), + NavigationProvider = require("NavigationProvider"); var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); @@ -829,5 +830,6 @@ define(function (require, exports, module) { AppInit.appReady(function () { ExtensionUtils.loadStyleSheet(module, "styles/recent-files.css"); + NavigationProvider.init(); }); }); diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index fc545114e54..640e91e5daa 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -415,6 +415,8 @@ define({ "CMD_CSS_QUICK_EDIT_NEW_RULE" : "New Rule", "CMD_NEXT_DOC" : "Next Document", "CMD_PREV_DOC" : "Previous Document", + "CMD_NAVIGATE_BACKWARD" : "Navigate Backward", + "CMD_NAVIGATE_FORWARD" : "Navigate Forward", "CMD_NEXT_DOC_LIST_ORDER" : "Next Document in List", "CMD_PREV_DOC_LIST_ORDER" : "Previous Document in List", "CMD_SHOW_IN_TREE" : "Show in File Tree", From 21702eac1256db48a265b311b3c1fad91be897e5 Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Fri, 2 Jun 2017 10:42:24 +0530 Subject: [PATCH 02/15] Fix lint errors --- .../default/NavigationAndHistory/NavigationProvider.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 2535c97e5e9..423e9ff3a8b 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -78,7 +78,7 @@ define(function (require, exports, module) { self.cm = null; self.bookMarkIds = null; }); - } + }; NavigationFrame.prototype._createMarkers = function (ranges) { var range, index, bookMark; @@ -106,7 +106,7 @@ define(function (require, exports, module) { if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { return entry; } - }) + }); for (index in markers) { marker = markers[index]; selection = marker.find(); From 91690e7b050c1e8da2b1d1f0ce87fd3bbde4a493 Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Fri, 2 Jun 2017 17:26:38 +0530 Subject: [PATCH 03/15] Handle undefined history entries --- src/extensions/default/NavigationAndHistory/main.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/extensions/default/NavigationAndHistory/main.js b/src/extensions/default/NavigationAndHistory/main.js index 18bb091fba5..2be81019915 100644 --- a/src/extensions/default/NavigationAndHistory/main.js +++ b/src/extensions/default/NavigationAndHistory/main.js @@ -646,6 +646,10 @@ define(function (require, exports, module) { function _initRecentFilesList() { _mrofList = PreferencesManager.getViewState(OPEN_FILES_VIEW_STATE, _getPrefsContext()) || []; + + _mrofList = _mrofList.filter(function (entry) { + return entry; + }); // Have a check on the number of entries to fallback to working set if we detect corruption if (_mrofList.length < MainViewManager.getWorkingSetSize(MainViewManager.ALL_PANES)) { _mrofList = _createMROFList(); From 88cac89ec7a72642c2333072197e82b744779a42 Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Mon, 5 Jun 2017 10:52:40 +0530 Subject: [PATCH 04/15] Added comments and some additional edge case handling --- .../NavigationProvider.js | 234 ++++++++++++++---- 1 file changed, 189 insertions(+), 45 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 423e9ff3a8b..41afb6c284f 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 - present Adobe Systems Incorporated. All rights reserved. + * Copyright (c) 2017 - present Adobe Systems Incorporated. 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"), @@ -20,7 +20,12 @@ * DEALINGS IN THE SOFTWARE. * */ - + +/** + * Manages Editor navigation history to aid back/fwd movement between the edit positions + * in the active project context. The navigation history is purely in-memory and not + * persisted to file system when a project is being closed. + */ define(function (require, exports, module) { "use strict"; @@ -34,43 +39,103 @@ define(function (require, exports, module) { CommandManager = brackets.getModule("command/CommandManager"), Commands = brackets.getModule("command/Commands"), Menus = brackets.getModule("command/Menus"), - KeyBindingManager = brackets.getModule("command/KeyBindingManager"); + KeyBindingManager = brackets.getModule("command/KeyBindingManager"), + FileSystem = brackets.getModule("filesystem/FileSystem"); var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); // Command constants for navigation history var NAVIGATION_JUMP_BACK = "navigation.jump.back", NAVIGATION_JUMP_FWD = "navigation.jump.fwd"; - - var NAV_FRAME_CAPTURE_LATENCY = 3000; - + + // The latency time to capture an explicit cursor movement as a navigation frame + var NAV_FRAME_CAPTURE_LATENCY = 2000; + + /* + * Contains list of most recently known cursor positions. + * @private + * @type {Array.} + */ + var jumpToPosStack = []; /* - * Contains list of most recently opened files and their last known cursor position + * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command. * @private * @type {Array.} */ - var jumpToPosStack = [], - jumpedPosStack = [], + var jumpedPosStack = [], captureTimer, activePosNotSynched = false, jumpInProgress, command_JumpBack, command_JumpFwd, cmMarkers = {}; + + /** + * Function to enable/disable navigation command based on cursor positions availability. + * @private + */ + function _validateNavigationCmds() { + if (jumpToPosStack.length > 0) { + command_JumpBack.setEnabled(true); + } else { + command_JumpBack.setEnabled(false); + } + if (jumpedPosStack.length > 0) { + command_JumpFwd.setEnabled(true); + } else { + command_JumpFwd.setEnabled(false); + } + } + /** + * Function to check existence of a file entry + * @private + */ + function _checkIfExist(entry) { + var deferred = new $.Deferred(), + fileEntry = FileSystem.getFileForPath(entry.file); + + if (entry.inMem) { + var indxInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); + // Remove entry if InMemoryFile is not found in Working set + if (indxInWS === -1) { + deferred.reject(); + } else { + deferred.resolve(); + } + } else { + fileEntry.exists(function (err, exists) { + if (!err && exists) { + deferred.resolve(); + } else { + deferred.reject(); + } + }); + } + + return deferred.promise(); + } + + /** + * Prototype to capture a navigation frame and it's various data/functional attributues + */ function NavigationFrame(editor, selectionObj) { this.cm = editor._codeMirror; this.file = editor.document.file._path; + this.inMem = editor.document.file.constructor.name === "InMemoryFile" ? true : false; this.paneId = editor._paneId; - this.uId = (new Date()).getTime() + ""; + this.uId = (new Date()).getTime(); this.selections = []; this.bookMarkIds = []; this._createMarkers(selectionObj.ranges); this._bindEditor(editor); } + /** + * Binds the lifecycle event listner of the editor for which this frame is captured + */ NavigationFrame.prototype._bindEditor = function (editor) { var self = this; editor.on("beforeDestroy", function () { @@ -80,20 +145,34 @@ define(function (require, exports, module) { }); }; + /** + * Function to create CM TextMarkers for the navigated positions/selections. + * This logic is required to ensure that the captured navaigation positions + * stay valid and contextual even when the actual document text mutates. + * The mutations which are handled here : + * -> Addition/Deletion of lines before the captured position + * -> Addition/Updation of characters in the captured selection + */ NavigationFrame.prototype._createMarkers = function (ranges) { var range, index, bookMark; this.bookMarkIds = []; for (index in ranges) { range = ranges[index]; + // 'markText' has to used for a non-zero length position, if current selection is + // of zero length use bookmark instead. if (range.anchor.line === range.head.line && range.anchor.ch === range.head.ch) { bookMark = this.cm.setBookmark(range.anchor, range.head); this.bookMarkIds.push(bookMark.id); } else { - this.cm.markText(range.anchor, range.head, {className: (this.uId + "")}); + this.cm.markText(range.anchor, range.head, {className: (this.uId)}); } } }; + /** + * Function to actually convert the CM markers to CM positions which can be used to + * set selections or cursor positions in Editor. + */ NavigationFrame.prototype._backupSelectionRanges = function () { if (!this.cm) { return; @@ -118,34 +197,47 @@ define(function (require, exports, module) { } }; + /** + * Function to actually navigate to the position(file,selections) captured in this frame + */ NavigationFrame.prototype.goTo = function () { var self = this; this._backupSelectionRanges(); jumpInProgress = true; CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { EditorManager.getCurrentFullEditor().setSelections(self.selections, true); - command_JumpFwd.setEnabled(true); + _validateNavigationCmds(); }).always(function () { jumpInProgress = false; }); }; + + /** + * Function to capture a non-zero set of selections as a navigation frame. + * The assumptions behind capturing a frame as a navigation frame are : + * + * -> If it's set by user explicitly (using mouse click or jump to definition) + * -> By clicking on search results + * -> Change of cursor by keyboard navigation keys or actual edits are not captured. + * + * @private + */ function _recordJumpDef(event, selectionObj) { if (jumpInProgress) { return; } + // Reset forward navigation stack if we are capturing a new event jumpedPosStack = []; + if (captureTimer) { + window.clearTimeout(captureTimer); + captureTimer = null; + } + // Ensure cursor activity has not happened because of arrow keys or edit if (selectionObj.origin !== "+move" && (window.event && window.event.type !== "input")) { - if (captureTimer) { - window.clearTimeout(captureTimer); - captureTimer = null; - } captureTimer = window.setTimeout(function () { jumpToPosStack.push(new NavigationFrame(event.target, selectionObj)); - command_JumpFwd.setEnabled(false); - if (jumpToPosStack.length > 1) { - command_JumpBack.setEnabled(true); - } + _validateNavigationCmds(); activePosNotSynched = false; }, NAV_FRAME_CAPTURE_LATENCY); } else { @@ -153,26 +245,81 @@ define(function (require, exports, module) { } } - function _jumpToPosBack() { + /** + * Command handler to navigate backward + */ + function _navigateBack() { if (!jumpedPosStack.length) { if (activePosNotSynched) { jumpToPosStack.push(new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()})); - } else { - jumpedPosStack.push(jumpToPosStack.pop()); } } var navFrame = jumpToPosStack.pop(); if (navFrame) { - jumpedPosStack.push(navFrame); - navFrame.goTo(); + // We will check for the file existence now, if it doesn't exist we will jump back again + // but discard the popped frame as invalid. + _checkIfExist(navFrame).done(function () { + jumpedPosStack.push(navFrame); + navFrame.goTo(); + }).fail(function () { + _validateNavigationCmds(); + CommandManager.execute(NAVIGATION_JUMP_BACK); + }); } } - function _jumpToPosFwd() { + /** + * Command handler to navigate forward + */ + function _navigateFwd() { var navFrame = jumpedPosStack.pop(); if (navFrame) { - jumpToPosStack.push(navFrame); - navFrame.goTo(); + // We will check for the file existence now, if it doesn't exist we will jump back again + // but discard the popped frame as invalid. + _checkIfExist(navFrame).done(function () { + jumpToPosStack.push(navFrame); + navFrame.goTo(); + }).fail(function () { + _validateNavigationCmds(); + CommandManager.execute(NAVIGATION_JUMP_FWD); + }); + } + } + + /** + * Function to initialize navigation menu items. + * @private + */ + function _initNavigationMenuItems() { + var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU); + menu.addMenuItem(NAVIGATION_JUMP_BACK, "", Menus.AFTER, Commands.NAVIGATE_PREV_DOC); + menu.addMenuItem(NAVIGATION_JUMP_FWD, "", Menus.AFTER, NAVIGATION_JUMP_BACK); + } + + /** + * Function to initialize navigation commands and it's keyboard shortcuts. + * @private + */ + function _initNavigationCommands() { + CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack); + CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateFwd); + command_JumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); + command_JumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); + command_JumpBack.setEnabled(false); + command_JumpFwd.setEnabled(false); + KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); + KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); + _initNavigationMenuItems(); + } + + /** + * Function to request a navigation frame creation explicitly. + * @private + */ + function _captureFrame(editor) { + // Capture the active position now if it was not captured earlier + if ((activePosNotSynched || !jumpToPosStack.length) && !jumpInProgress) { + jumpToPosStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); } } @@ -181,35 +328,32 @@ define(function (require, exports, module) { * @private */ function _handleActiveEditorChange(event, current, previous) { + if (previous && previous._paneId) { // Handle only full editors + previous.off("beforeSelectionChange", _recordJumpDef); + _captureFrame(previous); + _validateNavigationCmds(); + } + if (current && current._paneId) { // Handle only full editors + activePosNotSynched = true; current.on("beforeSelectionChange", _recordJumpDef); } - - if (previous && previous._paneId) { - previous.off("beforeSelectionChange", _recordJumpDef); - } } function _handleProjectOpen() { jumpToPosStack = []; jumpedPosStack = []; } - - function init() { - CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _jumpToPosBack); - CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _jumpToPosFwd); - command_JumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); - command_JumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); - command_JumpBack.setEnabled(false); - command_JumpFwd.setEnabled(false); - KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); - KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); - var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU); - menu.addMenuItem(NAVIGATION_JUMP_BACK, "", Menus.AFTER, Commands.NAVIGATE_PREV_DOC); - menu.addMenuItem(NAVIGATION_JUMP_FWD, "", Menus.AFTER, NAVIGATION_JUMP_BACK); + + function _initHandlers() { EditorManager.on("activeEditorChange", _handleActiveEditorChange); ProjectManager.on("projectOpen", _handleProjectOpen); } + + function init() { + _initNavigationCommands(); + _initHandlers(); + } exports.init = init; }); From fbae4dbaf7e695b322b579adcdba468491da71ce Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Mon, 5 Jun 2017 13:27:44 +0530 Subject: [PATCH 05/15] Update code review comments --- .../NavigationProvider.js | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 41afb6c284f..129624b6bc4 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -64,29 +64,19 @@ define(function (require, exports, module) { * @type {Array.} */ var jumpedPosStack = [], + activePosNotSynced = false, captureTimer, - activePosNotSynched = false, jumpInProgress, - command_JumpBack, - command_JumpFwd, - cmMarkers = {}; + commandJumpBack, + commandJumpFwd; /** * Function to enable/disable navigation command based on cursor positions availability. * @private */ function _validateNavigationCmds() { - if (jumpToPosStack.length > 0) { - command_JumpBack.setEnabled(true); - } else { - command_JumpBack.setEnabled(false); - } - - if (jumpedPosStack.length > 0) { - command_JumpFwd.setEnabled(true); - } else { - command_JumpFwd.setEnabled(false); - } + commandJumpBack.setEnabled(jumpToPosStack.length > 0); + commandJumpFwd.setEnabled(jumpedPosStack.length > 0); } /** @@ -98,9 +88,9 @@ define(function (require, exports, module) { fileEntry = FileSystem.getFileForPath(entry.file); if (entry.inMem) { - var indxInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); + var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); // Remove entry if InMemoryFile is not found in Working set - if (indxInWS === -1) { + if (indexInWS === -1) { deferred.reject(); } else { deferred.resolve(); @@ -112,7 +102,7 @@ define(function (require, exports, module) { } else { deferred.reject(); } - }); + }); } return deferred.promise(); @@ -124,7 +114,7 @@ define(function (require, exports, module) { function NavigationFrame(editor, selectionObj) { this.cm = editor._codeMirror; this.file = editor.document.file._path; - this.inMem = editor.document.file.constructor.name === "InMemoryFile" ? true : false; + this.inMem = editor.document.file.constructor.name === "InMemoryFile"; this.paneId = editor._paneId; this.uId = (new Date()).getTime(); this.selections = []; @@ -134,7 +124,7 @@ define(function (require, exports, module) { } /** - * Binds the lifecycle event listner of the editor for which this frame is captured + * Binds the lifecycle event listener of the editor for which this frame is captured */ NavigationFrame.prototype._bindEditor = function (editor) { var self = this; @@ -154,7 +144,10 @@ define(function (require, exports, module) { * -> Addition/Updation of characters in the captured selection */ NavigationFrame.prototype._createMarkers = function (ranges) { - var range, index, bookMark; + var range, + index, + bookMark; + this.bookMarkIds = []; for (index in ranges) { range = ranges[index]; @@ -177,15 +170,23 @@ define(function (require, exports, module) { if (!this.cm) { return; } + + var marker, + selection, + index; + // Reset selections first. this.selections = []; - var marker, selection, index; var self = this; + + // Collate only the markers we used to mark selections/cursors var markers = this.cm.getAllMarks().filter(function (entry) { if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { return entry; } }); + + // Iterate over CM textmarkers and collate the updated(if?) positions for (index in markers) { marker = markers[index]; selection = marker.find(); @@ -238,10 +239,10 @@ define(function (require, exports, module) { captureTimer = window.setTimeout(function () { jumpToPosStack.push(new NavigationFrame(event.target, selectionObj)); _validateNavigationCmds(); - activePosNotSynched = false; + activePosNotSynced = false; }, NAV_FRAME_CAPTURE_LATENCY); } else { - activePosNotSynched = true; + activePosNotSynced = true; } } @@ -250,7 +251,7 @@ define(function (require, exports, module) { */ function _navigateBack() { if (!jumpedPosStack.length) { - if (activePosNotSynched) { + if (activePosNotSynced) { jumpToPosStack.push(new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()})); } } @@ -303,10 +304,10 @@ define(function (require, exports, module) { function _initNavigationCommands() { CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack); CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateFwd); - command_JumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); - command_JumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); - command_JumpBack.setEnabled(false); - command_JumpFwd.setEnabled(false); + commandJumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); + commandJumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); + commandJumpBack.setEnabled(false); + commandJumpFwd.setEnabled(false); KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); _initNavigationMenuItems(); @@ -318,7 +319,7 @@ define(function (require, exports, module) { */ function _captureFrame(editor) { // Capture the active position now if it was not captured earlier - if ((activePosNotSynched || !jumpToPosStack.length) && !jumpInProgress) { + if ((activePosNotSynced || !jumpToPosStack.length) && !jumpInProgress) { jumpToPosStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); } } @@ -335,7 +336,7 @@ define(function (require, exports, module) { } if (current && current._paneId) { // Handle only full editors - activePosNotSynched = true; + activePosNotSynced = true; current.on("beforeSelectionChange", _recordJumpDef); } } From e60dc6a09834fb95d781fc76fee7810849c3649e Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Mon, 19 Jun 2017 09:34:40 +0530 Subject: [PATCH 06/15] Put a max navigation frame capture limit and control overflow once reached. Fix all bugs found in unit testing. --- .../NavigationProvider.js | 89 +++++++++++++++++-- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 129624b6bc4..5042e6b5470 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -49,7 +49,8 @@ define(function (require, exports, module) { NAVIGATION_JUMP_FWD = "navigation.jump.fwd"; // The latency time to capture an explicit cursor movement as a navigation frame - var NAV_FRAME_CAPTURE_LATENCY = 2000; + var NAV_FRAME_CAPTURE_LATENCY = 2000, + MAX_NAV_FRAMES_COUNT = 50; /* * Contains list of most recently known cursor positions. @@ -66,16 +67,26 @@ define(function (require, exports, module) { var jumpedPosStack = [], activePosNotSynced = false, captureTimer, + currentEditPos, jumpInProgress, commandJumpBack, commandJumpFwd; + + /** + * Function to check if there are any navigatable frame backward. + * @private + */ + function _hasNavBackFrames() { + return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) + || (!jumpedPosStack.length && jumpToPosStack.length > 1); + } /** * Function to enable/disable navigation command based on cursor positions availability. * @private */ function _validateNavigationCmds() { - commandJumpBack.setEnabled(jumpToPosStack.length > 0); + commandJumpBack.setEnabled(_hasNavBackFrames()); commandJumpFwd.setEnabled(jumpedPosStack.length > 0); } @@ -129,9 +140,20 @@ define(function (require, exports, module) { NavigationFrame.prototype._bindEditor = function (editor) { var self = this; editor.on("beforeDestroy", function () { + var updateCurrentPos; + + // Check if this frame is actually the current frame + // if true then we will update the current frame with serialized positions from CM + if (self === currentEditPos) { + updateCurrentPos = true; + } self._backupSelectionRanges(); self.cm = null; self.bookMarkIds = null; + + if (updateCurrentPos) { + currentEditPos = self; + } }); }; @@ -197,6 +219,23 @@ define(function (require, exports, module) { } } }; + + /** + * Function to clean up the markers in cm + */ + NavigationFrame.prototype._clearMarkers = function () { + if (!this.cm) { + return; + } + var self = this; + + // clear only the markers we used to mark selections/cursors + this.cm.getAllMarks().filter(function (entry) { + if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { + entry.clear(); + } + }); + }; /** * Function to actually navigate to the position(file,selections) captured in this frame @@ -234,10 +273,19 @@ define(function (require, exports, module) { window.clearTimeout(captureTimer); captureTimer = null; } + // Ensure cursor activity has not happened because of arrow keys or edit - if (selectionObj.origin !== "+move" && (window.event && window.event.type !== "input")) { + if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { captureTimer = window.setTimeout(function () { - jumpToPosStack.push(new NavigationFrame(event.target, selectionObj)); + // Check if we have reached MAX_NAV_FRAMES_COUNT + // If yes, control overflow + if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { + var navFrame = jumpToPosStack.splice(0, 1); + navFrame._clearMarkers(); + } + + currentEditPos = new NavigationFrame(event.target, selectionObj); + jumpToPosStack.push(currentEditPos); _validateNavigationCmds(); activePosNotSynced = false; }, NAV_FRAME_CAPTURE_LATENCY); @@ -252,20 +300,33 @@ define(function (require, exports, module) { function _navigateBack() { if (!jumpedPosStack.length) { if (activePosNotSynced) { - jumpToPosStack.push(new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()})); + currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); + jumpedPosStack.push(currentEditPos); } } + var navFrame = jumpToPosStack.pop(); + + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpedPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_BACK); + return; + } + if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again // but discard the popped frame as invalid. _checkIfExist(navFrame).done(function () { jumpedPosStack.push(navFrame); navFrame.goTo(); + currentEditPos = navFrame; }).fail(function () { - _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_BACK); - }); + }).always(function () { + _validateNavigationCmds(); + }); } } @@ -274,16 +335,28 @@ define(function (require, exports, module) { */ function _navigateFwd() { var navFrame = jumpedPosStack.pop(); + + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpToPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_FWD); + return; + } + if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again // but discard the popped frame as invalid. _checkIfExist(navFrame).done(function () { jumpToPosStack.push(navFrame); navFrame.goTo(); + currentEditPos = navFrame; }).fail(function () { _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_FWD); - }); + }).always(function () { + _validateNavigationCmds(); + }); } } From 05e8b992fc0680cf8461714dd7605d59640922fd Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Mon, 19 Jun 2017 09:47:16 +0530 Subject: [PATCH 07/15] Fix indentation issues --- .../NavigationProvider.js | 123 +++++++++--------- 1 file changed, 61 insertions(+), 62 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 5042e6b5470..1f9aef04884 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -50,7 +50,7 @@ define(function (require, exports, module) { // The latency time to capture an explicit cursor movement as a navigation frame var NAV_FRAME_CAPTURE_LATENCY = 2000, - MAX_NAV_FRAMES_COUNT = 50; + MAX_NAV_FRAMES_COUNT = 50; /* * Contains list of most recently known cursor positions. @@ -67,7 +67,7 @@ define(function (require, exports, module) { var jumpedPosStack = [], activePosNotSynced = false, captureTimer, - currentEditPos, + currentEditPos, jumpInProgress, commandJumpBack, commandJumpFwd; @@ -76,10 +76,10 @@ define(function (require, exports, module) { * Function to check if there are any navigatable frame backward. * @private */ - function _hasNavBackFrames() { - return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) - || (!jumpedPosStack.length && jumpToPosStack.length > 1); - } + function _hasNavBackFrames() { + return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) + || (!jumpedPosStack.length && jumpToPosStack.length > 1); + } /** * Function to enable/disable navigation command based on cursor positions availability. @@ -113,8 +113,8 @@ define(function (require, exports, module) { } else { deferred.reject(); } - }); - } + }); + } return deferred.promise(); } @@ -140,20 +140,19 @@ define(function (require, exports, module) { NavigationFrame.prototype._bindEditor = function (editor) { var self = this; editor.on("beforeDestroy", function () { - var updateCurrentPos; - - // Check if this frame is actually the current frame - // if true then we will update the current frame with serialized positions from CM - if (self === currentEditPos) { - updateCurrentPos = true; - } - self._backupSelectionRanges(); - self.cm = null; - self.bookMarkIds = null; - - if (updateCurrentPos) { - currentEditPos = self; - } + var updateCurrentPos; + + // Check if this frame is actually the current frame + // if true then we will update the current frame with serialized positions from CM + if (self === currentEditPos) { + updateCurrentPos = true; + } + self._backupSelectionRanges(); + self.cm = null; + self.bookMarkIds = null; + if (updateCurrentPos) { + currentEditPos = self; + } }); }; @@ -167,8 +166,8 @@ define(function (require, exports, module) { */ NavigationFrame.prototype._createMarkers = function (ranges) { var range, - index, - bookMark; + index, + bookMark; this.bookMarkIds = []; for (index in ranges) { @@ -193,22 +192,22 @@ define(function (require, exports, module) { return; } - var marker, - selection, - index; + var marker, + selection, + index; - // Reset selections first. + // Reset selections first. this.selections = []; var self = this; - // Collate only the markers we used to mark selections/cursors + // Collate only the markers we used to mark selections/cursors var markers = this.cm.getAllMarks().filter(function (entry) { if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { return entry; } }); - // Iterate over CM textmarkers and collate the updated(if?) positions + // Iterate over CM textmarkers and collate the updated(if?) positions for (index in markers) { marker = markers[index]; selection = marker.find(); @@ -220,7 +219,7 @@ define(function (require, exports, module) { } }; - /** + /** * Function to clean up the markers in cm */ NavigationFrame.prototype._clearMarkers = function () { @@ -229,7 +228,7 @@ define(function (require, exports, module) { } var self = this; - // clear only the markers we used to mark selections/cursors + // clear only the markers we used to mark selections/cursors this.cm.getAllMarks().filter(function (entry) { if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { entry.clear(); @@ -277,15 +276,15 @@ define(function (require, exports, module) { // Ensure cursor activity has not happened because of arrow keys or edit if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { captureTimer = window.setTimeout(function () { - // Check if we have reached MAX_NAV_FRAMES_COUNT - // If yes, control overflow - if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { - var navFrame = jumpToPosStack.splice(0, 1); - navFrame._clearMarkers(); - } - - currentEditPos = new NavigationFrame(event.target, selectionObj); - jumpToPosStack.push(currentEditPos); + // Check if we have reached MAX_NAV_FRAMES_COUNT + // If yes, control overflow + if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { + var navFrame = jumpToPosStack.splice(0, 1); + navFrame._clearMarkers(); + } + + currentEditPos = new NavigationFrame(event.target, selectionObj); + jumpToPosStack.push(currentEditPos); _validateNavigationCmds(); activePosNotSynced = false; }, NAV_FRAME_CAPTURE_LATENCY); @@ -300,20 +299,20 @@ define(function (require, exports, module) { function _navigateBack() { if (!jumpedPosStack.length) { if (activePosNotSynced) { - currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); + currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); jumpedPosStack.push(currentEditPos); } } var navFrame = jumpToPosStack.pop(); - // Check if the poped frame is the current active frame - // if true, jump again - if (navFrame === currentEditPos) { - jumpedPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_BACK); - return; - } + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpedPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_BACK); + return; + } if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again @@ -321,12 +320,12 @@ define(function (require, exports, module) { _checkIfExist(navFrame).done(function () { jumpedPosStack.push(navFrame); navFrame.goTo(); - currentEditPos = navFrame; + currentEditPos = navFrame; }).fail(function () { CommandManager.execute(NAVIGATION_JUMP_BACK); }).always(function () { - _validateNavigationCmds(); - }); + _validateNavigationCmds(); + }); } } @@ -336,13 +335,13 @@ define(function (require, exports, module) { function _navigateFwd() { var navFrame = jumpedPosStack.pop(); - // Check if the poped frame is the current active frame - // if true, jump again - if (navFrame === currentEditPos) { - jumpToPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_FWD); - return; - } + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpToPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_FWD); + return; + } if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again @@ -350,13 +349,13 @@ define(function (require, exports, module) { _checkIfExist(navFrame).done(function () { jumpToPosStack.push(navFrame); navFrame.goTo(); - currentEditPos = navFrame; + currentEditPos = navFrame; }).fail(function () { _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_FWD); }).always(function () { - _validateNavigationCmds(); - }); + _validateNavigationCmds(); + }); } } From 97ee96927cd6df9fd796367f859203f4feed77fc Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Mon, 19 Jun 2017 09:56:38 +0530 Subject: [PATCH 08/15] Change spaces to tabs for indentation --- .../NavigationProvider.js | 146 +++++++++--------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 1f9aef04884..0d357c1e17b 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -50,16 +50,16 @@ define(function (require, exports, module) { // The latency time to capture an explicit cursor movement as a navigation frame var NAV_FRAME_CAPTURE_LATENCY = 2000, - MAX_NAV_FRAMES_COUNT = 50; + MAX_NAV_FRAMES_COUNT = 50; - /* + /** * Contains list of most recently known cursor positions. * @private * @type {Array.} */ var jumpToPosStack = []; - /* + /** * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command. * @private * @type {Array.} @@ -67,18 +67,18 @@ define(function (require, exports, module) { var jumpedPosStack = [], activePosNotSynced = false, captureTimer, - currentEditPos, + currentEditPos, jumpInProgress, commandJumpBack, commandJumpFwd; - /** + /** * Function to check if there are any navigatable frame backward. * @private */ function _hasNavBackFrames() { - return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) - || (!jumpedPosStack.length && jumpToPosStack.length > 1); + return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) + || (!jumpedPosStack.length && jumpToPosStack.length > 1); } /** @@ -90,7 +90,7 @@ define(function (require, exports, module) { commandJumpFwd.setEnabled(jumpedPosStack.length > 0); } - /** + /** * Function to check existence of a file entry * @private */ @@ -113,8 +113,8 @@ define(function (require, exports, module) { } else { deferred.reject(); } - }); - } + }); + } return deferred.promise(); } @@ -140,19 +140,19 @@ define(function (require, exports, module) { NavigationFrame.prototype._bindEditor = function (editor) { var self = this; editor.on("beforeDestroy", function () { - var updateCurrentPos; + var updateCurrentPos; - // Check if this frame is actually the current frame - // if true then we will update the current frame with serialized positions from CM - if (self === currentEditPos) { - updateCurrentPos = true; - } - self._backupSelectionRanges(); - self.cm = null; - self.bookMarkIds = null; - if (updateCurrentPos) { - currentEditPos = self; - } + // Check if this frame is actually the current frame + // if true then we will update the current frame with serialized positions from CM + if (self === currentEditPos) { + updateCurrentPos = true; + } + self._backupSelectionRanges(); + self.cm = null; + self.bookMarkIds = null; + if (updateCurrentPos) { + currentEditPos = self; + } }); }; @@ -166,8 +166,8 @@ define(function (require, exports, module) { */ NavigationFrame.prototype._createMarkers = function (ranges) { var range, - index, - bookMark; + index, + bookMark; this.bookMarkIds = []; for (index in ranges) { @@ -192,22 +192,22 @@ define(function (require, exports, module) { return; } - var marker, - selection, - index; + var marker, + selection, + index; - // Reset selections first. - this.selections = []; - var self = this; - - // Collate only the markers we used to mark selections/cursors - var markers = this.cm.getAllMarks().filter(function (entry) { - if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { - return entry; - } - }); - - // Iterate over CM textmarkers and collate the updated(if?) positions + // Reset selections first. + this.selections = []; + var self = this; + + // Collate only the markers we used to mark selections/cursors + var markers = this.cm.getAllMarks().filter(function (entry) { + if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { + return entry; + } + }); + + // Iterate over CM textmarkers and collate the updated(if?) positions for (index in markers) { marker = markers[index]; selection = marker.find(); @@ -219,7 +219,7 @@ define(function (require, exports, module) { } }; - /** + /** * Function to clean up the markers in cm */ NavigationFrame.prototype._clearMarkers = function () { @@ -228,7 +228,7 @@ define(function (require, exports, module) { } var self = this; - // clear only the markers we used to mark selections/cursors + // clear only the markers we used to mark selections/cursors this.cm.getAllMarks().filter(function (entry) { if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { entry.clear(); @@ -276,17 +276,17 @@ define(function (require, exports, module) { // Ensure cursor activity has not happened because of arrow keys or edit if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { captureTimer = window.setTimeout(function () { - // Check if we have reached MAX_NAV_FRAMES_COUNT - // If yes, control overflow - if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { - var navFrame = jumpToPosStack.splice(0, 1); - navFrame._clearMarkers(); - } + // Check if we have reached MAX_NAV_FRAMES_COUNT + // If yes, control overflow + if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { + var navFrame = jumpToPosStack.splice(0, 1); + navFrame._clearMarkers(); + } - currentEditPos = new NavigationFrame(event.target, selectionObj); - jumpToPosStack.push(currentEditPos); - _validateNavigationCmds(); - activePosNotSynced = false; + currentEditPos = new NavigationFrame(event.target, selectionObj); + jumpToPosStack.push(currentEditPos); + _validateNavigationCmds(); + activePosNotSynced = false; }, NAV_FRAME_CAPTURE_LATENCY); } else { activePosNotSynced = true; @@ -299,20 +299,20 @@ define(function (require, exports, module) { function _navigateBack() { if (!jumpedPosStack.length) { if (activePosNotSynced) { - currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); + currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); jumpedPosStack.push(currentEditPos); } } var navFrame = jumpToPosStack.pop(); - // Check if the poped frame is the current active frame - // if true, jump again - if (navFrame === currentEditPos) { - jumpedPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_BACK); - return; - } + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpedPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_BACK); + return; + } if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again @@ -320,12 +320,12 @@ define(function (require, exports, module) { _checkIfExist(navFrame).done(function () { jumpedPosStack.push(navFrame); navFrame.goTo(); - currentEditPos = navFrame; + currentEditPos = navFrame; }).fail(function () { CommandManager.execute(NAVIGATION_JUMP_BACK); }).always(function () { - _validateNavigationCmds(); - }); + _validateNavigationCmds(); + }); } } @@ -335,13 +335,13 @@ define(function (require, exports, module) { function _navigateFwd() { var navFrame = jumpedPosStack.pop(); - // Check if the poped frame is the current active frame - // if true, jump again - if (navFrame === currentEditPos) { - jumpToPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_FWD); - return; - } + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpToPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_FWD); + return; + } if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again @@ -349,17 +349,17 @@ define(function (require, exports, module) { _checkIfExist(navFrame).done(function () { jumpToPosStack.push(navFrame); navFrame.goTo(); - currentEditPos = navFrame; + currentEditPos = navFrame; }).fail(function () { _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_FWD); }).always(function () { - _validateNavigationCmds(); - }); + _validateNavigationCmds(); + }); } } - /** + /** * Function to initialize navigation menu items. * @private */ From 07541cfcbbce21c36b26e89a37e29242526d4f9a Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Mon, 19 Jun 2017 16:45:31 +0530 Subject: [PATCH 09/15] Fix mixed tabs and spaces --- .../NavigationAndHistory/NavigationProvider.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 0d357c1e17b..c74458a1da6 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -113,7 +113,7 @@ define(function (require, exports, module) { } else { deferred.reject(); } - }); + }); } return deferred.promise(); @@ -158,7 +158,7 @@ define(function (require, exports, module) { /** * Function to create CM TextMarkers for the navigated positions/selections. - * This logic is required to ensure that the captured navaigation positions + * This logic is required to ensure that the captured navigation positions * stay valid and contextual even when the actual document text mutates. * The mutations which are handled here : * -> Addition/Deletion of lines before the captured position @@ -166,8 +166,8 @@ define(function (require, exports, module) { */ NavigationFrame.prototype._createMarkers = function (ranges) { var range, - index, - bookMark; + index, + bookMark; this.bookMarkIds = []; for (index in ranges) { @@ -325,14 +325,14 @@ define(function (require, exports, module) { CommandManager.execute(NAVIGATION_JUMP_BACK); }).always(function () { _validateNavigationCmds(); - }); + }); } } /** * Command handler to navigate forward */ - function _navigateFwd() { + function _navigateForward() { var navFrame = jumpedPosStack.pop(); // Check if the poped frame is the current active frame @@ -375,7 +375,7 @@ define(function (require, exports, module) { */ function _initNavigationCommands() { CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack); - CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateFwd); + CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateForward); commandJumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); commandJumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); commandJumpBack.setEnabled(false); From 3b3b544ae423502e00b90cfe3663c813a98d574f Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Wed, 21 Jun 2017 14:04:05 +0530 Subject: [PATCH 10/15] Convert spaces to tab --- .../NavigationProvider.js | 598 +++++++++--------- 1 file changed, 299 insertions(+), 299 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index c74458a1da6..3787122fe13 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -27,119 +27,119 @@ * persisted to file system when a project is being closed. */ define(function (require, exports, module) { - "use strict"; + "use strict"; - var Strings = brackets.getModule("strings"), - MainViewManager = brackets.getModule("view/MainViewManager"), - DocumentManager = brackets.getModule("document/DocumentManager"), - DocumentCommandHandlers = brackets.getModule("document/DocumentCommandHandlers"), - EditorManager = brackets.getModule("editor/EditorManager"), - Editor = brackets.getModule("editor/Editor"), - ProjectManager = brackets.getModule("project/ProjectManager"), - CommandManager = brackets.getModule("command/CommandManager"), - Commands = brackets.getModule("command/Commands"), - Menus = brackets.getModule("command/Menus"), - KeyBindingManager = brackets.getModule("command/KeyBindingManager"), - FileSystem = brackets.getModule("filesystem/FileSystem"); + var Strings = brackets.getModule("strings"), + MainViewManager = brackets.getModule("view/MainViewManager"), + DocumentManager = brackets.getModule("document/DocumentManager"), + DocumentCommandHandlers = brackets.getModule("document/DocumentCommandHandlers"), + EditorManager = brackets.getModule("editor/EditorManager"), + Editor = brackets.getModule("editor/Editor"), + ProjectManager = brackets.getModule("project/ProjectManager"), + CommandManager = brackets.getModule("command/CommandManager"), + Commands = brackets.getModule("command/Commands"), + Menus = brackets.getModule("command/Menus"), + KeyBindingManager = brackets.getModule("command/KeyBindingManager"), + FileSystem = brackets.getModule("filesystem/FileSystem"); - var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); - - // Command constants for navigation history - var NAVIGATION_JUMP_BACK = "navigation.jump.back", - NAVIGATION_JUMP_FWD = "navigation.jump.fwd"; - - // The latency time to capture an explicit cursor movement as a navigation frame - var NAV_FRAME_CAPTURE_LATENCY = 2000, + var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); + + // Command constants for navigation history + var NAVIGATION_JUMP_BACK = "navigation.jump.back", + NAVIGATION_JUMP_FWD = "navigation.jump.fwd"; + + // The latency time to capture an explicit cursor movement as a navigation frame + var NAV_FRAME_CAPTURE_LATENCY = 2000, MAX_NAV_FRAMES_COUNT = 50; - + /** - * Contains list of most recently known cursor positions. - * @private - * @type {Array.} - */ - var jumpToPosStack = []; - + * Contains list of most recently known cursor positions. + * @private + * @type {Array.} + */ + var jumpToPosStack = []; + /** - * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command. - * @private - * @type {Array.} - */ - var jumpedPosStack = [], - activePosNotSynced = false, - captureTimer, + * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command. + * @private + * @type {Array.} + */ + var jumpedPosStack = [], + activePosNotSynced = false, + captureTimer, currentEditPos, - jumpInProgress, - commandJumpBack, - commandJumpFwd; + jumpInProgress, + commandJumpBack, + commandJumpFwd; /** - * Function to check if there are any navigatable frame backward. - * @private - */ - function _hasNavBackFrames() { + * Function to check if there are any navigatable frame backward. + * @private + */ + function _hasNavBackFrames() { return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) || (!jumpedPosStack.length && jumpToPosStack.length > 1); - } - + } + /** - * Function to enable/disable navigation command based on cursor positions availability. - * @private - */ - function _validateNavigationCmds() { - commandJumpBack.setEnabled(_hasNavBackFrames()); - commandJumpFwd.setEnabled(jumpedPosStack.length > 0); - } - + * Function to enable/disable navigation command based on cursor positions availability. + * @private + */ + function _validateNavigationCmds() { + commandJumpBack.setEnabled(_hasNavBackFrames()); + commandJumpFwd.setEnabled(jumpedPosStack.length > 0); + } + /** - * Function to check existence of a file entry - * @private - */ - function _checkIfExist(entry) { - var deferred = new $.Deferred(), - fileEntry = FileSystem.getFileForPath(entry.file); + * Function to check existence of a file entry + * @private + */ + function _checkIfExist(entry) { + var deferred = new $.Deferred(), + fileEntry = FileSystem.getFileForPath(entry.file); - if (entry.inMem) { - var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); - // Remove entry if InMemoryFile is not found in Working set - if (indexInWS === -1) { - deferred.reject(); - } else { - deferred.resolve(); - } - } else { - fileEntry.exists(function (err, exists) { - if (!err && exists) { - deferred.resolve(); - } else { - deferred.reject(); - } + if (entry.inMem) { + var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); + // Remove entry if InMemoryFile is not found in Working set + if (indexInWS === -1) { + deferred.reject(); + } else { + deferred.resolve(); + } + } else { + fileEntry.exists(function (err, exists) { + if (!err && exists) { + deferred.resolve(); + } else { + deferred.reject(); + } }); } - return deferred.promise(); - } - + return deferred.promise(); + } + /** - * Prototype to capture a navigation frame and it's various data/functional attributues - */ - function NavigationFrame(editor, selectionObj) { - this.cm = editor._codeMirror; - this.file = editor.document.file._path; - this.inMem = editor.document.file.constructor.name === "InMemoryFile"; - this.paneId = editor._paneId; - this.uId = (new Date()).getTime(); - this.selections = []; - this.bookMarkIds = []; - this._createMarkers(selectionObj.ranges); - this._bindEditor(editor); - } - + * Prototype to capture a navigation frame and it's various data/functional attributues + */ + function NavigationFrame(editor, selectionObj) { + this.cm = editor._codeMirror; + this.file = editor.document.file._path; + this.inMem = editor.document.file.constructor.name === "InMemoryFile"; + this.paneId = editor._paneId; + this.uId = (new Date()).getTime(); + this.selections = []; + this.bookMarkIds = []; + this._createMarkers(selectionObj.ranges); + this._bindEditor(editor); + } + /** - * Binds the lifecycle event listener of the editor for which this frame is captured - */ - NavigationFrame.prototype._bindEditor = function (editor) { - var self = this; - editor.on("beforeDestroy", function () { + * Binds the lifecycle event listener of the editor for which this frame is captured + */ + NavigationFrame.prototype._bindEditor = function (editor) { + var self = this; + editor.on("beforeDestroy", function () { var updateCurrentPos; // Check if this frame is actually the current frame @@ -153,49 +153,49 @@ define(function (require, exports, module) { if (updateCurrentPos) { currentEditPos = self; } - }); - }; - + }); + }; + /** - * Function to create CM TextMarkers for the navigated positions/selections. - * This logic is required to ensure that the captured navigation positions - * stay valid and contextual even when the actual document text mutates. - * The mutations which are handled here : - * -> Addition/Deletion of lines before the captured position - * -> Addition/Updation of characters in the captured selection - */ - NavigationFrame.prototype._createMarkers = function (ranges) { - var range, + * Function to create CM TextMarkers for the navigated positions/selections. + * This logic is required to ensure that the captured navigation positions + * stay valid and contextual even when the actual document text mutates. + * The mutations which are handled here : + * -> Addition/Deletion of lines before the captured position + * -> Addition/Updation of characters in the captured selection + */ + NavigationFrame.prototype._createMarkers = function (ranges) { + var range, index, bookMark; - this.bookMarkIds = []; - for (index in ranges) { - range = ranges[index]; - // 'markText' has to used for a non-zero length position, if current selection is - // of zero length use bookmark instead. - if (range.anchor.line === range.head.line && range.anchor.ch === range.head.ch) { - bookMark = this.cm.setBookmark(range.anchor, range.head); - this.bookMarkIds.push(bookMark.id); - } else { - this.cm.markText(range.anchor, range.head, {className: (this.uId)}); - } - } - }; - + this.bookMarkIds = []; + for (index in ranges) { + range = ranges[index]; + // 'markText' has to used for a non-zero length position, if current selection is + // of zero length use bookmark instead. + if (range.anchor.line === range.head.line && range.anchor.ch === range.head.ch) { + bookMark = this.cm.setBookmark(range.anchor, range.head); + this.bookMarkIds.push(bookMark.id); + } else { + this.cm.markText(range.anchor, range.head, {className: (this.uId)}); + } + } + }; + /** - * Function to actually convert the CM markers to CM positions which can be used to - * set selections or cursor positions in Editor. - */ - NavigationFrame.prototype._backupSelectionRanges = function () { - if (!this.cm) { - return; - } + * Function to actually convert the CM markers to CM positions which can be used to + * set selections or cursor positions in Editor. + */ + NavigationFrame.prototype._backupSelectionRanges = function () { + if (!this.cm) { + return; + } var marker, selection, index; - + // Reset selections first. this.selections = []; var self = this; @@ -208,74 +208,74 @@ define(function (require, exports, module) { }); // Iterate over CM textmarkers and collate the updated(if?) positions - for (index in markers) { - marker = markers[index]; - selection = marker.find(); - if (marker.type === "bookmark") { - this.selections.push({start: selection, end: selection}); - } else { - this.selections.push({start: selection.from, end: selection.to}); - } - } - }; + for (index in markers) { + marker = markers[index]; + selection = marker.find(); + if (marker.type === "bookmark") { + this.selections.push({start: selection, end: selection}); + } else { + this.selections.push({start: selection.from, end: selection.to}); + } + } + }; /** - * Function to clean up the markers in cm - */ - NavigationFrame.prototype._clearMarkers = function () { - if (!this.cm) { - return; - } - var self = this; + * Function to clean up the markers in cm + */ + NavigationFrame.prototype._clearMarkers = function () { + if (!this.cm) { + return; + } + var self = this; // clear only the markers we used to mark selections/cursors - this.cm.getAllMarks().filter(function (entry) { - if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { - entry.clear(); - } - }); - }; + this.cm.getAllMarks().filter(function (entry) { + if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { + entry.clear(); + } + }); + }; /** - * Function to actually navigate to the position(file,selections) captured in this frame - */ - NavigationFrame.prototype.goTo = function () { - var self = this; - this._backupSelectionRanges(); - jumpInProgress = true; - CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { - EditorManager.getCurrentFullEditor().setSelections(self.selections, true); - _validateNavigationCmds(); - }).always(function () { - jumpInProgress = false; - }); - }; - - + * Function to actually navigate to the position(file,selections) captured in this frame + */ + NavigationFrame.prototype.goTo = function () { + var self = this; + this._backupSelectionRanges(); + jumpInProgress = true; + CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { + EditorManager.getCurrentFullEditor().setSelections(self.selections, true); + _validateNavigationCmds(); + }).always(function () { + jumpInProgress = false; + }); + }; + + /** - * Function to capture a non-zero set of selections as a navigation frame. - * The assumptions behind capturing a frame as a navigation frame are : - * - * -> If it's set by user explicitly (using mouse click or jump to definition) - * -> By clicking on search results - * -> Change of cursor by keyboard navigation keys or actual edits are not captured. - * - * @private - */ - function _recordJumpDef(event, selectionObj) { - if (jumpInProgress) { - return; - } - // Reset forward navigation stack if we are capturing a new event - jumpedPosStack = []; - if (captureTimer) { - window.clearTimeout(captureTimer); - captureTimer = null; - } + * Function to capture a non-zero set of selections as a navigation frame. + * The assumptions behind capturing a frame as a navigation frame are : + * + * -> If it's set by user explicitly (using mouse click or jump to definition) + * -> By clicking on search results + * -> Change of cursor by keyboard navigation keys or actual edits are not captured. + * + * @private + */ + function _recordJumpDef(event, selectionObj) { + if (jumpInProgress) { + return; + } + // Reset forward navigation stack if we are capturing a new event + jumpedPosStack = []; + if (captureTimer) { + window.clearTimeout(captureTimer); + captureTimer = null; + } - // Ensure cursor activity has not happened because of arrow keys or edit - if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { - captureTimer = window.setTimeout(function () { + // Ensure cursor activity has not happened because of arrow keys or edit + if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { + captureTimer = window.setTimeout(function () { // Check if we have reached MAX_NAV_FRAMES_COUNT // If yes, control overflow if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { @@ -287,24 +287,24 @@ define(function (require, exports, module) { jumpToPosStack.push(currentEditPos); _validateNavigationCmds(); activePosNotSynced = false; - }, NAV_FRAME_CAPTURE_LATENCY); - } else { - activePosNotSynced = true; - } - } - + }, NAV_FRAME_CAPTURE_LATENCY); + } else { + activePosNotSynced = true; + } + } + /** - * Command handler to navigate backward - */ - function _navigateBack() { - if (!jumpedPosStack.length) { - if (activePosNotSynced) { + * Command handler to navigate backward + */ + function _navigateBack() { + if (!jumpedPosStack.length) { + if (activePosNotSynced) { currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); - jumpedPosStack.push(currentEditPos); - } - } + jumpedPosStack.push(currentEditPos); + } + } - var navFrame = jumpToPosStack.pop(); + var navFrame = jumpToPosStack.pop(); // Check if the poped frame is the current active frame // if true, jump again @@ -314,26 +314,26 @@ define(function (require, exports, module) { return; } - if (navFrame) { - // We will check for the file existence now, if it doesn't exist we will jump back again - // but discard the popped frame as invalid. - _checkIfExist(navFrame).done(function () { - jumpedPosStack.push(navFrame); - navFrame.goTo(); + if (navFrame) { + // We will check for the file existence now, if it doesn't exist we will jump back again + // but discard the popped frame as invalid. + _checkIfExist(navFrame).done(function () { + jumpedPosStack.push(navFrame); + navFrame.goTo(); currentEditPos = navFrame; - }).fail(function () { - CommandManager.execute(NAVIGATION_JUMP_BACK); - }).always(function () { + }).fail(function () { + CommandManager.execute(NAVIGATION_JUMP_BACK); + }).always(function () { _validateNavigationCmds(); }); - } - } - + } + } + /** - * Command handler to navigate forward - */ - function _navigateForward() { - var navFrame = jumpedPosStack.pop(); + * Command handler to navigate forward + */ + function _navigateForward() { + var navFrame = jumpedPosStack.pop(); // Check if the poped frame is the current active frame // if true, jump again @@ -343,90 +343,90 @@ define(function (require, exports, module) { return; } - if (navFrame) { - // We will check for the file existence now, if it doesn't exist we will jump back again - // but discard the popped frame as invalid. - _checkIfExist(navFrame).done(function () { - jumpToPosStack.push(navFrame); - navFrame.goTo(); + if (navFrame) { + // We will check for the file existence now, if it doesn't exist we will jump back again + // but discard the popped frame as invalid. + _checkIfExist(navFrame).done(function () { + jumpToPosStack.push(navFrame); + navFrame.goTo(); currentEditPos = navFrame; - }).fail(function () { - _validateNavigationCmds(); - CommandManager.execute(NAVIGATION_JUMP_FWD); - }).always(function () { + }).fail(function () { + _validateNavigationCmds(); + CommandManager.execute(NAVIGATION_JUMP_FWD); + }).always(function () { _validateNavigationCmds(); }); - } - } - + } + } + /** - * Function to initialize navigation menu items. - * @private - */ - function _initNavigationMenuItems() { - var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU); - menu.addMenuItem(NAVIGATION_JUMP_BACK, "", Menus.AFTER, Commands.NAVIGATE_PREV_DOC); - menu.addMenuItem(NAVIGATION_JUMP_FWD, "", Menus.AFTER, NAVIGATION_JUMP_BACK); - } - + * Function to initialize navigation menu items. + * @private + */ + function _initNavigationMenuItems() { + var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU); + menu.addMenuItem(NAVIGATION_JUMP_BACK, "", Menus.AFTER, Commands.NAVIGATE_PREV_DOC); + menu.addMenuItem(NAVIGATION_JUMP_FWD, "", Menus.AFTER, NAVIGATION_JUMP_BACK); + } + /** - * Function to initialize navigation commands and it's keyboard shortcuts. - * @private - */ - function _initNavigationCommands() { - CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack); - CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateForward); - commandJumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); - commandJumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); - commandJumpBack.setEnabled(false); - commandJumpFwd.setEnabled(false); - KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); - KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); - _initNavigationMenuItems(); - } - + * Function to initialize navigation commands and it's keyboard shortcuts. + * @private + */ + function _initNavigationCommands() { + CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack); + CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateForward); + commandJumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); + commandJumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); + commandJumpBack.setEnabled(false); + commandJumpFwd.setEnabled(false); + KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); + KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); + _initNavigationMenuItems(); + } + /** - * Function to request a navigation frame creation explicitly. - * @private - */ - function _captureFrame(editor) { - // Capture the active position now if it was not captured earlier - if ((activePosNotSynced || !jumpToPosStack.length) && !jumpInProgress) { - jumpToPosStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); - } - } - - /** - * Handle Active Editor change to update navigation information - * @private - */ - function _handleActiveEditorChange(event, current, previous) { - if (previous && previous._paneId) { // Handle only full editors - previous.off("beforeSelectionChange", _recordJumpDef); - _captureFrame(previous); - _validateNavigationCmds(); - } - - if (current && current._paneId) { // Handle only full editors - activePosNotSynced = true; - current.on("beforeSelectionChange", _recordJumpDef); - } - } - - function _handleProjectOpen() { - jumpToPosStack = []; - jumpedPosStack = []; - } - - function _initHandlers() { - EditorManager.on("activeEditorChange", _handleActiveEditorChange); - ProjectManager.on("projectOpen", _handleProjectOpen); - } + * Function to request a navigation frame creation explicitly. + * @private + */ + function _captureFrame(editor) { + // Capture the active position now if it was not captured earlier + if ((activePosNotSynced || !jumpToPosStack.length) && !jumpInProgress) { + jumpToPosStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); + } + } + + /** + * Handle Active Editor change to update navigation information + * @private + */ + function _handleActiveEditorChange(event, current, previous) { + if (previous && previous._paneId) { // Handle only full editors + previous.off("beforeSelectionChange", _recordJumpDef); + _captureFrame(previous); + _validateNavigationCmds(); + } + + if (current && current._paneId) { // Handle only full editors + activePosNotSynced = true; + current.on("beforeSelectionChange", _recordJumpDef); + } + } + + function _handleProjectOpen() { + jumpToPosStack = []; + jumpedPosStack = []; + } + + function _initHandlers() { + EditorManager.on("activeEditorChange", _handleActiveEditorChange); + ProjectManager.on("projectOpen", _handleProjectOpen); + } - function init() { - _initNavigationCommands(); - _initHandlers(); - } - - exports.init = init; + function init() { + _initNavigationCommands(); + _initHandlers(); + } + + exports.init = init; }); From b94e6bf48c3a0e851c8e1250c822ea3d92f55bde Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Wed, 21 Jun 2017 14:11:22 +0530 Subject: [PATCH 11/15] resolve mixed tabs and spaces --- .../NavigationProvider.js | 748 +++++++++--------- 1 file changed, 374 insertions(+), 374 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 3787122fe13..5a07d49a3de 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -27,406 +27,406 @@ * persisted to file system when a project is being closed. */ define(function (require, exports, module) { - "use strict"; + "use strict"; - var Strings = brackets.getModule("strings"), - MainViewManager = brackets.getModule("view/MainViewManager"), - DocumentManager = brackets.getModule("document/DocumentManager"), - DocumentCommandHandlers = brackets.getModule("document/DocumentCommandHandlers"), - EditorManager = brackets.getModule("editor/EditorManager"), - Editor = brackets.getModule("editor/Editor"), - ProjectManager = brackets.getModule("project/ProjectManager"), - CommandManager = brackets.getModule("command/CommandManager"), - Commands = brackets.getModule("command/Commands"), - Menus = brackets.getModule("command/Menus"), - KeyBindingManager = brackets.getModule("command/KeyBindingManager"), - FileSystem = brackets.getModule("filesystem/FileSystem"); + var Strings = brackets.getModule("strings"), + MainViewManager = brackets.getModule("view/MainViewManager"), + DocumentManager = brackets.getModule("document/DocumentManager"), + DocumentCommandHandlers = brackets.getModule("document/DocumentCommandHandlers"), + EditorManager = brackets.getModule("editor/EditorManager"), + Editor = brackets.getModule("editor/Editor"), + ProjectManager = brackets.getModule("project/ProjectManager"), + CommandManager = brackets.getModule("command/CommandManager"), + Commands = brackets.getModule("command/Commands"), + Menus = brackets.getModule("command/Menus"), + KeyBindingManager = brackets.getModule("command/KeyBindingManager"), + FileSystem = brackets.getModule("filesystem/FileSystem"); - var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); - - // Command constants for navigation history - var NAVIGATION_JUMP_BACK = "navigation.jump.back", - NAVIGATION_JUMP_FWD = "navigation.jump.fwd"; - - // The latency time to capture an explicit cursor movement as a navigation frame - var NAV_FRAME_CAPTURE_LATENCY = 2000, - MAX_NAV_FRAMES_COUNT = 50; - + var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); + + // Command constants for navigation history + var NAVIGATION_JUMP_BACK = "navigation.jump.back", + NAVIGATION_JUMP_FWD = "navigation.jump.fwd"; + + // The latency time to capture an explicit cursor movement as a navigation frame + var NAV_FRAME_CAPTURE_LATENCY = 2000, + MAX_NAV_FRAMES_COUNT = 50; + /** - * Contains list of most recently known cursor positions. - * @private - * @type {Array.} - */ - var jumpToPosStack = []; - + * Contains list of most recently known cursor positions. + * @private + * @type {Array.} + */ + var jumpToPosStack = []; + /** - * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command. - * @private - * @type {Array.} - */ - var jumpedPosStack = [], - activePosNotSynced = false, - captureTimer, - currentEditPos, - jumpInProgress, - commandJumpBack, - commandJumpFwd; - + * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command. + * @private + * @type {Array.} + */ + var jumpedPosStack = [], + activePosNotSynced = false, + captureTimer, + currentEditPos, + jumpInProgress, + commandJumpBack, + commandJumpFwd; + /** - * Function to check if there are any navigatable frame backward. - * @private - */ - function _hasNavBackFrames() { - return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) - || (!jumpedPosStack.length && jumpToPosStack.length > 1); - } - + * Function to check if there are any navigatable frame backward. + * @private + */ + function _hasNavBackFrames() { + return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) + || (!jumpedPosStack.length && jumpToPosStack.length > 1); + } + /** - * Function to enable/disable navigation command based on cursor positions availability. - * @private - */ - function _validateNavigationCmds() { - commandJumpBack.setEnabled(_hasNavBackFrames()); - commandJumpFwd.setEnabled(jumpedPosStack.length > 0); - } - + * Function to enable/disable navigation command based on cursor positions availability. + * @private + */ + function _validateNavigationCmds() { + commandJumpBack.setEnabled(_hasNavBackFrames()); + commandJumpFwd.setEnabled(jumpedPosStack.length > 0); + } + /** - * Function to check existence of a file entry - * @private - */ - function _checkIfExist(entry) { - var deferred = new $.Deferred(), - fileEntry = FileSystem.getFileForPath(entry.file); + * Function to check existence of a file entry + * @private + */ + function _checkIfExist(entry) { + var deferred = new $.Deferred(), + fileEntry = FileSystem.getFileForPath(entry.file); - if (entry.inMem) { - var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); - // Remove entry if InMemoryFile is not found in Working set - if (indexInWS === -1) { - deferred.reject(); - } else { - deferred.resolve(); - } - } else { - fileEntry.exists(function (err, exists) { - if (!err && exists) { - deferred.resolve(); - } else { - deferred.reject(); - } - }); - } + if (entry.inMem) { + var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); + // Remove entry if InMemoryFile is not found in Working set + if (indexInWS === -1) { + deferred.reject(); + } else { + deferred.resolve(); + } + } else { + fileEntry.exists(function (err, exists) { + if (!err && exists) { + deferred.resolve(); + } else { + deferred.reject(); + } + }); + } - return deferred.promise(); - } - + return deferred.promise(); + } + /** - * Prototype to capture a navigation frame and it's various data/functional attributues - */ - function NavigationFrame(editor, selectionObj) { - this.cm = editor._codeMirror; - this.file = editor.document.file._path; - this.inMem = editor.document.file.constructor.name === "InMemoryFile"; - this.paneId = editor._paneId; - this.uId = (new Date()).getTime(); - this.selections = []; - this.bookMarkIds = []; - this._createMarkers(selectionObj.ranges); - this._bindEditor(editor); - } - + * Prototype to capture a navigation frame and it's various data/functional attributues + */ + function NavigationFrame(editor, selectionObj) { + this.cm = editor._codeMirror; + this.file = editor.document.file._path; + this.inMem = editor.document.file.constructor.name === "InMemoryFile"; + this.paneId = editor._paneId; + this.uId = (new Date()).getTime(); + this.selections = []; + this.bookMarkIds = []; + this._createMarkers(selectionObj.ranges); + this._bindEditor(editor); + } + /** - * Binds the lifecycle event listener of the editor for which this frame is captured - */ - NavigationFrame.prototype._bindEditor = function (editor) { - var self = this; - editor.on("beforeDestroy", function () { - var updateCurrentPos; + * Binds the lifecycle event listener of the editor for which this frame is captured + */ + NavigationFrame.prototype._bindEditor = function (editor) { + var self = this; + editor.on("beforeDestroy", function () { + var updateCurrentPos; - // Check if this frame is actually the current frame - // if true then we will update the current frame with serialized positions from CM - if (self === currentEditPos) { - updateCurrentPos = true; - } - self._backupSelectionRanges(); - self.cm = null; - self.bookMarkIds = null; - if (updateCurrentPos) { - currentEditPos = self; - } - }); - }; - + // Check if this frame is actually the current frame + // if true then we will update the current frame with serialized positions from CM + if (self === currentEditPos) { + updateCurrentPos = true; + } + self._backupSelectionRanges(); + self.cm = null; + self.bookMarkIds = null; + if (updateCurrentPos) { + currentEditPos = self; + } + }); + }; + /** - * Function to create CM TextMarkers for the navigated positions/selections. - * This logic is required to ensure that the captured navigation positions - * stay valid and contextual even when the actual document text mutates. - * The mutations which are handled here : - * -> Addition/Deletion of lines before the captured position - * -> Addition/Updation of characters in the captured selection - */ - NavigationFrame.prototype._createMarkers = function (ranges) { - var range, - index, - bookMark; + * Function to create CM TextMarkers for the navigated positions/selections. + * This logic is required to ensure that the captured navigation positions + * stay valid and contextual even when the actual document text mutates. + * The mutations which are handled here : + * -> Addition/Deletion of lines before the captured position + * -> Addition/Updation of characters in the captured selection + */ + NavigationFrame.prototype._createMarkers = function (ranges) { + var range, + index, + bookMark; - this.bookMarkIds = []; - for (index in ranges) { - range = ranges[index]; - // 'markText' has to used for a non-zero length position, if current selection is - // of zero length use bookmark instead. - if (range.anchor.line === range.head.line && range.anchor.ch === range.head.ch) { - bookMark = this.cm.setBookmark(range.anchor, range.head); - this.bookMarkIds.push(bookMark.id); - } else { - this.cm.markText(range.anchor, range.head, {className: (this.uId)}); - } - } - }; - + this.bookMarkIds = []; + for (index in ranges) { + range = ranges[index]; + // 'markText' has to used for a non-zero length position, if current selection is + // of zero length use bookmark instead. + if (range.anchor.line === range.head.line && range.anchor.ch === range.head.ch) { + bookMark = this.cm.setBookmark(range.anchor, range.head); + this.bookMarkIds.push(bookMark.id); + } else { + this.cm.markText(range.anchor, range.head, {className: (this.uId)}); + } + } + }; + /** - * Function to actually convert the CM markers to CM positions which can be used to - * set selections or cursor positions in Editor. - */ - NavigationFrame.prototype._backupSelectionRanges = function () { - if (!this.cm) { - return; - } - - var marker, - selection, - index; - - // Reset selections first. - this.selections = []; - var self = this; + * Function to actually convert the CM markers to CM positions which can be used to + * set selections or cursor positions in Editor. + */ + NavigationFrame.prototype._backupSelectionRanges = function () { + if (!this.cm) { + return; + } + + var marker, + selection, + index; + + // Reset selections first. + this.selections = []; + var self = this; - // Collate only the markers we used to mark selections/cursors - var markers = this.cm.getAllMarks().filter(function (entry) { - if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { - return entry; - } - }); + // Collate only the markers we used to mark selections/cursors + var markers = this.cm.getAllMarks().filter(function (entry) { + if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { + return entry; + } + }); - // Iterate over CM textmarkers and collate the updated(if?) positions - for (index in markers) { - marker = markers[index]; - selection = marker.find(); - if (marker.type === "bookmark") { - this.selections.push({start: selection, end: selection}); - } else { - this.selections.push({start: selection.from, end: selection.to}); - } - } - }; - + // Iterate over CM textmarkers and collate the updated(if?) positions + for (index in markers) { + marker = markers[index]; + selection = marker.find(); + if (marker.type === "bookmark") { + this.selections.push({start: selection, end: selection}); + } else { + this.selections.push({start: selection.from, end: selection.to}); + } + } + }; + /** - * Function to clean up the markers in cm - */ - NavigationFrame.prototype._clearMarkers = function () { - if (!this.cm) { - return; - } - var self = this; - - // clear only the markers we used to mark selections/cursors - this.cm.getAllMarks().filter(function (entry) { - if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { - entry.clear(); - } - }); - }; + * Function to clean up the markers in cm + */ + NavigationFrame.prototype._clearMarkers = function () { + if (!this.cm) { + return; + } + var self = this; + + // clear only the markers we used to mark selections/cursors + this.cm.getAllMarks().filter(function (entry) { + if (entry.className === self.uId || self.bookMarkIds.indexOf(entry.id) !== -1) { + entry.clear(); + } + }); + }; /** - * Function to actually navigate to the position(file,selections) captured in this frame - */ - NavigationFrame.prototype.goTo = function () { - var self = this; - this._backupSelectionRanges(); - jumpInProgress = true; - CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { - EditorManager.getCurrentFullEditor().setSelections(self.selections, true); - _validateNavigationCmds(); - }).always(function () { - jumpInProgress = false; - }); - }; - - + * Function to actually navigate to the position(file,selections) captured in this frame + */ + NavigationFrame.prototype.goTo = function () { + var self = this; + this._backupSelectionRanges(); + jumpInProgress = true; + CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { + EditorManager.getCurrentFullEditor().setSelections(self.selections, true); + _validateNavigationCmds(); + }).always(function () { + jumpInProgress = false; + }); + }; + + /** - * Function to capture a non-zero set of selections as a navigation frame. - * The assumptions behind capturing a frame as a navigation frame are : - * - * -> If it's set by user explicitly (using mouse click or jump to definition) - * -> By clicking on search results - * -> Change of cursor by keyboard navigation keys or actual edits are not captured. - * - * @private - */ - function _recordJumpDef(event, selectionObj) { - if (jumpInProgress) { - return; - } - // Reset forward navigation stack if we are capturing a new event - jumpedPosStack = []; - if (captureTimer) { - window.clearTimeout(captureTimer); - captureTimer = null; - } - - // Ensure cursor activity has not happened because of arrow keys or edit - if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { - captureTimer = window.setTimeout(function () { - // Check if we have reached MAX_NAV_FRAMES_COUNT - // If yes, control overflow - if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { - var navFrame = jumpToPosStack.splice(0, 1); - navFrame._clearMarkers(); - } + * Function to capture a non-zero set of selections as a navigation frame. + * The assumptions behind capturing a frame as a navigation frame are : + * + * -> If it's set by user explicitly (using mouse click or jump to definition) + * -> By clicking on search results + * -> Change of cursor by keyboard navigation keys or actual edits are not captured. + * + * @private + */ + function _recordJumpDef(event, selectionObj) { + if (jumpInProgress) { + return; + } + // Reset forward navigation stack if we are capturing a new event + jumpedPosStack = []; + if (captureTimer) { + window.clearTimeout(captureTimer); + captureTimer = null; + } + + // Ensure cursor activity has not happened because of arrow keys or edit + if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { + captureTimer = window.setTimeout(function () { + // Check if we have reached MAX_NAV_FRAMES_COUNT + // If yes, control overflow + if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { + var navFrame = jumpToPosStack.splice(0, 1); + navFrame._clearMarkers(); + } - currentEditPos = new NavigationFrame(event.target, selectionObj); - jumpToPosStack.push(currentEditPos); - _validateNavigationCmds(); - activePosNotSynced = false; - }, NAV_FRAME_CAPTURE_LATENCY); - } else { - activePosNotSynced = true; - } - } - + currentEditPos = new NavigationFrame(event.target, selectionObj); + jumpToPosStack.push(currentEditPos); + _validateNavigationCmds(); + activePosNotSynced = false; + }, NAV_FRAME_CAPTURE_LATENCY); + } else { + activePosNotSynced = true; + } + } + /** - * Command handler to navigate backward - */ - function _navigateBack() { - if (!jumpedPosStack.length) { - if (activePosNotSynced) { - currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); - jumpedPosStack.push(currentEditPos); - } - } - - var navFrame = jumpToPosStack.pop(); - - // Check if the poped frame is the current active frame - // if true, jump again - if (navFrame === currentEditPos) { - jumpedPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_BACK); - return; - } - - if (navFrame) { - // We will check for the file existence now, if it doesn't exist we will jump back again - // but discard the popped frame as invalid. - _checkIfExist(navFrame).done(function () { - jumpedPosStack.push(navFrame); - navFrame.goTo(); - currentEditPos = navFrame; - }).fail(function () { - CommandManager.execute(NAVIGATION_JUMP_BACK); - }).always(function () { - _validateNavigationCmds(); - }); - } - } - + * Command handler to navigate backward + */ + function _navigateBack() { + if (!jumpedPosStack.length) { + if (activePosNotSynced) { + currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); + jumpedPosStack.push(currentEditPos); + } + } + + var navFrame = jumpToPosStack.pop(); + + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpedPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_BACK); + return; + } + + if (navFrame) { + // We will check for the file existence now, if it doesn't exist we will jump back again + // but discard the popped frame as invalid. + _checkIfExist(navFrame).done(function () { + jumpedPosStack.push(navFrame); + navFrame.goTo(); + currentEditPos = navFrame; + }).fail(function () { + CommandManager.execute(NAVIGATION_JUMP_BACK); + }).always(function () { + _validateNavigationCmds(); + }); + } + } + /** - * Command handler to navigate forward - */ - function _navigateForward() { - var navFrame = jumpedPosStack.pop(); - - // Check if the poped frame is the current active frame - // if true, jump again - if (navFrame === currentEditPos) { - jumpToPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_FWD); - return; - } - - if (navFrame) { - // We will check for the file existence now, if it doesn't exist we will jump back again - // but discard the popped frame as invalid. - _checkIfExist(navFrame).done(function () { - jumpToPosStack.push(navFrame); - navFrame.goTo(); - currentEditPos = navFrame; - }).fail(function () { - _validateNavigationCmds(); - CommandManager.execute(NAVIGATION_JUMP_FWD); - }).always(function () { - _validateNavigationCmds(); - }); - } - } - + * Command handler to navigate forward + */ + function _navigateForward() { + var navFrame = jumpedPosStack.pop(); + + // Check if the poped frame is the current active frame + // if true, jump again + if (navFrame === currentEditPos) { + jumpToPosStack.push(navFrame); + CommandManager.execute(NAVIGATION_JUMP_FWD); + return; + } + + if (navFrame) { + // We will check for the file existence now, if it doesn't exist we will jump back again + // but discard the popped frame as invalid. + _checkIfExist(navFrame).done(function () { + jumpToPosStack.push(navFrame); + navFrame.goTo(); + currentEditPos = navFrame; + }).fail(function () { + _validateNavigationCmds(); + CommandManager.execute(NAVIGATION_JUMP_FWD); + }).always(function () { + _validateNavigationCmds(); + }); + } + } + /** - * Function to initialize navigation menu items. - * @private - */ - function _initNavigationMenuItems() { - var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU); - menu.addMenuItem(NAVIGATION_JUMP_BACK, "", Menus.AFTER, Commands.NAVIGATE_PREV_DOC); - menu.addMenuItem(NAVIGATION_JUMP_FWD, "", Menus.AFTER, NAVIGATION_JUMP_BACK); - } - + * Function to initialize navigation menu items. + * @private + */ + function _initNavigationMenuItems() { + var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU); + menu.addMenuItem(NAVIGATION_JUMP_BACK, "", Menus.AFTER, Commands.NAVIGATE_PREV_DOC); + menu.addMenuItem(NAVIGATION_JUMP_FWD, "", Menus.AFTER, NAVIGATION_JUMP_BACK); + } + /** - * Function to initialize navigation commands and it's keyboard shortcuts. - * @private - */ - function _initNavigationCommands() { - CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack); - CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateForward); - commandJumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); - commandJumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); - commandJumpBack.setEnabled(false); - commandJumpFwd.setEnabled(false); - KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); - KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); - _initNavigationMenuItems(); - } - + * Function to initialize navigation commands and it's keyboard shortcuts. + * @private + */ + function _initNavigationCommands() { + CommandManager.register(Strings.CMD_NAVIGATE_BACKWARD, NAVIGATION_JUMP_BACK, _navigateBack); + CommandManager.register(Strings.CMD_NAVIGATE_FORWARD, NAVIGATION_JUMP_FWD, _navigateForward); + commandJumpBack = CommandManager.get(NAVIGATION_JUMP_BACK); + commandJumpFwd = CommandManager.get(NAVIGATION_JUMP_FWD); + commandJumpBack.setEnabled(false); + commandJumpFwd.setEnabled(false); + KeyBindingManager.addBinding(NAVIGATION_JUMP_BACK, KeyboardPrefs[NAVIGATION_JUMP_BACK]); + KeyBindingManager.addBinding(NAVIGATION_JUMP_FWD, KeyboardPrefs[NAVIGATION_JUMP_FWD]); + _initNavigationMenuItems(); + } + /** - * Function to request a navigation frame creation explicitly. - * @private - */ - function _captureFrame(editor) { - // Capture the active position now if it was not captured earlier - if ((activePosNotSynced || !jumpToPosStack.length) && !jumpInProgress) { - jumpToPosStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); - } - } - - /** - * Handle Active Editor change to update navigation information - * @private - */ - function _handleActiveEditorChange(event, current, previous) { - if (previous && previous._paneId) { // Handle only full editors - previous.off("beforeSelectionChange", _recordJumpDef); - _captureFrame(previous); - _validateNavigationCmds(); - } - - if (current && current._paneId) { // Handle only full editors - activePosNotSynced = true; - current.on("beforeSelectionChange", _recordJumpDef); - } - } - - function _handleProjectOpen() { - jumpToPosStack = []; - jumpedPosStack = []; - } - - function _initHandlers() { - EditorManager.on("activeEditorChange", _handleActiveEditorChange); - ProjectManager.on("projectOpen", _handleProjectOpen); - } + * Function to request a navigation frame creation explicitly. + * @private + */ + function _captureFrame(editor) { + // Capture the active position now if it was not captured earlier + if ((activePosNotSynced || !jumpToPosStack.length) && !jumpInProgress) { + jumpToPosStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); + } + } + + /** + * Handle Active Editor change to update navigation information + * @private + */ + function _handleActiveEditorChange(event, current, previous) { + if (previous && previous._paneId) { // Handle only full editors + previous.off("beforeSelectionChange", _recordJumpDef); + _captureFrame(previous); + _validateNavigationCmds(); + } + + if (current && current._paneId) { // Handle only full editors + activePosNotSynced = true; + current.on("beforeSelectionChange", _recordJumpDef); + } + } + + function _handleProjectOpen() { + jumpToPosStack = []; + jumpedPosStack = []; + } + + function _initHandlers() { + EditorManager.on("activeEditorChange", _handleActiveEditorChange); + ProjectManager.on("projectOpen", _handleProjectOpen); + } - function init() { - _initNavigationCommands(); - _initHandlers(); - } - - exports.init = init; + function init() { + _initNavigationCommands(); + _initHandlers(); + } + + exports.init = init; }); From ca88b4294096eaa12470acc5f7234d1833f42b05 Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Thu, 22 Jun 2017 10:42:11 +0530 Subject: [PATCH 12/15] Initialize variables --- .../default/NavigationAndHistory/NavigationProvider.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 5a07d49a3de..6b79dafd3a9 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -66,9 +66,9 @@ define(function (require, exports, module) { */ var jumpedPosStack = [], activePosNotSynced = false, - captureTimer, - currentEditPos, - jumpInProgress, + captureTimer = null, + currentEditPos = null, + jumpInProgress = false, commandJumpBack, commandJumpFwd; From 9ed941e4ba3d8ebc08d077cc01d6221caab20a17 Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Fri, 23 Jun 2017 14:03:16 +0530 Subject: [PATCH 13/15] Handle external file changes and discard stale frames --- .../NavigationProvider.js | 181 +++++++++++++++--- 1 file changed, 151 insertions(+), 30 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 6b79dafd3a9..6cf6c168347 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -31,6 +31,7 @@ define(function (require, exports, module) { var Strings = brackets.getModule("strings"), MainViewManager = brackets.getModule("view/MainViewManager"), + Document = brackets.getModule("document/Document"), DocumentManager = brackets.getModule("document/DocumentManager"), DocumentCommandHandlers = brackets.getModule("document/DocumentCommandHandlers"), EditorManager = brackets.getModule("editor/EditorManager"), @@ -41,7 +42,7 @@ define(function (require, exports, module) { Menus = brackets.getModule("command/Menus"), KeyBindingManager = brackets.getModule("command/KeyBindingManager"), FileSystem = brackets.getModule("filesystem/FileSystem"); - + var KeyboardPrefs = JSON.parse(require("text!keyboard.json")); // Command constants for navigation history @@ -50,7 +51,7 @@ define(function (require, exports, module) { // The latency time to capture an explicit cursor movement as a navigation frame var NAV_FRAME_CAPTURE_LATENCY = 2000, - MAX_NAV_FRAMES_COUNT = 50; + MAX_NAV_FRAMES_COUNT = 30; /** * Contains list of most recently known cursor positions. @@ -131,29 +132,46 @@ define(function (require, exports, module) { this.selections = []; this.bookMarkIds = []; this._createMarkers(selectionObj.ranges); - this._bindEditor(editor); } /** - * Binds the lifecycle event listener of the editor for which this frame is captured + * Lifecycle event handler of the editor for which this frame is captured */ - NavigationFrame.prototype._bindEditor = function (editor) { - var self = this; - editor.on("beforeDestroy", function () { - var updateCurrentPos; + NavigationFrame.prototype._handleEditorDestroy = function (editor) { + this._backupSelectionRanges(); + this._clearMarkers(); + this.cm = null; + this.bookMarkIds = null; + }; + + /** + * Function to re-create CM TextMarkers for previously backed up ranges + * This logic is required to ensure that the captured navigation positions + * stay valid and contextual even when the actual document text mutates. + * The mutations which are handled here : + * -> Addition/Deletion of lines before the captured position + * -> Addition/Updation of characters in the captured selection + */ + NavigationFrame.prototype._reinstateMarkers = function (editor) { + this.cm = editor._codeMirror; + this.paneId = editor._paneId; + + var range, + index, + bookMark; - // Check if this frame is actually the current frame - // if true then we will update the current frame with serialized positions from CM - if (self === currentEditPos) { - updateCurrentPos = true; - } - self._backupSelectionRanges(); - self.cm = null; - self.bookMarkIds = null; - if (updateCurrentPos) { - currentEditPos = self; + this.bookMarkIds = []; + for (index in this.selections) { + range = this.selections[index]; + // 'markText' has to used for a non-zero length position, if current selection is + // of zero length use bookmark instead. + if (range.start.line === range.end.line && range.start.ch === range.end.ch) { + bookMark = this.cm.setBookmark(range.start, range.end); + this.bookMarkIds.push(bookMark.id); + } else { + this.cm.markText(range.start, range.end, {className: (this.uId)}); } - }); + } }; /** @@ -235,6 +253,14 @@ define(function (require, exports, module) { } }); }; + + /** + * Function to check if we have valid markers in cm for this frame + */ + NavigationFrame.prototype._validateMarkers = function () { + this._backupSelectionRanges(); + return this.selections.length; + }; /** * Function to actually navigate to the position(file,selections) captured in this frame @@ -243,6 +269,14 @@ define(function (require, exports, module) { var self = this; this._backupSelectionRanges(); jumpInProgress = true; + + // To ensure we don't reopen the same doc in the last known pane + // rather bring it to the same pane where user has opened it + var thisDoc = DocumentManager.getOpenDocumentForPath(this.file); + if (thisDoc && thisDoc._masterEditor) { + this.paneId = thisDoc._masterEditor._paneId; + } + CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { EditorManager.getCurrentFullEditor().setSelections(self.selections, true); _validateNavigationCmds(); @@ -263,7 +297,8 @@ define(function (require, exports, module) { * @private */ function _recordJumpDef(event, selectionObj) { - if (jumpInProgress) { + // Don't capture frames if we are navigating or document text is being refreshed(fileSync in progress) + if (jumpInProgress || (event.target && event.target.document._refreshInProgress)) { return; } // Reset forward navigation stack if we are capturing a new event @@ -279,7 +314,7 @@ define(function (require, exports, module) { // Check if we have reached MAX_NAV_FRAMES_COUNT // If yes, control overflow if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { - var navFrame = jumpToPosStack.splice(0, 1); + var navFrame = jumpToPosStack.splice(0, 1)[0]; navFrame._clearMarkers(); } @@ -306,12 +341,15 @@ define(function (require, exports, module) { var navFrame = jumpToPosStack.pop(); - // Check if the poped frame is the current active frame + // Check if the poped frame is the current active frame or doesn't have any valid marker information // if true, jump again - if (navFrame === currentEditPos) { + if (navFrame && navFrame === currentEditPos) { jumpedPosStack.push(navFrame); CommandManager.execute(NAVIGATION_JUMP_BACK); return; + } else if (navFrame && !navFrame._validateMarkers()) { + CommandManager.execute(NAVIGATION_JUMP_BACK); + return; } if (navFrame) { @@ -335,12 +373,15 @@ define(function (require, exports, module) { function _navigateForward() { var navFrame = jumpedPosStack.pop(); - // Check if the poped frame is the current active frame + // Check if the poped frame is the current active frame or doesn't have any valid marker information // if true, jump again - if (navFrame === currentEditPos) { + if (navFrame && navFrame === currentEditPos) { jumpToPosStack.push(navFrame); CommandManager.execute(NAVIGATION_JUMP_FWD); return; + } else if (navFrame && !navFrame._validateMarkers()) { + CommandManager.execute(NAVIGATION_JUMP_FWD); + return; } if (navFrame) { @@ -396,6 +437,80 @@ define(function (require, exports, module) { } } + /** + * Create snapshot of last known live markers. + * @private + */ + function _backupLiveMarkers(frames, editor) { + var index, frame; + for (index in frames) { + frame = frames[index]; + if (frame.cm === editor._codeMirror) { + frame._handleEditorDestroy(); + } + } + } + + /** + * Handle Editor destruction to create backup of live marker positions + * @private + */ + function _handleEditorCleanup(event, editor) { + _backupLiveMarkers(jumpToPosStack, editor); + _backupLiveMarkers(jumpedPosStack, editor); + } + + /** + * Removes all frames from backward navigation stack for the given file. + * @private + */ + function _removeBackwardFramesForFile(file) { + jumpToPosStack = jumpToPosStack.filter(function (frame) { + return frame.file !== file._path; + }); + } + + /** + * Removes all frames from forward navigation stack for the given file. + * @private + */ + function _removeForwardFramesForFile(file) { + jumpedPosStack = jumpedPosStack.filter(function (frame) { + return frame.file !== file._path; + }); + } + + /** + * Handles explicit content reset for a document caused by external changes + * @private + */ + function _handleExternalChange(evt, doc) { + if (doc) { + _removeBackwardFramesForFile(doc.file); + _removeForwardFramesForFile(doc.file); + _validateNavigationCmds(); + } + } + + function _handleProjectOpen() { + jumpToPosStack = []; + jumpedPosStack = []; + } + + /** + * Required to make offline markers alive again to track document mutation + * @private + */ + function _reinstateMarkers(editor, frames) { + var index, frame; + for (index in frames) { + frame = frames[index]; + if (!frame.cm && frame.file === editor.document.file._path) { + frame._reinstateMarkers(editor); + } + } + } + /** * Handle Active Editor change to update navigation information * @private @@ -409,18 +524,24 @@ define(function (require, exports, module) { if (current && current._paneId) { // Handle only full editors activePosNotSynced = true; + current.off("beforeSelectionChange", _recordJumpDef); current.on("beforeSelectionChange", _recordJumpDef); + current.off("beforeDestroy", _handleEditorCleanup); + current.on("beforeDestroy", _handleEditorCleanup); } } - function _handleProjectOpen() { - jumpToPosStack = []; - jumpedPosStack = []; - } - function _initHandlers() { EditorManager.on("activeEditorChange", _handleActiveEditorChange); ProjectManager.on("projectOpen", _handleProjectOpen); + Document.on("_documentRefreshed", _handleExternalChange); + EditorManager.on("_fullEditorCreatedForDocument", function (event, document, editor) { + _reinstateMarkers(editor, jumpToPosStack); + _reinstateMarkers(editor, jumpedPosStack); + }); + FileSystem.on("change", function (event, entry) { + _handleExternalChange(event, {file: entry}); + }); } function init() { From 167e4dd029335834f86bc93bae4249cc647b4156 Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Tue, 27 Jun 2017 13:16:08 +0530 Subject: [PATCH 14/15] Additional checks to validate the navigation frames --- .../NavigationProvider.js | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index 6cf6c168347..bcf31acc2e9 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -92,10 +92,10 @@ define(function (require, exports, module) { } /** - * Function to check existence of a file entry + * Function to check existence of a file entry, validity of markers * @private */ - function _checkIfExist(entry) { + function _validateFrame(entry) { var deferred = new $.Deferred(), fileEntry = FileSystem.getFileForPath(entry.file); @@ -110,7 +110,14 @@ define(function (require, exports, module) { } else { fileEntry.exists(function (err, exists) { if (!err && exists) { - deferred.resolve(); + // Additional check to handle external modification and mutation of the doc text affecting markers + if (fileEntry._stat !== entry.fileStat) { + deferred.reject(); + } else if (!entry._validateMarkers()) { + deferred.reject(); + } else { + deferred.resolve(); + } } else { deferred.reject(); } @@ -128,6 +135,7 @@ define(function (require, exports, module) { this.file = editor.document.file._path; this.inMem = editor.document.file.constructor.name === "InMemoryFile"; this.paneId = editor._paneId; + this.fileStat = editor.document.file._stat; this.uId = (new Date()).getTime(); this.selections = []; this.bookMarkIds = []; @@ -345,9 +353,7 @@ define(function (require, exports, module) { // if true, jump again if (navFrame && navFrame === currentEditPos) { jumpedPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_BACK); - return; - } else if (navFrame && !navFrame._validateMarkers()) { + _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_BACK); return; } @@ -355,7 +361,7 @@ define(function (require, exports, module) { if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again // but discard the popped frame as invalid. - _checkIfExist(navFrame).done(function () { + _validateFrame(navFrame).done(function () { jumpedPosStack.push(navFrame); navFrame.goTo(); currentEditPos = navFrame; @@ -377,9 +383,7 @@ define(function (require, exports, module) { // if true, jump again if (navFrame && navFrame === currentEditPos) { jumpToPosStack.push(navFrame); - CommandManager.execute(NAVIGATION_JUMP_FWD); - return; - } else if (navFrame && !navFrame._validateMarkers()) { + _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_FWD); return; } @@ -387,7 +391,7 @@ define(function (require, exports, module) { if (navFrame) { // We will check for the file existence now, if it doesn't exist we will jump back again // but discard the popped frame as invalid. - _checkIfExist(navFrame).done(function () { + _validateFrame(navFrame).done(function () { jumpToPosStack.push(navFrame); navFrame.goTo(); currentEditPos = navFrame; @@ -461,22 +465,22 @@ define(function (require, exports, module) { } /** - * Removes all frames from backward navigation stack for the given file. + * Removes all frames from backward navigation stack for the given file only if the file is changed on disk. * @private */ function _removeBackwardFramesForFile(file) { jumpToPosStack = jumpToPosStack.filter(function (frame) { - return frame.file !== file._path; + return frame.file !== file._path && frame.stat !== file._stat; }); } /** - * Removes all frames from forward navigation stack for the given file. + * Removes all frames from forward navigation stack for the given file only if the file is changed on disk. * @private */ function _removeForwardFramesForFile(file) { jumpedPosStack = jumpedPosStack.filter(function (frame) { - return frame.file !== file._path; + return frame.file !== file._path && frame.stat !== file._stat; }); } @@ -534,14 +538,17 @@ define(function (require, exports, module) { function _initHandlers() { EditorManager.on("activeEditorChange", _handleActiveEditorChange); ProjectManager.on("projectOpen", _handleProjectOpen); - Document.on("_documentRefreshed", _handleExternalChange); EditorManager.on("_fullEditorCreatedForDocument", function (event, document, editor) { + _handleExternalChange(event, {file: document.file}); _reinstateMarkers(editor, jumpToPosStack); _reinstateMarkers(editor, jumpedPosStack); }); FileSystem.on("change", function (event, entry) { _handleExternalChange(event, {file: entry}); }); + Document.on("_documentRefreshed", function (event, doc) { + _handleExternalChange(event, {file: doc.file}); + }); } function init() { From 661627943cbccdf9e0c4cbeae607aba752b47f89 Mon Sep 17 00:00:00 2001 From: Swagatam Mitra Date: Tue, 27 Jun 2017 14:13:28 +0530 Subject: [PATCH 15/15] Address review comments --- .../NavigationProvider.js | 131 ++++++++---------- 1 file changed, 61 insertions(+), 70 deletions(-) diff --git a/src/extensions/default/NavigationAndHistory/NavigationProvider.js b/src/extensions/default/NavigationAndHistory/NavigationProvider.js index bcf31acc2e9..59e713c823c 100644 --- a/src/extensions/default/NavigationAndHistory/NavigationProvider.js +++ b/src/extensions/default/NavigationAndHistory/NavigationProvider.js @@ -58,14 +58,14 @@ define(function (require, exports, module) { * @private * @type {Array.} */ - var jumpToPosStack = []; + var jumpBackwardStack = []; /** * Contains list of most recently traversed cursor positions using NAVIGATION_JUMP_BACK command. * @private * @type {Array.} */ - var jumpedPosStack = [], + var jumpForwardStack = [], activePosNotSynced = false, captureTimer = null, currentEditPos = null, @@ -78,8 +78,8 @@ define(function (require, exports, module) { * @private */ function _hasNavBackFrames() { - return (jumpedPosStack.length > 0 && jumpToPosStack.length > 0) - || (!jumpedPosStack.length && jumpToPosStack.length > 1); + return (jumpForwardStack.length > 0 && jumpBackwardStack.length > 0) + || (!jumpForwardStack.length && jumpBackwardStack.length > 1); } /** @@ -88,7 +88,7 @@ define(function (require, exports, module) { */ function _validateNavigationCmds() { commandJumpBack.setEnabled(_hasNavBackFrames()); - commandJumpFwd.setEnabled(jumpedPosStack.length > 0); + commandJumpFwd.setEnabled(jumpForwardStack.length > 0); } /** @@ -97,10 +97,10 @@ define(function (require, exports, module) { */ function _validateFrame(entry) { var deferred = new $.Deferred(), - fileEntry = FileSystem.getFileForPath(entry.file); + fileEntry = FileSystem.getFileForPath(entry.filePath); if (entry.inMem) { - var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.file); + var indexInWS = MainViewManager.findInWorkingSet(entry.paneId, entry.filePath); // Remove entry if InMemoryFile is not found in Working set if (indexInWS === -1) { deferred.reject(); @@ -132,7 +132,7 @@ define(function (require, exports, module) { */ function NavigationFrame(editor, selectionObj) { this.cm = editor._codeMirror; - this.file = editor.document.file._path; + this.filePath = editor.document.file._path; this.inMem = editor.document.file.constructor.name === "InMemoryFile"; this.paneId = editor._paneId; this.fileStat = editor.document.file._stat; @@ -163,23 +163,7 @@ define(function (require, exports, module) { NavigationFrame.prototype._reinstateMarkers = function (editor) { this.cm = editor._codeMirror; this.paneId = editor._paneId; - - var range, - index, - bookMark; - - this.bookMarkIds = []; - for (index in this.selections) { - range = this.selections[index]; - // 'markText' has to used for a non-zero length position, if current selection is - // of zero length use bookmark instead. - if (range.start.line === range.end.line && range.start.ch === range.end.ch) { - bookMark = this.cm.setBookmark(range.start, range.end); - this.bookMarkIds.push(bookMark.id); - } else { - this.cm.markText(range.start, range.end, {className: (this.uId)}); - } - } + this._createMarkers(this.selections); }; /** @@ -192,19 +176,23 @@ define(function (require, exports, module) { */ NavigationFrame.prototype._createMarkers = function (ranges) { var range, + rangeStart, + rangeEnd, index, bookMark; this.bookMarkIds = []; for (index in ranges) { range = ranges[index]; + rangeStart = range.anchor || range.start; + rangeEnd = range.head || range.end; // 'markText' has to used for a non-zero length position, if current selection is // of zero length use bookmark instead. - if (range.anchor.line === range.head.line && range.anchor.ch === range.head.ch) { - bookMark = this.cm.setBookmark(range.anchor, range.head); + if (rangeStart.line === rangeEnd.line && rangeStart.ch === rangeEnd.ch) { + bookMark = this.cm.setBookmark(rangeStart, rangeEnd); this.bookMarkIds.push(bookMark.id); } else { - this.cm.markText(range.anchor, range.head, {className: (this.uId)}); + this.cm.markText(rangeStart, rangeEnd, {className: (this.uId)}); } } }; @@ -280,12 +268,12 @@ define(function (require, exports, module) { // To ensure we don't reopen the same doc in the last known pane // rather bring it to the same pane where user has opened it - var thisDoc = DocumentManager.getOpenDocumentForPath(this.file); + var thisDoc = DocumentManager.getOpenDocumentForPath(this.filePath); if (thisDoc && thisDoc._masterEditor) { this.paneId = thisDoc._masterEditor._paneId; } - CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.file, paneId: this.paneId}).done(function () { + CommandManager.execute(Commands.FILE_OPEN, {fullPath: this.filePath, paneId: this.paneId}).done(function () { EditorManager.getCurrentFullEditor().setSelections(self.selections, true); _validateNavigationCmds(); }).always(function () { @@ -310,24 +298,24 @@ define(function (require, exports, module) { return; } // Reset forward navigation stack if we are capturing a new event - jumpedPosStack = []; + jumpForwardStack = []; if (captureTimer) { window.clearTimeout(captureTimer); captureTimer = null; } // Ensure cursor activity has not happened because of arrow keys or edit - if (selectionObj.origin !== "+move" && (!window.event || (window.event && window.event.type !== "input"))) { + if (selectionObj.origin !== "+move" && (!window.event || window.event.type !== "input")) { captureTimer = window.setTimeout(function () { // Check if we have reached MAX_NAV_FRAMES_COUNT // If yes, control overflow - if (jumpToPosStack.length === MAX_NAV_FRAMES_COUNT) { - var navFrame = jumpToPosStack.splice(0, 1)[0]; + if (jumpBackwardStack.length === MAX_NAV_FRAMES_COUNT) { + var navFrame = jumpBackwardStack.shift(); navFrame._clearMarkers(); } currentEditPos = new NavigationFrame(event.target, selectionObj); - jumpToPosStack.push(currentEditPos); + jumpBackwardStack.push(currentEditPos); _validateNavigationCmds(); activePosNotSynced = false; }, NAV_FRAME_CAPTURE_LATENCY); @@ -340,19 +328,19 @@ define(function (require, exports, module) { * Command handler to navigate backward */ function _navigateBack() { - if (!jumpedPosStack.length) { + if (!jumpForwardStack.length) { if (activePosNotSynced) { currentEditPos = new NavigationFrame(EditorManager.getCurrentFullEditor(), {ranges: EditorManager.getCurrentFullEditor()._codeMirror.listSelections()}); - jumpedPosStack.push(currentEditPos); + jumpForwardStack.push(currentEditPos); } } - var navFrame = jumpToPosStack.pop(); + var navFrame = jumpBackwardStack.pop(); // Check if the poped frame is the current active frame or doesn't have any valid marker information // if true, jump again if (navFrame && navFrame === currentEditPos) { - jumpedPosStack.push(navFrame); + jumpForwardStack.push(navFrame); _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_BACK); return; @@ -362,7 +350,7 @@ define(function (require, exports, module) { // We will check for the file existence now, if it doesn't exist we will jump back again // but discard the popped frame as invalid. _validateFrame(navFrame).done(function () { - jumpedPosStack.push(navFrame); + jumpForwardStack.push(navFrame); navFrame.goTo(); currentEditPos = navFrame; }).fail(function () { @@ -377,31 +365,34 @@ define(function (require, exports, module) { * Command handler to navigate forward */ function _navigateForward() { - var navFrame = jumpedPosStack.pop(); + var navFrame = jumpForwardStack.pop(); + + if (!navFrame) { + return; + } // Check if the poped frame is the current active frame or doesn't have any valid marker information // if true, jump again - if (navFrame && navFrame === currentEditPos) { - jumpToPosStack.push(navFrame); + if (navFrame === currentEditPos) { + jumpBackwardStack.push(navFrame); _validateNavigationCmds(); CommandManager.execute(NAVIGATION_JUMP_FWD); return; } - if (navFrame) { - // We will check for the file existence now, if it doesn't exist we will jump back again - // but discard the popped frame as invalid. - _validateFrame(navFrame).done(function () { - jumpToPosStack.push(navFrame); - navFrame.goTo(); - currentEditPos = navFrame; - }).fail(function () { - _validateNavigationCmds(); - CommandManager.execute(NAVIGATION_JUMP_FWD); - }).always(function () { - _validateNavigationCmds(); - }); - } + // We will check for the file existence now, if it doesn't exist we will jump back again + // but discard the popped frame as invalid. + _validateFrame(navFrame).done(function () { + jumpBackwardStack.push(navFrame); + navFrame.goTo(); + currentEditPos = navFrame; + }).fail(function () { + _validateNavigationCmds(); + CommandManager.execute(NAVIGATION_JUMP_FWD); + }).always(function () { + _validateNavigationCmds(); + }); + } /** @@ -436,8 +427,8 @@ define(function (require, exports, module) { */ function _captureFrame(editor) { // Capture the active position now if it was not captured earlier - if ((activePosNotSynced || !jumpToPosStack.length) && !jumpInProgress) { - jumpToPosStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); + if ((activePosNotSynced || !jumpBackwardStack.length) && !jumpInProgress) { + jumpBackwardStack.push(new NavigationFrame(editor, {ranges: editor._codeMirror.listSelections()})); } } @@ -460,8 +451,8 @@ define(function (require, exports, module) { * @private */ function _handleEditorCleanup(event, editor) { - _backupLiveMarkers(jumpToPosStack, editor); - _backupLiveMarkers(jumpedPosStack, editor); + _backupLiveMarkers(jumpBackwardStack, editor); + _backupLiveMarkers(jumpForwardStack, editor); } /** @@ -469,8 +460,8 @@ define(function (require, exports, module) { * @private */ function _removeBackwardFramesForFile(file) { - jumpToPosStack = jumpToPosStack.filter(function (frame) { - return frame.file !== file._path && frame.stat !== file._stat; + jumpBackwardStack = jumpBackwardStack.filter(function (frame) { + return frame.filePath !== file._path && frame.stat !== file._stat; }); } @@ -479,8 +470,8 @@ define(function (require, exports, module) { * @private */ function _removeForwardFramesForFile(file) { - jumpedPosStack = jumpedPosStack.filter(function (frame) { - return frame.file !== file._path && frame.stat !== file._stat; + jumpForwardStack = jumpForwardStack.filter(function (frame) { + return frame.filePath !== file._path && frame.stat !== file._stat; }); } @@ -497,8 +488,8 @@ define(function (require, exports, module) { } function _handleProjectOpen() { - jumpToPosStack = []; - jumpedPosStack = []; + jumpBackwardStack = []; + jumpForwardStack = []; } /** @@ -509,7 +500,7 @@ define(function (require, exports, module) { var index, frame; for (index in frames) { frame = frames[index]; - if (!frame.cm && frame.file === editor.document.file._path) { + if (!frame.cm && frame.filePath === editor.document.file._path) { frame._reinstateMarkers(editor); } } @@ -540,8 +531,8 @@ define(function (require, exports, module) { ProjectManager.on("projectOpen", _handleProjectOpen); EditorManager.on("_fullEditorCreatedForDocument", function (event, document, editor) { _handleExternalChange(event, {file: document.file}); - _reinstateMarkers(editor, jumpToPosStack); - _reinstateMarkers(editor, jumpedPosStack); + _reinstateMarkers(editor, jumpBackwardStack); + _reinstateMarkers(editor, jumpForwardStack); }); FileSystem.on("change", function (event, entry) { _handleExternalChange(event, {file: entry});