Modules (188)

DocumentCommandHandlers

Description

Dependencies

Variables

Public API

APP_QUIT_CANCELLED

Event triggered when File Save is cancelled, when prompted to save dirty files

    var APP_QUIT_CANCELLED = "appQuitCancelled";

USER_CANCELED

Unique token used to indicate user-driven cancellation of Save As (as opposed to file IO error)

    var USER_CANCELED = { userCanceled: true };

    PreferencesManager.definePreference("defaultExtension", "string", "", {
        excludeFromHints: true
    });
    EventDispatcher.makeEventDispatcher(exports);

WINDOW_TITLE_STRING_DOC

String template for window title when a file is open.

Type
string
    var WINDOW_TITLE_STRING_DOC = "{0} ({1}) " + _osDash + " {2}";

WINDOW_TITLE_STRING_NO_DOC

String template for window title when no file is open.

Type
string
    var WINDOW_TITLE_STRING_NO_DOC = "{0} " + _osDash + " {1}";
Private

_$dirtydot

Container for dirty dot; must be an inline element

Type
jQueryObject
    var _$dirtydot = null;
Private

_$title

Container for label shown above editor; must be an inline element

Type
jQueryObject
    var _$title = null;
Private

_$titleContainerToolbar

Container for _$titleWrapper; if changing title changes this element's height, must kick editor to resize

Type
jQueryObject
    var _$titleContainerToolbar = null;
Private

_$titleWrapper

Container for _$title; need not be an inline element

Type
jQueryObject
    var _$titleWrapper = null;
Private

_addedNavKeyHandler

Are we already listening for a keyup to call detectDocumentNavEnd()?

    var _addedNavKeyHandler = false;
Private

_currentTitlePath

Label shown above editor for current document: filename and potentially some of its path

Type
string
    var _currentTitlePath = null;
Private

_defaultOpenDialogFullPath

    var _defaultOpenDialogFullPath = null;
Private

_isReloading

prevents reentrancy of browserReload()

Type
boolean
    var _isReloading = false;
Private

_lastToolbarHeight

Last known height of _$titleContainerToolbar

Type
number
    var _lastToolbarHeight = null;
Private

_nextUntitledIndexToUse

index to use for next, new Untitled document

Type
number
    var _nextUntitledIndexToUse = 1;
Private

_osDash

Determine the dash character for each platform. Use emdash on Mac and a standard dash on all other platforms.

Type
string
    var _osDash = brackets.platform === "mac" ? "\u2014" : "-";
Private

_windowGoingAway

    var _windowGoingAway = false;

fileNewInProgress

Prevents re-entrancy into handleFileNewInProject()

handleFileNewInProject() first prompts the user to name a file and then asynchronously writes the file when the filename field loses focus. This boolean prevent additional calls to handleFileNewInProject() when an existing file creation call is outstanding

    var fileNewInProgress = false;

handleFileSaveAs

JSLint workaround for circular dependency

Type
function
    var handleFileSaveAs;

handleReloadWithoutExts

Reload Without Extensions commnad handler *

    var handleReloadWithoutExts = _.partial(handleReload, true);

isTestWindow

Attach a beforeunload handler to notify user about unsaved changes and URL redirection in CEF. Prevents data loss in scenario reported under #13708 Make sure we don't attach this handler if the current window is actually a test window


    var isTestWindow = (new window.URLSearchParams(window.location.search || "")).get("testEnvironment");
    if (!isTestWindow) {
        window.onbeforeunload = function(e) {
            var openDocs = DocumentManager.getAllOpenDocuments();

            // Detect any unsaved changes
            openDocs = openDocs.filter(function(doc) {
                return doc && doc.isDirty;
            });

            // Ensure we are not in normal app-quit or reload workflow
            if (!_isReloading && !_windowGoingAway) {
                if (openDocs.length > 0) {
                    return Strings.WINDOW_UNLOAD_WARNING_WITH_UNSAVED_CHANGES;
                } else {
                    return Strings.WINDOW_UNLOAD_WARNING;
                }
            }
        };
    }

Functions

Private

_closeList

list non-nullable Array.<File>
the list of files to close
promptOnly boolean
true to just prompt for saving documents with actually closing them.
_forceClose boolean
Whether to force all the documents to close even if they have unsaved changes. For unit testing only.
Returns: jQuery.Promise
promise that is resolved or rejected when the function finishes.
    function _closeList(list, promptOnly, _forceClose) {
        var result      = new $.Deferred(),
            unsavedDocs = [];

        list.forEach(function (file) {
            var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);
            if (doc && doc.isDirty) {
                unsavedDocs.push(doc);
            }
        });

        if (unsavedDocs.length === 0 || _forceClose) {
            // No unsaved changes or we want to ignore them, so we can proceed without a prompt
            result.resolve();

        } else if (unsavedDocs.length === 1) {
            // Only one unsaved file: show the usual single-file-close confirmation UI
            var fileCloseArgs = { file: unsavedDocs[0].file, promptOnly: promptOnly, spawnedRequest: true };

            handleFileClose(fileCloseArgs).done(function () {
                // still need to close any other, non-unsaved documents
                result.resolve();
            }).fail(function () {
                result.reject();
            });

        } else {
            // Multiple unsaved files: show a single bulk prompt listing all files
            var message = Strings.SAVE_CLOSE_MULTI_MESSAGE + FileUtils.makeDialogFileList(_.map(unsavedDocs, _shortTitleForDocument));

            Dialogs.showModalDialog(
                DefaultDialogs.DIALOG_ID_SAVE_CLOSE,
                Strings.SAVE_CLOSE_TITLE,
                message,
                [
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_LEFT,
                        id        : Dialogs.DIALOG_BTN_DONTSAVE,
                        text      : Strings.DONT_SAVE
                    },
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
                        id        : Dialogs.DIALOG_BTN_CANCEL,
                        text      : Strings.CANCEL
                    },
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
                        id        : Dialogs.DIALOG_BTN_OK,
                        text      : Strings.SAVE
                    }
                ]
            )
                .done(function (id) {
                    if (id === Dialogs.DIALOG_BTN_CANCEL) {
                        dispatchAppQuitCancelledEvent();
                        result.reject();
                    } else if (id === Dialogs.DIALOG_BTN_OK) {
                        // Save all unsaved files, then if that succeeds, close all
                        _saveFileList(list).done(function (listAfterSave) {
                            // List of files after save may be different, if any were Untitled
                            result.resolve(listAfterSave);
                        }).fail(function () {
                            result.reject();
                        });
                    } else {
                        // "Don't Save" case--we can just go ahead and close all files.
                        result.resolve();
                    }
                });
        }

        // If all the unsaved-changes confirmations pan out above, then go ahead & close all editors
        // NOTE: this still happens before any done() handlers added by our caller, because jQ
        // guarantees that handlers run in the order they are added.
        result.done(function (listAfterSave) {
            listAfterSave = listAfterSave || list;
            if (!promptOnly) {
                MainViewManager._closeList(MainViewManager.ALL_PANES, listAfterSave);
            }
        });

        return result.promise();
    }
