diff --git a/extensions/configuration-editing/src/settingsDocumentHelper.ts b/extensions/configuration-editing/src/settingsDocumentHelper.ts index b8f9c16fca6..dc4c47ac129 100644 --- a/extensions/configuration-editing/src/settingsDocumentHelper.ts +++ b/extensions/configuration-editing/src/settingsDocumentHelper.ts @@ -46,8 +46,10 @@ export class SettingsDocument { completions.push(this.newSimpleCompletionItem('${activeEditorShort}', range, localize('activeEditorShort', "e.g. myFile.txt"))); completions.push(this.newSimpleCompletionItem('${activeEditorMedium}', range, localize('activeEditorMedium', "e.g. myFolder/myFile.txt"))); completions.push(this.newSimpleCompletionItem('${activeEditorLong}', range, localize('activeEditorLong', "e.g. /Users/Development/myProject/myFolder/myFile.txt"))); - completions.push(this.newSimpleCompletionItem('${rootName}', range, localize('rootName', "e.g. myProject"))); + completions.push(this.newSimpleCompletionItem('${rootName}', range, localize('rootName', "e.g. myFolder1, myFolder2, myFolder3"))); completions.push(this.newSimpleCompletionItem('${rootPath}', range, localize('rootPath', "e.g. /Users/Development/myProject"))); + completions.push(this.newSimpleCompletionItem('${folderName}', range, localize('folderName', "e.g. myFolder"))); + completions.push(this.newSimpleCompletionItem('${folderPath}', range, localize('folderPath', "e.g. /Users/Development/myFolder"))); completions.push(this.newSimpleCompletionItem('${appName}', range, localize('appName', "e.g. VS Code"))); completions.push(this.newSimpleCompletionItem('${dirty}', range, localize('dirty', "a dirty indicator if the active editor is dirty"))); completions.push(this.newSimpleCompletionItem('${separator}', range, localize('separator', "a conditional separator (' - ') that only shows when surrounded by variables with values"))); diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 2ee481c2bb8..0c5daf8472f 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -163,6 +163,10 @@ export class Workspace implements IWorkspace { } public getRoot(resource: URI): URI { + if (!resource) { + return null; + } + return this._rootsMap.findSubstr(resource.fsPath); } diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 2298b18f4b1..7d3de6cb827 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -25,12 +25,13 @@ import { IEditorGroupService } from 'vs/workbench/services/group/common/groupSer import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import nls = require('vs/nls'); import * as labels from 'vs/base/common/labels'; -import { EditorInput } from 'vs/workbench/common/editor'; +import { EditorInput, toResource } from 'vs/workbench/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Verbosity } from 'vs/platform/editor/common/editor'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TITLE_BAR_ACTIVE_BACKGROUND, TITLE_BAR_ACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_BACKGROUND } from 'vs/workbench/common/theme'; +import URI from "vs/base/common/uri"; export class TitlebarPart extends Part implements ITitleService { @@ -52,7 +53,6 @@ export class TitlebarPart extends Part implements ITitleService { private titleTemplate: string; private isPure: boolean; private activeEditorListeners: IDisposable[]; - private workspacePath: string; constructor( id: string, @@ -71,7 +71,6 @@ export class TitlebarPart extends Part implements ITitleService { this.isPure = true; this.activeEditorListeners = []; - this.computeWorkspacePath(); this.init(); @@ -114,19 +113,9 @@ export class TitlebarPart extends Part implements ITitleService { } private onDidChangeWorkspaceRoots(): void { - this.computeWorkspacePath(); this.setTitle(this.getWindowTitle()); } - private computeWorkspacePath(): void { - const workspace = this.contextService.getWorkspace2(); - if (workspace && workspace.roots.length === 1) { - this.workspacePath = labels.getPathLabel(workspace.roots[0], void 0, this.environmentService); - } else { - this.workspacePath = ''; - } - } - private onConfigurationChanged(update?: boolean): void { const currentTitleTemplate = this.titleTemplate; this.titleTemplate = this.configurationService.lookup('window.title').value; @@ -184,8 +173,10 @@ export class TitlebarPart extends Part implements ITitleService { * {activeEditorLong}: e.g. /Users/Development/myProject/myFolder/myFile.txt * {activeEditorMedium}: e.g. myFolder/myFile.txt * {activeEditorShort}: e.g. myFile.txt - * {rootName}: e.g. myProject + * {rootName}: e.g. myFolder1, myFolder2, myFolder3 * {rootPath}: e.g. /Users/Development/myProject + * {folderName}: e.g. myFolder + * {folderPath}: e.g. /Users/Development/myFolder * {appName}: e.g. VS Code * {dirty}: indiactor * {separator}: conditional separator @@ -194,12 +185,36 @@ export class TitlebarPart extends Part implements ITitleService { const input = this.editorService.getActiveEditorInput(); const workspace = this.contextService.getWorkspace2(); + // Compute root resource + // Single Root Workspace: always the single root workspace in this case + // Multi Root Workspace: not yet defined (TODO@Ben multi root) + let root: URI; + if (workspace) { + if (workspace.roots.length === 1) { + root = workspace.roots[0]; + } + } + + // Compute folder resource + // Single Root Workspace: always the root single workspace in this case + // Multi Root Workspace: root folder of the currently active file if any + let folder: URI; + if (workspace) { + if (workspace.roots.length === 1) { + folder = workspace.roots[0]; + } else { + folder = this.contextService.getRoot(toResource(input, { supportSideBySide: true, filter: 'file' })); + } + } + // Variables const activeEditorShort = input ? input.getTitle(Verbosity.SHORT) : ''; const activeEditorMedium = input ? input.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = input ? input.getTitle(Verbosity.LONG) : activeEditorMedium; const rootName = workspace ? workspace.name : ''; - const rootPath = workspace ? this.workspacePath : ''; + const rootPath = workspace ? labels.getPathLabel(root, void 0, this.environmentService) : ''; + const folderName = folder ? (paths.basename(folder.fsPath) || folder.fsPath) : ''; + const folderPath = folder ? labels.getPathLabel(folder, void 0, this.environmentService) : ''; const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; const appName = this.environmentService.appNameLong; const separator = TitlebarPart.TITLE_SEPARATOR; @@ -210,6 +225,8 @@ export class TitlebarPart extends Part implements ITitleService { activeEditorMedium, rootName, rootPath, + folderName, + folderPath, dirty, appName, separator: { label: separator } diff --git a/src/vs/workbench/electron-browser/main.contribution.ts b/src/vs/workbench/electron-browser/main.contribution.ts index 8cb6e97a195..3013ffa94fc 100644 --- a/src/vs/workbench/electron-browser/main.contribution.ts +++ b/src/vs/workbench/electron-browser/main.contribution.ts @@ -251,14 +251,16 @@ Note that there can still be cases where this setting is ignored (e.g. when usin }, 'window.title': { 'type': 'string', - 'default': isMacintosh ? '${activeEditorShort}${separator}${rootName}' : '${dirty}${activeEditorShort}${separator}${rootName}${separator}${appName}', + 'default': isMacintosh ? '${activeEditorShort}${separator}${folderName}' : '${dirty}${activeEditorShort}${separator}${folderName}${separator}${appName}', 'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by parenthesis are not to be translated.'], key: 'title' }, `Controls the window title based on the active editor. Variables are substituted based on the context: \${activeEditorShort}: e.g. myFile.txt \${activeEditorMedium}: e.g. myFolder/myFile.txt \${activeEditorLong}: e.g. /Users/Development/myProject/myFolder/myFile.txt -\${rootName}: e.g. myProject -\${rootPath}: e.g. /Users/Development/myProject +\${folderName}: e.g. myFolder +\${folderPath}: e.g. /Users/Development/myFolder +\${rootName}: e.g. myFolder1, myFolder2, myFolder3 +\${rootPath}: e.g. /Users/Development/myWorkspace \${appName}: e.g. VS Code \${dirty}: a dirty indicator if the active editor is dirty \${separator}: a conditional separator (" - ") that only shows when surrounded by variables with values`)