Skip to content

Commit f53a7e1

Browse files
committed
feat: add project name window title variable
Register the project name against a VS Code context key when the host supports window title variables. Keep current-project detection independent of status bar visibility and document the template.
1 parent 19970a6 commit f53a7e1

4 files changed

Lines changed: 75 additions & 28 deletions

File tree

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,14 @@ If you intend to _share_ projects between **Stable** and **Insider** installati
298298
"projectManager.showProjectNameInStatusBar": true
299299
```
300300

301+
* Display the Project Name in the Window Title (VS Code 1.93 and newer)
302+
303+
Project Manager exposes the `${projectName}` variable for use in the built-in `window.title` setting.
304+
305+
```json
306+
"window.title": "${projectName}${separator}${activeEditorShort}"
307+
```
308+
301309
* Open projects in _New Window_ when clicking in status bar (`false` by default)
302310

303311
```json

src/extension.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { registerWalkthrough } from "./commands/walkthrough";
3535
import { registerSideBarDecorations } from "./sidebar/decoration";
3636
import { ProjectNode } from "./sidebar/nodes";
3737
import { Project } from "./core/project";
38+
import { registerProjectNameWindowTitleVariable, updateProjectNameWindowTitleVariable } from "./utils/windowTitle";
3839

3940
let locators: Locators;
4041