Private

_disableCache

Disables Brackets' cache via the remote debugging protocol.

Returns: $.Promise
A jQuery promise that will be resolved when the cache is disabled and be rejected in any other case
    function _disableCache() {
        var result = new $.Deferred();

        if (brackets.inBrowser) {
            result.resolve();
        } else {
            var port = brackets.app.getRemoteDebuggingPort ? brackets.app.getRemoteDebuggingPort() : 9234;
            Inspector.getDebuggableWindows("127.0.0.1", port)
                .fail(result.reject)
                .done(function (response) {
                    var page = response[0];
                    if (!page || !page.webSocketDebuggerUrl) {
                        result.reject();
                        return;
                    }
                    var _socket = new WebSocket(page.webSocketDebuggerUrl);
                    // Disable the cache
                    _socket.onopen = function _onConnect() {
                        _socket.send(JSON.stringify({ id: 1, method: "Network.setCacheDisabled", params: { "cacheDisabled": true } }));
                    };
                    // The first message will be the confirmation => disconnected to allow remote debugging of Brackets
                    _socket.onmessage = function _onMessage(e) {
                        _socket.close();
                        result.resolve();
                    };
                    // In case of an error
                    _socket.onerror = result.reject;
                });
        }

        return result.promise();
    }
Private

_doOpen

fullPath non-nullable string
silent optional boolean
If true, don't show error message
paneId, optional string
the id oi the pane in which to open the file. Can be undefined, a valid pane id or ACTIVE_PANE.
options, optional {*}
command options
Returns: $.Promise
a jQuery promise that will either - be resolved with a file for the specified file path or - be rejected with FileSystemError if the file can not be read. If paneId is undefined, the ACTIVE_PANE constant
    function _doOpen(fullPath, silent, paneId, options) {
        var result = new $.Deferred();

        // workaround for https://github.com/adobe/brackets/issues/6001
        // TODO should be removed once bug is closed.
        // if we are already displaying a file do nothing but resolve immediately.
        // this fixes timing issues in test cases.
        if (MainViewManager.getCurrentlyViewedPath(paneId || MainViewManager.ACTIVE_PANE) === fullPath) {
            result.resolve(MainViewManager.getCurrentlyViewedFile(paneId || MainViewManager.ACTIVE_PANE));
            return result.promise();
        }

        function _cleanup(fileError, fullFilePath) {
            if (fullFilePath) {
                // For performance, we do lazy checking of file existence, so it may be in workingset
                MainViewManager._removeView(paneId, FileSystem.getFileForPath(fullFilePath));
                MainViewManager.focusActivePane();
            }
            result.reject(fileError);
        }
        function _showErrorAndCleanUp(fileError, fullFilePath) {
            if (silent) {
                _cleanup(fileError, fullFilePath);
            } else {
                showFileOpenError(fileError, fullFilePath).done(function () {
                    _cleanup(fileError, fullFilePath);
                });
            }
        }

        if (!fullPath) {
            throw new Error("_doOpen() called without fullPath");
        } else {
            var perfTimerName = PerfUtils.markStart("Open File:\t" + fullPath);
            result.always(function () {
                PerfUtils.addMeasurement(perfTimerName);
            });

            var file = FileSystem.getFileForPath(fullPath);
            if (options && options.encoding) {
                file._encoding = options.encoding;
            } else {
                var projectRoot = ProjectManager.getProjectRoot(),
                    context = {
                        location : {
                            scope: "user",
                            layer: "project",
                            layerID: projectRoot.fullPath
                        }
                    };
                var encoding = PreferencesManager.getViewState("encoding", context);
                if (encoding && encoding[fullPath]) {
                    file._encoding = encoding[fullPath];
                }
            }
            MainViewManager._open(paneId, file, options)
                .done(function () {
                    result.resolve(file);
                })
                .fail(function (fileError) {
                    _showErrorAndCleanUp(fileError, fullPath);
                    result.reject();
                });
        }

        return result.promise();
    }
Private

_doOpenWithOptionalPath

fullPath nullable string
The path of the file to open; if it's null we'll prompt for it
silent optional boolean
If true, don't show error message
paneId optional string
the pane in which to open the file. Can be undefined, a valid pane id or ACTIVE_PANE
options optional {*}
options to pass to MainViewManager._open
Returns: $.Promise
a jQuery promise resolved with a Document object or rejected with an err
    function _doOpenWithOptionalPath(fullPath, silent, paneId, options) {
        var result;
        paneId = paneId || MainViewManager.ACTIVE_PANE;
        if (!fullPath) {
            // Create placeholder deferred
            result = new $.Deferred();

            //first time through, default to the current project path
            if (!_defaultOpenDialogFullPath) {
                _defaultOpenDialogFullPath = ProjectManager.getProjectRoot().fullPath;
            }
            // Prompt the user with a dialog
            FileSystem.showOpenDialog(true, false, Strings.OPEN_FILE, _defaultOpenDialogFullPath, null, function (err, paths) {
                if (!err) {
                    if (paths.length > 0) {
                        // Add all files to the workingset without verifying that
                        // they still exist on disk (for faster opening)
                        var filesToOpen = [];

                        paths.forEach(function (path) {
                            filesToOpen.push(FileSystem.getFileForPath(path));
                        });
                        MainViewManager.addListToWorkingSet(paneId, filesToOpen);

                        _doOpen(paths[paths.length - 1], silent, paneId, options)
                            .done(function (file) {
                                _defaultOpenDialogFullPath =
                                    FileUtils.getDirectoryPath(
                                        MainViewManager.getCurrentlyViewedPath(paneId)
                                    );
                            })
                            // Send the resulting document that was opened
                            .then(result.resolve, result.reject);
                    } else {
                        // Reject if the user canceled the dialog
                        result.reject();
                    }
                }
            });
        } else {
            result = _doOpen(fullPath, silent, paneId, options);
        }

        return result.promise();
    }
Private

_doRevert

Reverts the Document to the current contents of its file on disk. Discards any unsaved changes in the Document.

doc Document
suppressError optional boolean
If true, then a failure to read the file will be ignored and the resulting promise will be resolved rather than rejected.
Returns: $.Promise
a Promise that's resolved when done, or (if suppressError is false) rejected with a FileSystemError if the file cannot be read (after showing an error dialog to the user).
    function _doRevert(doc, suppressError) {
        var result = new $.Deferred();

        FileUtils.readAsText(doc.file)
            .done(function (text, readTimestamp) {
                doc.refreshText(text, readTimestamp);
                result.resolve();
            })
            .fail(function (error) {
                if (suppressError) {
                    result.resolve();
                } else {
                    showFileOpenError(error, doc.file.fullPath)
                        .done(function () {
                            result.reject(error);
                        });
                }
            });

        return result.promise();
    }
