ProjectModel.prototype.startRename = function (path) { path = _getPathFromFSObject(path); if (!path) { path = this._selections.context; if (!path) { return new $.Deferred().resolve().promise(); } } if (this._selections.rename && this._selections.rename.path === path) { return; } if (path !== this._selections.context) { this.setContext(path); } else { this.performRename(); } this._viewModel.moveMarker("rename", null, this.makeProjectRelativeIfPossible(path)); var d = new $.Deferred(); this._selections.rename = { deferred: d, type: FILE_RENAMING, path: path, newName: FileUtils.getBaseName(path) }; return d.promise(); };
/** * Resolves a file path to a Language object. * @param {!string} path Path to the file to find a language for * @param {?boolean} ignoreOverride If set to true will cause the lookup to ignore any * overrides and return default binding. By default override is not ignored. * * @return {Language} The language for the provided file type or the fallback language */ function getLanguageForPath(path, ignoreOverride) { var fileName, language = _filePathToLanguageMap[path], extension, parts; // if there's an override, return it if (!ignoreOverride && language) { return language; } fileName = FileUtils.getBaseName(path).toLowerCase(); language = _fileNameToLanguageMap[fileName]; // If no language was found for the file name, use the file extension instead if (!language) { // Split the file name into parts: // "foo.coffee.md" => ["foo", "coffee", "md"] // ".profile.bak" => ["", "profile", "bak"] // "1. Vacation.txt" => ["1", " Vacation", "txt"] parts = fileName.split("."); // A leading dot does not indicate a file extension, but marks the file as hidden => remove it if (parts[0] === "") { // ["", "profile", "bak"] => ["profile", "bak"] parts.shift(); } // The first part is assumed to be the title, not the extension => remove it // ["foo", "coffee", "md"] => ["coffee", "md"] // ["profile", "bak"] => ["bak"] // ["1", " Vacation", "txt"] => [" Vacation", "txt"] parts.shift(); // Join the remaining parts into a file extension until none are left or a language was found while (!language && parts.length) { // First iteration: // ["coffee", "md"] => "coffee.md" // ["bak"] => "bak" // [" Vacation", "txt"] => " Vacation.txt" // Second iteration (assuming no language was found for "coffee.md"): // ["md"] => "md" // ["txt"] => "txt" extension = parts.join("."); language = _fileExtensionToLanguageMap[extension]; // Remove the first part // First iteration: // ["coffee", "md"] => ["md"] // ["bak"] => [] // [" Vacation", "txt"] => ["txt"] // Second iteration: // ["md"] => [] // ["txt"] => [] parts.shift(); } } return language || _fallbackLanguage; }
file.unlink(function (err) { if (err) { result.reject(err); return; } ExtensionLoader.loadExtension(FileUtils.getBaseName(path), { baseUrl: path }, "main") .done(result.resolve) .fail(result.reject); });
ProjectModel.prototype.performRename = function () { var renameInfo = this._selections.rename; if (!renameInfo) { return; } var oldPath = renameInfo.path, isFolder = renameInfo.isFolder || !_pathIsFile(oldPath), oldProjectPath = this.makeProjectRelativeIfPossible(oldPath), // To get the parent directory, we need to strip off the trailing slash on a directory name parentDirectory = FileUtils.getDirectoryPath(isFolder ? FileUtils.stripTrailingSlash(oldPath) : oldPath), oldName = FileUtils.getBaseName(oldPath), newName = renameInfo.newName, newPath = parentDirectory + newName, viewModel = this._viewModel, self = this; if (renameInfo.type !== FILE_CREATING && oldName === newName) { this.cancelRename(); return; } if (isFolder) { newPath += "/"; } delete this._selections.rename; delete this._selections.context; viewModel.moveMarker("rename", oldProjectPath, null); viewModel.moveMarker("context", oldProjectPath, null); viewModel.moveMarker("creating", oldProjectPath, null); if (renameInfo.type === FILE_CREATING) { this.createAtPath(newPath).done(function (entry) { viewModel.renameItem(oldProjectPath, newName); renameInfo.deferred.resolve(entry); }).fail(function (error) { self._viewModel.deleteAtPath(self.makeProjectRelativeIfPossible(renameInfo.path)); renameInfo.deferred.reject(error); }); } else { this._renameItem(oldPath, newPath).then(function () { viewModel.renameItem(oldProjectPath, newName); renameInfo.deferred.resolve({ newPath: newPath }); }).fail(function (error) { renameInfo.deferred.reject(error); }); } };
added.forEach(function (filePath) { var isFolder = _.last(filePath) === "/"; filePath = isFolder ? filePath.substr(0, filePath.length - 1) : filePath; var parentPath = FileUtils.getDirectoryPath(filePath), parentObjectPath = _filePathToObjectPath(treeData, parentPath), basename = FileUtils.getBaseName(filePath); if (parentObjectPath) { treeData = _createPlaceholder(treeData, parentPath, basename, isFolder, { notInCreateMode: true, doNotOpen: true }); } });
ProjectModel.prototype.createAtPath = function (path) { var isFolder = !_pathIsFile(path), name = FileUtils.getBaseName(path), self = this; return doCreate(path, isFolder).done(function (entry) { if (!isFolder) { self.selectInWorkingSet(entry.fullPath); } }).fail(function (error) { self.trigger(ERROR_CREATION, { type: error, name: name, isFolder: isFolder }); }); };
ProjectModel.prototype.startRename = function (path) { var d = new $.Deferred(); path = _getPathFromFSObject(path); if (!path) { path = this._selections.context; if (!path) { return d.resolve().promise(); } } if (this._selections.rename && this._selections.rename.path === path) { return; } if (!this.isWithinProject(path)) { return d.reject({ type: ERROR_NOT_IN_PROJECT, isFolder: !_pathIsFile(path), fullPath: path }).promise(); } var projectRelativePath = this.makeProjectRelativeIfPossible(path); if (!this._viewModel.isFilePathVisible(projectRelativePath)) { this.showInTree(path); } if (path !== this._selections.context) { this.setContext(path); } else { this.performRename(); } this._viewModel.moveMarker("rename", null, projectRelativePath); this._selections.rename = { deferred: d, type: FILE_RENAMING, path: path, newName: FileUtils.getBaseName(path) }; return d.promise(); };
/** * Rename a file/folder. This will update the project tree data structures * and send notifications about the rename. * * @param {string} oldName Old item name * @param {string} newName New item name * @param {boolean} isFolder True if item is a folder; False if it is a file. * @return {$.Promise} A promise object that will be resolved or rejected when * the rename is finished. */ function _renameItem(oldName, newName, isFolder) { var result = new $.Deferred(); if (oldName === newName) { result.resolve(); } else if (!isValidFilename(FileUtils.getBaseName(newName), _invalidChars)) { result.reject(ERROR_INVALID_FILENAME); } else { var entry = isFolder ? FileSystem.getDirectoryForPath(oldName) : FileSystem.getFileForPath(oldName); entry.rename(newName, function (err) { if (err) { result.reject(err); } else { result.resolve(); } }); } return result.promise(); }
/** * Get the file extension (excluding ".") given a path OR a bare filename. * Returns "" for names with no extension. * If the only `.` in the file is the first character, * returns "" as this is not considered an extension. * This method considers known extensions which include `.` in them. * * @param {string} fullPath full path to a file or directory * @return {string} Returns the extension of a filename or empty string if * the argument is a directory or a filename with no extension */ function getCompoundFileExtension(fullPath) { var baseName = FileUtils.getBaseName(fullPath), parts = baseName.split("."); // get rid of file name parts.shift(); if (baseName[0] === ".") { // if starts with a `.`, then still consider it as file name parts.shift(); } var extension = [parts.pop()], // last part is always an extension i = parts.length; while (i--) { if (getLanguageForExtension(parts[i])) { extension.unshift(parts[i]); } else { break; } } return extension.join("."); }
/** * Creates a new file or folder at the given path. The returned promise is rejected if the filename * is invalid, the new path already exists or some other filesystem error comes up. * * @param {string} path path to create * @param {boolean} isFolder true if the new entry is a folder * @return {$.Promise} resolved when the file or directory has been created. */ function doCreate(path, isFolder) { var d = new $.Deferred(); var name = FileUtils.getBaseName(path); if (!isValidFilename(name, _invalidChars)) { return d.reject(ERROR_INVALID_FILENAME).promise(); } FileSystem.resolve(path, function (err) { if (!err) { // Item already exists, fail with error d.reject(FileSystemError.ALREADY_EXISTS); } else { if (isFolder) { var directory = FileSystem.getDirectoryForPath(path); directory.create(function (err) { if (err) { d.reject(err); } else { d.resolve(directory); } }); } else { // Create an empty file var file = FileSystem.getFileForPath(path); FileUtils.writeText(file, "").then(function () { d.resolve(file); }, d.reject); } } }); return d.promise(); }
searchFiles.some(function (fullPath) { showMatches = true; item = searchResults[fullPath]; // Since the amount of matches on this item plus the amount of matches we skipped until // now is still smaller than the first match that we want to display, skip these. if (matchesCounter + item.matches.length < currentStart) { matchesCounter += item.matches.length; showMatches = false; // If we still haven't skipped enough items to get to the first match, but adding the // item matches to the skipped ones is greater the the first match we want to display, // then we can display the matches from this item skipping the first ones } else if (matchesCounter < currentStart) { i = currentStart - matchesCounter; matchesCounter = currentStart; // If we already skipped enough matches to get to the first match to display, we can start // displaying from the first match of this item } else if (matchesCounter < last) { i = 0; // We can't display more items by now. Break the loop } else { return true; } if (showMatches && i < item.matches.length) { // Add a row for each match in the file searchItems = []; // Add matches until we get to the last match of this item, or filling the page while (i < item.matches.length && matchesCounter < last) { match = item.matches[i]; searchItems.push({ file: searchList.length, item: searchItems.length, line: match.start.line + 1, pre: match.line.substr(0, match.start.ch), highlight: match.line.substring(match.start.ch, match.end.ch), post: match.line.substr(match.end.ch), start: match.start, end: match.end }); matchesCounter++; i++; } // Add a row for each file var relativePath = FileUtils.getDirectoryPath(ProjectManager.makeProjectRelativeIfPossible(fullPath)), directoryPath = FileUtils.getDirectoryPath(relativePath), displayFileName = StringUtils.format( Strings.FIND_IN_FILES_FILE_PATH, StringUtils.breakableUrl(FileUtils.getBaseName(fullPath)), StringUtils.breakableUrl(directoryPath), directoryPath ? "—" : "" ); searchList.push({ file: searchList.length, filename: displayFileName, fullPath: fullPath, items: searchItems }); } });
it("should get the file name of a posix file path", function () { expect(FileUtils.getBaseName("/foo/bar/baz.txt")).toBe("baz.txt"); });
it("should get the file name of a normalized win file path", function () { expect(FileUtils.getBaseName("C:/foo/bar/baz.txt")).toBe("baz.txt"); });
it("should return the directory name of a path containing #", function () { expect(FileUtils.getBaseName("C:/foo/bar/#baz/jaz/")).toBe("jaz"); expect(FileUtils.getBaseName("C:/foo/bar/baz/#jaz/")).toBe("#jaz"); });
it("should return the directory name of a posix directory path", function () { expect(FileUtils.getBaseName("C:/foo/bar/")).toBe("bar"); });