@@ -167,6 +168,8 @@ export async function activate(context: vscode.ExtensionContext) {
167168
// introduce issues.
168169
const currentProject = showStatusBar(projectStorage, locators);
169170
Container.currentProject = currentProject;
171+
await registerProjectNameWindowTitleVariable();
172+
await updateProjectNameWindowTitleVariable(currentProject);
170173

171174
// // new place to register TreeView
172175
await providerManager.showTreeViewFromAllProviders();
@@ -319,7 +322,7 @@ export async function activate(context: vscode.ExtensionContext) {
319322
vscode.window.showInformationMessage(l10n.t("Project saved!"));
320323
if (!node) {
321324
showStatusBar(projectStorage, locators, projectName);
322-
updateCurrentProject();
325+
await updateCurrentProject();
323326
}
324327
return true;
325328
} else {
@@ -426,7 +429,7 @@ export async function activate(context: vscode.ExtensionContext) {
426429
input.show();
427430
}
428431

429-
function updateCurrentProject() {
432+
async function updateCurrentProject() {
430433
const workspace0 = vscode.workspace.workspaceFile ? vscode.workspace.workspaceFile :
431434
vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[ 0 ].uri :
432435
undefined;
@@ -439,6 +442,7 @@ export async function activate(context: vscode.ExtensionContext) {
439442
foundProject = projectStorage.existsWithRootPath(currentProjectPath, true);
440443
}
441444
Container.currentProject = foundProject;
445+
await updateProjectNameWindowTitleVariable(foundProject);
442446
}
443447

444448
async function listProjects(forceNewWindow: boolean) {
@@ -529,7 +533,7 @@ export async function activate(context: vscode.ExtensionContext) {
529533
value: oldName
530534
};
531535

532-
vscode.window.showInputBox(ibo).then(newName => {
536+
vscode.window.showInputBox(ibo).then(async newName => {
533537
if (typeof newName === "undefined" || newName === oldName) {
534538
return;
535539
}
@@ -546,6 +550,10 @@ export async function activate(context: vscode.ExtensionContext) {
546550
projectStorage.save();
547551
vscode.window.showInformationMessage(l10n.t("Project renamed!"));
548552
updateStatusBar(oldName, node.command.arguments[0], newName);
553+
if (Container.currentProject?.name.toLowerCase() === oldName.toLowerCase()) {
554+
Container.currentProject.name = newName;
555+
await updateProjectNameWindowTitleVariable(Container.currentProject);
556+
}
549557
} else {
550558
vscode.window.showErrorMessage(l10n.t("Project already exists!"));
551559
}
@@ -606,4 +614,4 @@ export async function activate(context: vscode.ExtensionContext) {
606614
export function deactivate() {
607615

608616
locators.dispose();
609-
}
617+
}

src/statusbar/statusBar.ts

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,33 @@ export function showStatusBar(projectStorage: ProjectStorage, locators: Locators
2626
undefined;
2727
const currentProjectPath = workspace0 ? workspace0.fsPath : undefined;
2828

29-
if (!showStatusConfig || !currentProjectPath) { return; }
29+
if (!currentProjectPath) { return; }
30+
31+
let foundProject: Project;
32+
if (!projectName) {
33+
if (isRemoteUri(workspace0)) {
34+
foundProject = projectStorage.existsRemoteWithRootPath(workspace0);
35+
} else {
36+
foundProject = projectStorage.existsWithRootPath(currentProjectPath, true);
37+
if (!foundProject) {
38+
foundProject = locators.vscLocator.existsWithRootPath(currentProjectPath);
39+
}
40+
if (!foundProject) {
41+
foundProject = locators.gitLocator.existsWithRootPath(currentProjectPath);
42+
}
43+
if (!foundProject) {
44+
foundProject = locators.mercurialLocator.existsWithRootPath(currentProjectPath);
45+
}
46+
if (!foundProject) {
47+
foundProject = locators.svnLocator.existsWithRootPath(currentProjectPath);
48+
}
49+
if (!foundProject) {
50+
foundProject = locators.anyLocator.existsWithRootPath(currentProjectPath);
51+
}
52+
}
53+
}
54+
55+
if (!showStatusConfig) { return foundProject; }
3056

3157
if (!statusItem) {
3258
statusItem = window.createStatusBarItem("projectManager.statusBar", StatusBarAlignment.Left);
@@ -42,34 +68,12 @@ export function showStatusBar(projectStorage: ProjectStorage, locators: Locators
4268
statusItem.command = "projectManager.listProjects";
4369
}
4470

45-
// if we have a projectName, we don't need to search.
4671
if (projectName) {
4772
statusItem.text += projectName;
4873
statusItem.show();
4974
return undefined;
5075
}
5176

52-
let foundProject: Project;
53-
if (isRemoteUri(workspace0)) {
54-
foundProject = projectStorage.existsRemoteWithRootPath(workspace0);
55-
} else {
56-
foundProject = projectStorage.existsWithRootPath(currentProjectPath, true);
57-
if (!foundProject) {
58-
foundProject = locators.vscLocator.existsWithRootPath(currentProjectPath);
59-
}
60-
if (!foundProject) {
61-
foundProject = locators.gitLocator.existsWithRootPath(currentProjectPath);
62-
}
63-
if (!foundProject) {
64-
foundProject = locators.mercurialLocator.existsWithRootPath(currentProjectPath);
65-
}
66-
if (!foundProject) {
67-
foundProject = locators.svnLocator.existsWithRootPath(currentProjectPath);
68-
}
69-
if (!foundProject) {
70-
foundProject = locators.anyLocator.existsWithRootPath(currentProjectPath);
71-
}
72-
}
7377
if (foundProject) {
7478
statusItem.text += foundProject.name;
7579
statusItem.show();
@@ -81,4 +85,4 @@ export function updateStatusBar(oldName: string, oldPath: string, newName: strin
8185
if (statusItem.text === codicons.file_directory + " " + oldName && statusItem.tooltip === oldPath) {
8286
statusItem.text = codicons.file_directory + " " + newName;
8387
}
84-
}
88+
}

src/utils/windowTitle.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Alessandro Fragnani. All rights reserved.
3+
* Licensed under the GPLv3 License. See License.md in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { commands } from "vscode";
7+
import { Project } from "../core/project";
8+
9+
const PROJECT_NAME_CONTEXT_KEY = "projectManager.projectName";
10+
const REGISTER_WINDOW_TITLE_VARIABLE_COMMAND = "registerWindowTitleVariable";
11+
12+
export async function registerProjectNameWindowTitleVariable(): Promise<void> {
13+
const availableCommands = await commands.getCommands();
14+
if (!availableCommands.includes(REGISTER_WINDOW_TITLE_VARIABLE_COMMAND)) {
15+
return;
16+
}
17+
18+
await commands.executeCommand(
19+
REGISTER_WINDOW_TITLE_VARIABLE_COMMAND,
20+
"projectName",
21+
PROJECT_NAME_CONTEXT_KEY
22+
);
23+
}
24+
25+
export async function updateProjectNameWindowTitleVariable(project?: Project): Promise<void> {
26+
await commands.executeCommand("setContext", PROJECT_NAME_CONTEXT_KEY, project?.name);
27+
}

0 commit comments

Comments
 (0)