Private

_doSaveAs

Opens the native OS save as dialog and saves document. The original document is reverted in case it was dirty. Text selection and cursor position from the original document are preserved in the new document. When saving to the original document the document is saved as if save was called.

doc Document
settings nullable {cursorPos:!Object, selection:!Object, scrollPos:!Object}
properties of the original document's editor that need to be carried over to the new document i.e. scrollPos, cursorPos and text selection
Returns: $.Promise
a promise that is resolved with the saved document's File. Rejected in case of IO error (after error dialog dismissed), or if the Save dialog was canceled.
    function _doSaveAs(doc, settings) {
        var origPath,
            saveAsDefaultPath,
            defaultName,
            result = new $.Deferred();

        function _doSaveAfterSaveDialog(path) {
            var newFile;

            // Reconstruct old doc's editor's view state, & finally resolve overall promise
            function _configureEditorAndResolve() {
                var editor = EditorManager.getActiveEditor();
                if (editor) {
                    if (settings) {
                        editor.setSelections(settings.selections);
                        editor.setScrollPos(settings.scrollPos.x, settings.scrollPos.y);
                    }
                }
                result.resolve(newFile);
            }

            // Replace old document with new one in open editor & workingset
            function openNewFile() {
                var fileOpenPromise;

                if (FileViewController.getFileSelectionFocus() === FileViewController.PROJECT_MANAGER) {
                    // If selection is in the tree, leave workingset unchanged - even if orig file is in the list
                    fileOpenPromise = FileViewController
                        .openAndSelectDocument(path, FileViewController.PROJECT_MANAGER);
                } else {
                    // If selection is in workingset, replace orig item in place with the new file
                    var info = MainViewManager.findInAllWorkingSets(doc.file.fullPath).shift();

                    // Remove old file from workingset; no redraw yet since there's a pause before the new file is opened
                    MainViewManager._removeView(info.paneId, doc.file, true);

                    // Add new file to workingset, and ensure we now redraw (even if index hasn't changed)
                    fileOpenPromise = handleFileAddToWorkingSetAndOpen({fullPath: path, paneId: info.paneId, index: info.index, forceRedraw: true});
                }

                // always configure editor after file is opened
                fileOpenPromise.always(function () {
                    _configureEditorAndResolve();
                });
            }

            // Same name as before - just do a regular Save
            if (path === origPath) {
                doSave(doc).then(result.resolve, result.reject);
                return;
            }

            doc.isSaving = true;    // mark that we're saving the document

            // First, write document's current text to new file
            if (doc.file._encoding && doc.file._encoding !== "UTF-8") {
                var projectRoot = ProjectManager.getProjectRoot(),
                    context = {
                        location : {
                            scope: "user",
                            layer: "project",
                            layerID: projectRoot.fullPath
                        }
                    };
                var encoding = PreferencesManager.getViewState("encoding", context);
                encoding[path] = doc.file._encoding;
                PreferencesManager.setViewState("encoding", encoding, context);
            }
            newFile = FileSystem.getFileForPath(path);
            newFile._encoding = doc.file._encoding;

            // Save as warns you when you're about to overwrite a file, so we
            // explicitly allow "blind" writes to the filesystem in this case,
            // ignoring warnings about the contents being modified outside of
            // the editor.
            FileUtils.writeText(newFile, doc.getText(true), true)
                .done(function () {
                    // If there were unsaved changes before Save As, they don't stay with the old
                    // file anymore - so must revert the old doc to match disk content.
                    // Only do this if the doc was dirty: _doRevert on a file that is not dirty and
                    // not in the workingset has the side effect of adding it to the workingset.
                    if (doc.isDirty && !(doc.isUntitled())) {
                        // if the file is dirty it must be in the workingset
                        // _doRevert is side effect free in this case
                        _doRevert(doc).always(openNewFile);
                    } else {
                        openNewFile();
                    }
                })
                .fail(function (error) {
                    _showSaveFileError(error, path)
                        .done(function () {
                            result.reject(error);
                        });
                })
                .always(function () {
                    // mark that we're done saving the document
                    doc.isSaving = false;
                });
        }

        if (doc) {
            origPath = doc.file.fullPath;
            // If the document is an untitled document, we should default to project root.
            if (doc.isUntitled()) {
                // (Issue #4489) if we're saving an untitled document, go ahead and switch to this document
                //   in the editor, so that if we're, for example, saving several files (ie. Save All),
                //   then the user can visually tell which document we're currently prompting them to save.
                var info = MainViewManager.findInAllWorkingSets(origPath).shift();

                if (info) {
                    MainViewManager._open(info.paneId, doc.file);
                }

                // If the document is untitled, default to project root.
                saveAsDefaultPath = ProjectManager.getProjectRoot().fullPath;
            } else {
                saveAsDefaultPath = FileUtils.getDirectoryPath(origPath);
            }
            defaultName = FileUtils.getBaseName(origPath);
            var file = FileSystem.getFileForPath(origPath);
            if (file instanceof InMemoryFile) {
                var language = LanguageManager.getLanguageForPath(origPath);
                if (language) {
                    var fileExtensions = language.getFileExtensions();
                    if (fileExtensions && fileExtensions.length > 0) {
                        defaultName += "." + fileExtensions[0];
                    }
                }
            }
            FileSystem.showSaveDialog(Strings.SAVE_FILE_AS, saveAsDefaultPath, defaultName, function (err, selectedPath) {
                if (!err) {
                    if (selectedPath) {
                        _doSaveAfterSaveDialog(selectedPath);
                    } else {
                        dispatchAppQuitCancelledEvent();
                        result.reject(USER_CANCELED);
                    }
                } else {
                    result.reject(err);
                }
            });
        } else {
            result.reject();
        }
        return result.promise();
    }
Private

_getUntitledFileSuggestion

dir Directory
The directory to use
baseFileName string
The base to start with, "-n" will get appended to make unique
isFolder boolean
True if the suggestion is for a folder name
Returns: $.Promise
a jQuery promise that will be resolved with a unique name starting with the given base name
    function _getUntitledFileSuggestion(dir, baseFileName, isFolder) {
        var suggestedName   = baseFileName + "-" + _nextUntitledIndexToUse++,
            deferred        = $.Deferred();

        if (_nextUntitledIndexToUse > 9999) {
            //we've tried this enough
            deferred.reject();
        } else {
            var path = dir.fullPath + suggestedName,
                entry = isFolder ? FileSystem.getDirectoryForPath(path)
                                 : FileSystem.getFileForPath(path);

            entry.exists(function (err, exists) {
                if (err || exists) {
                    _getUntitledFileSuggestion(dir, baseFileName, isFolder)
                        .then(deferred.resolve, deferred.reject);
                } else {
                    deferred.resolve(suggestedName);
                }
            });
        }

        return deferred.promise();
    }
Private

_handleNewItemInProject

Bottleneck function for creating new files and folders in the project tree.

isFolder boolean
true if creating a new folder, false if creating a new file
    function _handleNewItemInProject(isFolder) {
        if (fileNewInProgress) {
            ProjectManager.forceFinishRename();
            return;
        }
        fileNewInProgress = true;

        // Determine the directory to put the new file
        // If a file is currently selected in the tree, put it next to it.
        // If a directory is currently selected in the tree, put it in it.
        // If an Untitled document is selected or nothing is selected in the tree, put it at the root of the project.
        var baseDirEntry,
            selected = ProjectManager.getFileTreeContext();
        if ((!selected) || (selected instanceof InMemoryFile)) {
            selected = ProjectManager.getProjectRoot();
        }

        if (selected.isFile) {
            baseDirEntry = FileSystem.getDirectoryForPath(selected.parentPath);
        }

        baseDirEntry = baseDirEntry || selected;

        // Create the new node. The createNewItem function does all the heavy work
        // of validating file name, creating the new file and selecting.
        function createWithSuggestedName(suggestedName) {
            return ProjectManager.createNewItem(baseDirEntry, suggestedName, false, isFolder)
                .always(function () { fileNewInProgress = false; });
        }

        return _getUntitledFileSuggestion(baseDirEntry, Strings.UNTITLED, isFolder)
            .then(createWithSuggestedName, createWithSuggestedName.bind(undefined, Strings.UNTITLED));
    }
Private

_handleWindowGoingAway

commandData Object
(not referenced)
postCloseHandler non-nullable function()
called after close
failHandler non-nullable function()
called when the save fails to cancel closing the window
    function _handleWindowGoingAway(commandData, postCloseHandler, failHandler) {
        if (_windowGoingAway) {
            //if we get called back while we're closing, then just return
            return (new $.Deferred()).reject().promise();
        }

        return CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true })
            .done(function () {
                _windowGoingAway = true;

                // Give everyone a chance to save their state - but don't let any problems block
                // us from quitting
                try {
                    ProjectManager.trigger("beforeAppClose");
                } catch (ex) {
                    console.error(ex);
                }

                postCloseHandler();
            })
            .fail(function () {
                _windowGoingAway = false;
                if (failHandler) {
                    failHandler();
                }
            });
    }
Private Public API

_parseDecoratedPath

path nullable string
a string of the form "fullpath[:lineNumber[:columnNumber]]"
Returns: {path: string,line: ?number,column: ?number}
    function _parseDecoratedPath(path) {
        var result = {path: path, line: null, column: null};
        if (path) {
            // If the path has a trailing :lineNumber and :columnNumber, strip
            // these off and assign to result.line and result.column.
            var matchResult = /(.+?):([0-9]+)(:([0-9]+))?$/.exec(path);
            if (matchResult) {
                result.path = matchResult[1];
                if (matchResult[2]) {
                    result.line = parseInt(matchResult[2], 10);
                }
                if (matchResult[4]) {
                    result.column = parseInt(matchResult[4], 10);
                }
            }
        }
        return result;
    }
Private

_saveFileList

Saves all unsaved documents corresponding to 'fileList'. Returns a Promise that will be resolved once ALL the save operations have been completed. If ANY save operation fails, an error dialog is immediately shown but after dismissing we continue saving the other files; after all files have been processed, the Promise is rejected if any ONE save operation failed (the error given is the first one encountered). If the user cancels any Save As dialog (for untitled files), the Promise is immediately rejected.

fileList non-nullable Array.<File>
Returns: !$.Promise
Resolved with {!Array.}, which may differ from 'fileList' if any of the files were Unsaved documents. Or rejected with {?FileSystemError}.
    function _saveFileList(fileList) {
        // Do in serial because doSave shows error UI for each file, and we don't want to stack
        // multiple dialogs on top of each other
        var userCanceled = false,
            filesAfterSave = [];

        return Async.doSequentially(
            fileList,
            function (file) {
                // Abort remaining saves if user canceled any Save As dialog
                if (userCanceled) {
                    return (new $.Deferred()).reject().promise();
                }

                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);
                if (doc) {
                    var savePromise = handleFileSave({doc: doc});
                    savePromise
                        .done(function (newFile) {
                            filesAfterSave.push(newFile);
                        })
                        .fail(function (error) {
                            if (error === USER_CANCELED) {
                                userCanceled = true;
                            }
                        });
                    return savePromise;
                } else {
                    // workingset entry that was never actually opened - ignore
                    filesAfterSave.push(file);
                    return (new $.Deferred()).resolve().promise();
                }
            },
            false  // if any save fails, continue trying to save other files anyway; then reject at end
        ).then(function () {
            return filesAfterSave;
        });
    }
Private

_shortTitleForDocument

Returns a short title for a given document.

doc Document
the document to compute the short title for
Returns: string
- a short title for doc.
    function _shortTitleForDocument(doc) {
        var fullPath = doc.file.fullPath;

        // If the document is untitled then return the filename, ("Untitled-n.ext");
        // otherwise show the project-relative path if the file is inside the
        // current project or the full absolute path if it's not in the project.
        if (doc.isUntitled()) {
            return fullPath.substring(fullPath.lastIndexOf("/") + 1);
        } else {
            return ProjectManager.makeProjectRelativeIfPossible(fullPath);
        }
    }
Private

_showSaveFileError

name string
path string
Returns: Dialog
    function _showSaveFileError(name, path) {
        return Dialogs.showModalDialog(
            DefaultDialogs.DIALOG_ID_ERROR,
            Strings.ERROR_SAVING_FILE_TITLE,
            StringUtils.format(
                Strings.ERROR_SAVING_FILE,
                StringUtils.breakableUrl(path),
                FileUtils.getFileErrorString(name)
            )
        );
    }
Private

_updateTitle

Updates the title bar with new file title or dirty indicator

    function _updateTitle() {
        var currentDoc          = DocumentManager.getCurrentDocument(),
            windowTitle         = brackets.config.app_title,
            currentlyViewedFile = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE),
            currentlyViewedPath = currentlyViewedFile && currentlyViewedFile.fullPath,
            readOnlyString      = (currentlyViewedFile && currentlyViewedFile.readOnly) ? "[Read Only] - " : "";

        if (!brackets.nativeMenus) {
            if (currentlyViewedPath) {
                _$title.text(_currentTitlePath);
                _$title.attr("title", currentlyViewedPath);
                if (currentDoc) {
                    // dirty dot is always in DOM so layout doesn't change, and visibility is toggled
                    _$dirtydot.css("visibility", (currentDoc.isDirty) ? "visible" : "hidden");
                } else {
                    // hide dirty dot if there is no document
                    _$dirtydot.css("visibility", "hidden");
                }
            } else {
                _$title.text("");
                _$title.attr("title", "");
                _$dirtydot.css("visibility", "hidden");
            }

            // Set _$titleWrapper to a fixed width just large enough to accommodate _$title. This seems equivalent to what
            // the browser would do automatically, but the CSS trick we use for layout requires _$titleWrapper to have a
            // fixed width set on it (see the "#titlebar" CSS rule for details).
            _$titleWrapper.css("width", "");
            var newWidth = _$title.width();
            _$titleWrapper.css("width", newWidth);

            // Changing the width of the title may cause the toolbar layout to change height, which needs to resize the
            // editor beneath it (toolbar changing height due to window resize is already caught by EditorManager).
            var newToolbarHeight = _$titleContainerToolbar.height();
            if (_lastToolbarHeight !== newToolbarHeight) {
                _lastToolbarHeight = newToolbarHeight;
                WorkspaceManager.recomputeLayout();
            }
        }

        var projectRoot = ProjectManager.getProjectRoot();
        if (projectRoot) {
            var projectName = projectRoot.name;
            // Construct shell/browser window title, e.g. "• index.html (myProject) — Brackets"
            if (currentlyViewedPath) {
                windowTitle = StringUtils.format(WINDOW_TITLE_STRING_DOC, readOnlyString + _currentTitlePath, projectName, brackets.config.app_title);
                // Display dirty dot when there are unsaved changes
                if (currentDoc && currentDoc.isDirty) {
                    windowTitle = "• " + windowTitle;
                }
            } else {
                // A document is not open
                windowTitle = StringUtils.format(WINDOW_TITLE_STRING_NO_DOC, projectName, brackets.config.app_title);
            }
        }
        window.document.title = windowTitle;
    }

browserReload

Does a full reload of the browser window

href string
The url to reload into the window
    function browserReload(href) {
        if (_isReloading) {
            return;
        }

        _isReloading = true;

        return CommandManager.execute(Commands.FILE_CLOSE_ALL, { promptOnly: true }).done(function () {
            // Give everyone a chance to save their state - but don't let any problems block
            // us from quitting
            try {
                ProjectManager.trigger("beforeAppClose");
            } catch (ex) {
                console.error(ex);
            }

            // Disable the cache to make reloads work
            _disableCache().always(function () {
                // Remove all menus to assure every part of Brackets is reloaded
                _.forEach(Menus.getAllMenus(), function (value, key) {
                    Menus.removeMenu(key);
                });

                // If there's a fragment in both URLs, setting location.href won't actually reload
                var fragment = href.indexOf("#");
                if (fragment !== -1) {
                    href = href.substr(0, fragment);
                }

                // Defer for a more successful reload - issue #11539
                setTimeout(function () {
                    window.location.href = href;
                }, 1000);
            });
        }).fail(function () {
            _isReloading = false;
        });
    }

detectDocumentNavEnd

When the Ctrl key is released, if we were in the middle of a next/prev document navigation sequence, now is the time to end it and update the MRU order. If we allowed the order to update on every next/prev increment, the 1st & 2nd entries would just switch places forever and we'd never get further down the list.

event jQueryEvent
Key-up event
    function detectDocumentNavEnd(event) {
        if (event.keyCode === KeyEvent.DOM_VK_CONTROL) {  // Ctrl key
            MainViewManager.endTraversal();
            _addedNavKeyHandler = false;
            $(window.document.body).off("keyup", detectDocumentNavEnd);
        }
    }

dispatchAppQuitCancelledEvent

Dispatches the app quit cancelled event

    function dispatchAppQuitCancelledEvent() {
        exports.trigger(exports.APP_QUIT_CANCELLED);
    }

doSave

Saves a document to its existing path. Does NOT support untitled documents.

docToSave non-nullable Document
force optional boolean
Ignore CONTENTS_MODIFIED errors from the FileSystem
Returns: $.Promise
a promise that is resolved with the File of docToSave (to mirror the API of _doSaveAs()). Rejected in case of IO error (after error dialog dismissed).
    function doSave(docToSave, force) {
        var result = new $.Deferred(),
            file = docToSave.file;

        function handleError(error) {
            _showSaveFileError(error, file.fullPath)
                .done(function () {
                    result.reject(error);
                });
        }

        function handleContentsModified() {
            Dialogs.showModalDialog(
                DefaultDialogs.DIALOG_ID_ERROR,
                Strings.EXT_MODIFIED_TITLE,
                StringUtils.format(
                    Strings.EXT_MODIFIED_WARNING,
                    StringUtils.breakableUrl(docToSave.file.fullPath)
                ),
                [
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_LEFT,
                        id        : Dialogs.DIALOG_BTN_SAVE_AS,
                        text      : Strings.SAVE_AS
                    },
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
                        id        : Dialogs.DIALOG_BTN_CANCEL,
                        text      : Strings.CANCEL
                    },
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
                        id        : Dialogs.DIALOG_BTN_OK,
                        text      : Strings.SAVE_AND_OVERWRITE
                    }
                ]
            )
                .done(function (id) {
                    if (id === Dialogs.DIALOG_BTN_CANCEL) {
                        result.reject();
                    } else if (id === Dialogs.DIALOG_BTN_OK) {
                        // Re-do the save, ignoring any CONTENTS_MODIFIED errors
                        doSave(docToSave, true).then(result.resolve, result.reject);
                    } else if (id === Dialogs.DIALOG_BTN_SAVE_AS) {
                        // Let the user choose a different path at which to write the file
                        handleFileSaveAs({doc: docToSave}).then(result.resolve, result.reject);
                    }
                });
        }

        function trySave() {
            // We don't want normalized line endings, so it's important to pass true to getText()
            FileUtils.writeText(file, docToSave.getText(true), force)
                .done(function () {
                    docToSave.notifySaved();
                    result.resolve(file);
                })
                .fail(function (err) {
                    if (err === FileSystemError.CONTENTS_MODIFIED) {
                        handleContentsModified();
                    } else {
                        handleError(err);
                    }
                });
        }

        if (docToSave.isDirty) {
            if (docToSave.keepChangesTime) {
                // The user has decided to keep conflicting changes in the editor. Check to make sure
                // the file hasn't changed since they last decided to do that.
                docToSave.file.stat(function (err, stat) {
                    // If the file has been deleted on disk, the stat will return an error, but that's fine since
                    // that means there's no file to overwrite anyway, so the save will succeed without us having
                    // to set force = true.
                    if (!err && docToSave.keepChangesTime === stat.mtime.getTime()) {
                        // OK, it's safe to overwrite the file even though we never reloaded the latest version,
                        // since the user already said s/he wanted to ignore the disk version.
                        force = true;
                    }
                    trySave();
                });
            } else {
                trySave();
            }
        } else {
            result.resolve(file);
        }
        result.always(function () {
            MainViewManager.focusActivePane();
        });
        return result.promise();
    }

goNextPrevDoc

Navigate to the next/previous (MRU or list order) document. Don't update MRU order yet

inc non-nullable number
Delta indicating in which direction we're going
listOrder nullable boolean
Whether to navigate using MRU or list order. Defaults to MRU order
    function goNextPrevDoc(inc, listOrder) {
        var result;
        if (listOrder) {
            result = MainViewManager.traverseToNextViewInListOrder(inc);
        } else {
            result = MainViewManager.traverseToNextViewByMRU(inc);
        }

        if (result) {
            var file = result.file,
                paneId = result.paneId;

            MainViewManager.beginTraversal();
            CommandManager.execute(Commands.FILE_OPEN, {fullPath: file.fullPath,
                                                        paneId: paneId });

            // Listen for ending of Ctrl+Tab sequence
            if (!_addedNavKeyHandler) {
                _addedNavKeyHandler = true;
                $(window.document.body).keyup(detectDocumentNavEnd);
            }
        }
    }
Private

handleAbortQuit

    function handleAbortQuit() {
        _windowGoingAway = false;
    }
Private

handleBeforeMenuPopup

    function handleBeforeMenuPopup() {
        PopUpManager.trigger("beforeMenuPopup");
    }

handleCurrentFileChange

Handles currentFileChange and filenameChanged events and updates the titlebar

    function handleCurrentFileChange() {
        var newFile = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);

        if (newFile) {
            var newDocument = DocumentManager.getOpenDocumentForPath(newFile.fullPath);

            if (newDocument) {
                _currentTitlePath = _shortTitleForDocument(newDocument);
            } else {
                _currentTitlePath = ProjectManager.makeProjectRelativeIfPossible(newFile.fullPath);
            }
        } else {
            _currentTitlePath = null;
        }

        // Update title text & "dirty dot" display
        _updateTitle();
    }

handleDirtyChange

Handles dirtyFlagChange event and updates the title bar if necessary

    function handleDirtyChange(event, changedDoc) {
        var currentDoc = DocumentManager.getCurrentDocument();

        if (currentDoc && changedDoc.file.fullPath === currentDoc.file.fullPath) {
            _updateTitle();
        }
    }

handleDocumentOpen

Opens the given file, makes it the current file, does NOT add it to the workingset

commandData FileCommandData
fullPath: File to open; silent: optional flag to suppress error messages; paneId: optional PaneId (defaults to active pane)
Returns: $.Promise
a jQuery promise that will be resolved with @type {Document}
    function handleDocumentOpen(commandData) {
        var result = new $.Deferred();
        handleFileOpen(commandData)
            .done(function (file) {
                // if we succeeded with an open file
                //  then we need to resolve that to a document.
                //  getOpenDocumentForPath will return null if there isn't a
                //  supporting document for that file (e.g. an image)
                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);
                result.resolve(doc);
            })
            .fail(function (err) {
                result.reject(err);
            });

        return result.promise();

    }

deprecated handleFileAddToWorkingSet

commandData non-nullable PaneCommandData
record with the following properties: fullPath: File to open; index: optional index to position in workingset (defaults to last); silent: optional flag to suppress error messages; forceRedraw: flag to force the working set view redraw; paneId: optional PaneId (defaults to active pane)
Returns: $.Promise
a jQuery promise that will be resolved with @type {File}
    function handleFileAddToWorkingSet(commandData) {
        // This is a legacy deprecated command that
        //  will use the new command and resolve with a document
        //  as the legacy command would only support.
        DeprecationWarning.deprecationWarning("Commands.FILE_ADD_TO_WORKING_SET has been deprecated.  Use Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN instead.");
        var result = new $.Deferred();

        handleFileAddToWorkingSetAndOpen(commandData)
            .done(function (file) {
                // if we succeeded with an open file
                //  then we need to resolve that to a document.
                //  getOpenDocumentForPath will return null if there isn't a
                //  supporting document for that file (e.g. an image)
                var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);
                result.resolve(doc);
            })
            .fail(function (err) {
                result.reject(err);
            });

        return result.promise();
    }

handleFileAddToWorkingSetAndOpen

Opens the given file, makes it the current file, AND adds it to the workingset

commandData non-nullable PaneCommandData
record with the following properties: fullPath: File to open; index: optional index to position in workingset (defaults to last); silent: optional flag to suppress error messages; forceRedraw: flag to force the working set view redraw; paneId: optional PaneId (defaults to active pane)
Returns: $.Promise
a jQuery promise that will be resolved with a @type {File}
    function handleFileAddToWorkingSetAndOpen(commandData) {
        return handleFileOpen(commandData).done(function (file) {
            var paneId = (commandData && commandData.paneId) || MainViewManager.ACTIVE_PANE;
            MainViewManager.addToWorkingSet(paneId, file, commandData.index, commandData.forceRedraw);
            HealthLogger.fileOpened(file.fullPath, true);
        });
    }

handleFileClose

Closes the specified file: removes it from the workingset, and closes the main editor if one is open. Prompts user about saving changes first, if document is dirty.

commandData nullable {file: File, promptOnly:boolean}
Optional bag of arguments: file - File to close; assumes the current document if not specified. promptOnly - If true, only displays the relevant confirmation UI and does NOT actually close the document. This is useful when chaining file-close together with other user prompts that may be cancelable. _forceClose - If true, closes the document without prompting even if there are unsaved changes. Only for use in unit tests.
Returns: $.Promise
a promise that is resolved when the file is closed, or if no file is open. FUTURE: should we reject the promise if no file is open?
    function handleFileClose(commandData) {
        var file,
            promptOnly,
            _forceClose,
            _spawnedRequest,
            paneId = MainViewManager.ACTIVE_PANE;

        if (commandData) {
            file        = commandData.file;
            promptOnly  = commandData.promptOnly;
            _forceClose = commandData._forceClose;
            paneId      = commandData.paneId || paneId;
            _spawnedRequest = commandData.spawnedRequest || false;
        }

        // utility function for handleFileClose: closes document & removes from workingset
        function doClose(file) {
            if (!promptOnly) {
                MainViewManager._close(paneId, file);
            }
        }

        var result = new $.Deferred(), promise = result.promise();

        // Default to current document if doc is null
        if (!file) {
            file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);
        }

        // No-op if called when nothing is open; TODO: (issue #273) should command be grayed out instead?
        if (!file) {
            result.resolve();
            return promise;
        }

        var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);

        if (doc && doc.isDirty && !_forceClose && (MainViewManager.isExclusiveToPane(doc.file, paneId) || _spawnedRequest)) {
            // Document is dirty: prompt to save changes before closing if only the document is exclusively
            // listed in the requested pane or this is part of a list close request
            var filename = FileUtils.getBaseName(doc.file.fullPath);

            Dialogs.showModalDialog(
                DefaultDialogs.DIALOG_ID_SAVE_CLOSE,
                Strings.SAVE_CLOSE_TITLE,
                StringUtils.format(
                    Strings.SAVE_CLOSE_MESSAGE,
                    StringUtils.breakableUrl(filename)
                ),
                [
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_LEFT,
                        id        : Dialogs.DIALOG_BTN_DONTSAVE,
                        text      : Strings.DONT_SAVE
                    },
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
                        id        : Dialogs.DIALOG_BTN_CANCEL,
                        text      : Strings.CANCEL
                    },
                    {
                        className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
                        id        : Dialogs.DIALOG_BTN_OK,
                        text      : Strings.SAVE
                    }
                ]
            )
                .done(function (id) {
                    if (id === Dialogs.DIALOG_BTN_CANCEL) {
                        dispatchAppQuitCancelledEvent();
                        result.reject();
                    } else if (id === Dialogs.DIALOG_BTN_OK) {
                        // "Save" case: wait until we confirm save has succeeded before closing
                        handleFileSave({doc: doc})
                            .done(function (newFile) {
                                doClose(newFile);
                                result.resolve();
                            })
                            .fail(function () {
                                result.reject();
                            });
                    } else {
                        // "Don't Save" case: even though we're closing the main editor, other views of
                        // the Document may remain in the UI. So we need to revert the Document to a clean
                        // copy of whatever's on disk.
                        doClose(file);

                        // Only reload from disk if we've executed the Close for real.
                        if (promptOnly) {
                            result.resolve();
                        } else {
                            // Even if there are no listeners attached to the document at this point, we want
                            // to do the revert anyway, because clients who are listening to the global documentChange
                            // event from the Document module (rather than attaching to the document directly),
                            // such as the Find in Files panel, should get a change event. However, in that case,
                            // we want to ignore errors during the revert, since we don't want a failed revert
                            // to throw a dialog if the document isn't actually open in the UI.
                            var suppressError = !DocumentManager.getOpenDocumentForPath(file.fullPath);
                            _doRevert(doc, suppressError)
                                .then(result.resolve, result.reject);
                        }
                    }
                });
            result.always(function () {
                MainViewManager.focusActivePane();
            });
        } else {
            // File is not open, or IS open but Document not dirty: close immediately
            doClose(file);
            MainViewManager.focusActivePane();
            result.resolve();
        }
        return promise;
    }

handleFileCloseAll

Closes all open files; equivalent to calling handleFileClose() for each document, except that unsaved changes are confirmed once, in bulk.

If nullable {promptOnly: boolean, _forceClose: boolean}
promptOnly is true, only displays the relevant confirmation UI and does NOT actually close any documents. This is useful when chaining close-all together with other user prompts that may be cancelable. If _forceClose is true, forces the files to close with no confirmation even if dirty. Should only be used for unit test cleanup.
Returns: $.Promise
a promise that is resolved when all files are closed
    function handleFileCloseAll(commandData) {
        return _closeList(MainViewManager.getAllOpenFiles(),
                                    (commandData && commandData.promptOnly), (commandData && commandData._forceClose));
    }

handleFileCloseList

Closes a list of open files; equivalent to calling handleFileClose() for each document, except that unsaved changes are confirmed once, in bulk.

If nullable {promptOnly: boolean, _forceClose: boolean}
promptOnly is true, only displays the relevant confirmation UI and does NOT actually close any documents. This is useful when chaining close-all together with other user prompts that may be cancelable. If _forceClose is true, forces the files to close with no confirmation even if dirty. Should only be used for unit test cleanup.
Returns: $.Promise
a promise that is resolved when all files are closed
    function handleFileCloseList(commandData) {
        return _closeList(commandData.fileList);
    }

handleFileCloseWindow

Confirms any unsaved changes, then closes the window

command Object
data
    function handleFileCloseWindow(commandData) {
        return _handleWindowGoingAway(
            commandData,
            function () {
                window.close();
            },
            function () {
                // if fail, tell the app to abort any pending quit operation.
                brackets.app.abortQuit();
            }
        );
    }

handleFileDelete

Delete file command handler *

    function handleFileDelete() {
        var entry = ProjectManager.getSelectedItem();
        Dialogs.showModalDialog(
            DefaultDialogs.DIALOG_ID_EXT_DELETED,
            Strings.CONFIRM_DELETE_TITLE,
            StringUtils.format(
                entry.isFile ? Strings.CONFIRM_FILE_DELETE : Strings.CONFIRM_FOLDER_DELETE,
                StringUtils.breakableUrl(entry.name)
            ),
            [
                {
                    className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
                    id        : Dialogs.DIALOG_BTN_CANCEL,
                    text      : Strings.CANCEL
                },
                {
                    className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
                    id        : Dialogs.DIALOG_BTN_OK,
                    text      : Strings.DELETE
                }
            ]
        )
            .done(function (id) {
                if (id === Dialogs.DIALOG_BTN_OK) {
                    ProjectManager.deleteItem(entry);
                }
            });
    }

handleFileNew

Create a new untitled document in the workingset, and make it the current document. Promise is resolved (synchronously) with the newly-created Document.

    function handleFileNew() {
        //var defaultExtension = PreferencesManager.get("defaultExtension");
        //if (defaultExtension) {
        //    defaultExtension = "." + defaultExtension;
        //}
        var defaultExtension = "";  // disable preference setting for now

        var doc = DocumentManager.createUntitledDocument(_nextUntitledIndexToUse++, defaultExtension);
        MainViewManager._edit(MainViewManager.ACTIVE_PANE, doc);

        return new $.Deferred().resolve(doc).promise();
    }

handleFileNewInProject

Create a new file in the project tree.

    function handleFileNewInProject() {
        _handleNewItemInProject(false);
    }

handleFileOpen

Opens the given file and makes it the current file. Does NOT add it to the workingset.

commandData optional FileCommandData
record with the following properties: fullPath: File to open; silent: optional flag to suppress error messages; paneId: optional PaneId (defaults to active pane)
Returns: $.Promise
a jQuery promise that will be resolved with a file object
    function handleFileOpen(commandData) {
        var fileInfo = _parseDecoratedPath(commandData ? commandData.fullPath : null),
            silent = (commandData && commandData.silent) || false,
            paneId = (commandData && commandData.paneId) || MainViewManager.ACTIVE_PANE,
            result = new $.Deferred();

        _doOpenWithOptionalPath(fileInfo.path, silent, paneId, commandData && commandData.options)
            .done(function (file) {
                HealthLogger.fileOpened(file._path, false, file._encoding);
                if (!commandData || !commandData.options || !commandData.options.noPaneActivate) {
                    MainViewManager.setActivePaneId(paneId);
                }

                // If a line and column number were given, position the editor accordingly.
                if (fileInfo.line !== null) {
                    if (fileInfo.column === null || (fileInfo.column <= 0)) {
                        fileInfo.column = 1;
                    }

                    // setCursorPos expects line/column numbers as 0-origin, so we subtract 1
                    EditorManager.getCurrentFullEditor().setCursorPos(fileInfo.line - 1,
                                                                      fileInfo.column - 1,
                                                                      true);
                }

                result.resolve(file);
            })
            .fail(function (err) {
                result.reject(err);
            });

        return result;
        // Testing notes: here are some recommended manual tests for handleFileOpen, on Macintosh.
        // Do all tests with brackets already running, and also with brackets not already running.
        //
        // drag a file onto brackets icon in desktop (this uses undecorated paths)
        // drag a file onto brackets icon in taskbar (this uses undecorated paths)
        // open a file from brackets sidebar (this uses undecorated paths)
        // from command line: ...../Brackets.app/Contents path         - where 'path' is undecorated
        // from command line: ...../Brackets.app path                  - where 'path' has the form "path:line"
        // from command line: ...../Brackets.app path                  - where 'path' has the form "path:line:column"
        // from command line: open -a ...../Brackets.app path          - where 'path' is undecorated
        // do "View Source" from Adobe Scout version 1.2 or newer (this will use decorated paths of the form "path:line:column")
    }

handleFileQuit

Closes the window, then quits the app

    function handleFileQuit(commandData) {
        return _handleWindowGoingAway(
            commandData,
            function () {
                brackets.app.quit();
            },
            function () {
                // if fail, don't exit: user canceled (or asked us to save changes first, but we failed to do so)
                brackets.app.abortQuit();
            }
        );
    }

handleFileRename

Show a textfield to rename whatever is currently selected in the sidebar (or current doc if nothing else selected)

    function handleFileRename() {
        // Prefer selected sidebar item (which could be a folder)
        var entry = ProjectManager.getContext();
        if (!entry) {
            // Else use current file (not selected in ProjectManager if not visible in tree or workingset)
            entry = MainViewManager.getCurrentlyViewedFile();
        }
        if (entry) {
            ProjectManager.renameItemInline(entry);
        }
    }

handleFileSave

Saves the given file. If no file specified, assumes the current document.

commandData nullable {doc: ?Document}
Document to close, or null
Returns: $.Promise
resolved with the saved document's File (which MAY DIFFER from the doc passed in, if the doc was untitled). Rejected in case of IO error (after error dialog dismissed), or if doc was untitled and the Save dialog was canceled (will be rejected with USER_CANCELED object).
    function handleFileSave(commandData) {
        var activeEditor = EditorManager.getActiveEditor(),
            activeDoc = activeEditor && activeEditor.document,
            doc = (commandData && commandData.doc) || activeDoc,
            settings;

        if (doc && !doc.isSaving) {
            if (doc.isUntitled()) {
                if (doc === activeDoc) {
                    settings = {
                        selections: activeEditor.getSelections(),
                        scrollPos: activeEditor.getScrollPos()
                    };
                }

                return _doSaveAs(doc, settings);
            } else {
                return doSave(doc);
            }
        }

        return $.Deferred().reject().promise();
    }

handleFileSaveAll

Saves all unsaved documents.

Returns: $.Promise
a promise that is resolved once ALL the saves have been completed; or rejected after all operations completed if any ONE of them failed.
    function handleFileSaveAll() {
        return saveAll();
    }

handleGoNextDoc

Next Doc command handler (MRU order) *

    function handleGoNextDoc() {
        goNextPrevDoc(+1);
    }

handleGoNextDocListOrder

Next Doc command handler (list order) *

    function handleGoNextDocListOrder() {
        goNextPrevDoc(+1, true);
    }

handleGoPrevDoc

Previous Doc command handler (MRU order) *

    function handleGoPrevDoc() {
        goNextPrevDoc(-1);
    }

handleGoPrevDocListOrder

Previous Doc command handler (list order) *

    function handleGoPrevDocListOrder() {
        goNextPrevDoc(-1, true);
    }

handleNewFolderInProject

Create a new folder in the project tree.

    function handleNewFolderInProject() {
        _handleNewItemInProject(true);
    }

handleReload

Restarts brackets Handler

loadWithoutExtensions optional boolean
true to restart without extensions, otherwise extensions are loadeed as it is durning a typical boot
    function handleReload(loadWithoutExtensions) {
        var href    = window.location.href,
            params  = new UrlParams();

        // Make sure the Reload Without User Extensions parameter is removed
        params.parse();

        if (loadWithoutExtensions) {
            if (!params.get("reloadWithoutUserExts")) {
                params.put("reloadWithoutUserExts", true);
            }
        } else {
            if (params.get("reloadWithoutUserExts")) {
                params.remove("reloadWithoutUserExts");
            }
        }

        if (href.indexOf("?") !== -1) {
            href = href.substring(0, href.indexOf("?"));
        }

        if (!params.isEmpty()) {
            href += "?" + params.toString();
        }

        // Give Mac native menus extra time to update shortcut highlighting.
        // Prevents the menu highlighting from getting messed up after reload.
        window.setTimeout(function () {
            browserReload(href);
        }, 100);
    }

handleShowInOS

Show the selected sidebar (tree or workingset) item in Finder/Explorer

    function handleShowInOS() {
        var entry = ProjectManager.getSelectedItem();
        if (entry) {
            brackets.app.showOSFolder(entry.fullPath, function (err) {
                if (err) {
                    console.error("Error showing '" + entry.fullPath + "' in OS folder:", err);
                }
            });
        }
    }

handleShowInTree

Show in File Tree command handler *

    function handleShowInTree() {
        ProjectManager.showInTree(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE));
    }

saveAll

Saves all unsaved documents. See _saveFileList() for details on the semantics.

Returns: $.Promise
    function saveAll() {
        return _saveFileList(MainViewManager.getWorkingSet(MainViewManager.ALL_PANES));
    }
Public API

showFileOpenError

Shows an error dialog indicating that the given file could not be opened due to the given error

name non-nullable FileSystemError
Returns: !Dialog
    function showFileOpenError(name, path) {
        return Dialogs.showModalDialog(
            DefaultDialogs.DIALOG_ID_ERROR,
            Strings.ERROR_OPENING_FILE_TITLE,
            StringUtils.format(
                Strings.ERROR_OPENING_FILE,
                StringUtils.breakableUrl(path),
                FileUtils.getFileErrorString(name)
            )
        );
    }