Skip to content

Commit c47c001

Browse files
committed
move labelService to workbench
1 parent 6ac72bd commit c47c001

7 files changed

Lines changed: 192 additions & 167 deletions

File tree

build/lib/i18n.resources.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@
238238
"name": "vs/workbench/services/decorations",
239239
"project": "vscode-workbench"
240240
},
241+
{
242+
"name": "vs/workbench/services/label",
243+
"project": "vscode-workbench"
244+
},
241245
{
242246
"name": "vs/workbench/services/preferences",
243247
"project": "vscode-preferences"

src/vs/platform/label/common/label.ts

Lines changed: 6 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,15 @@
55

66
import { URI } from 'vs/base/common/uri';
77
import { IDisposable } from 'vs/base/common/lifecycle';
8-
import { Event, Emitter } from 'vs/base/common/event';
9-
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
10-
import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace';
8+
import { Event } from 'vs/base/common/event';
9+
import { IWorkspace } from 'vs/platform/workspace/common/workspace';
1110
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
12-
import { isEqual, basenameOrAuthority } from 'vs/base/common/resources';
13-
import { isLinux, isWindows } from 'vs/base/common/platform';
14-
import { tildify, getPathLabel } from 'vs/base/common/labels';
15-
import { ltrim, startsWith } from 'vs/base/common/strings';
16-
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, WORKSPACE_EXTENSION, toWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
11+
import { basenameOrAuthority } from 'vs/base/common/resources';
12+
import { isLinux } from 'vs/base/common/platform';
13+
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces';
1714
import { localize } from 'vs/nls';
1815
import { isParent } from 'vs/platform/files/common/files';
19-
import { basename, dirname, join } from 'vs/base/common/paths';
20-
import { Schemas } from 'vs/base/common/network';
21-
import { IWindowService } from 'vs/platform/windows/common/windows';
22-
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
16+
import { basename } from 'vs/base/common/paths';
2317

2418
export interface RegisterFormatterData {
2519
selector: string;
@@ -54,12 +48,6 @@ export interface LabelRules {
5448
}
5549

5650
const LABEL_SERVICE_ID = 'label';
57-
const sepRegexp = /\//g;
58-
const labelMatchingRegexp = /\$\{scheme\}|\$\{authority\}|\$\{path\}/g;
59-
60-
function hasDriveLetter(path: string): boolean {
61-
return !!(isWindows && path && path[2] === ':');
62-
}
6351

6452
export function getSimpleWorkspaceLabel(workspace: IWorkspaceIdentifier | URI, workspaceHome: string): string {
6553
if (isSingleFolderWorkspaceIdentifier(workspace)) {
@@ -75,150 +63,5 @@ export function getSimpleWorkspaceLabel(workspace: IWorkspaceIdentifier | URI, w
7563
return localize('workspaceName', "{0} (Workspace)", workspaceName);
7664
}
7765

78-
export class LabelService implements ILabelService {
79-
_serviceBrand: any;
80-
81-
private readonly formatters: { [prefix: string]: LabelRules } = Object.create(null);
82-
private readonly _onDidRegisterFormatter = new Emitter<RegisterFormatterData>();
83-
84-
constructor(
85-
@IEnvironmentService private readonly environmentService: IEnvironmentService,
86-
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
87-
@IWindowService private readonly windowService: IWindowService
88-
) { }
89-
90-
get onDidRegisterFormatter(): Event<RegisterFormatterData> {
91-
return this._onDidRegisterFormatter.event;
92-
}
93-
94-
findFormatter(resource: URI): LabelRules | undefined {
95-
const path = `${resource.scheme}://${resource.authority}`;
96-
let bestPrefix = '';
97-
for (let prefix in this.formatters) {
98-
if (startsWith(path, prefix) && prefix.length > bestPrefix.length) {
99-
bestPrefix = prefix;
100-
}
101-
}
102-
if (bestPrefix.length) {
103-
return this.formatters[bestPrefix];
104-
}
105-
return undefined;
106-
}
107-
108-
getUriLabel(resource: URI, options: { relative?: boolean, noPrefix?: boolean } = {}): string {
109-
const formatter = this.findFormatter(resource);
110-
if (!formatter) {
111-
return getPathLabel(resource.path, this.environmentService, options.relative ? this.contextService : undefined);
112-
}
113-
114-
if (options.relative) {
115-
const baseResource = this.contextService && this.contextService.getWorkspaceFolder(resource);
116-
if (baseResource) {
117-
let relativeLabel: string;
118-
if (isEqual(baseResource.uri, resource, !isLinux)) {
119-
relativeLabel = ''; // no label if resources are identical
120-
} else {
121-
const baseResourceLabel = this.formatUri(baseResource.uri, formatter, options.noPrefix);
122-
relativeLabel = ltrim(this.formatUri(resource, formatter, options.noPrefix).substring(baseResourceLabel.length), formatter.uri.separator);
123-
}
124-
125-
const hasMultipleRoots = this.contextService.getWorkspace().folders.length > 1;
126-
if (hasMultipleRoots && !options.noPrefix) {
127-
const rootName = (baseResource && baseResource.name) ? baseResource.name : basenameOrAuthority(baseResource.uri);
128-
relativeLabel = relativeLabel ? (rootName + ' • ' + relativeLabel) : rootName; // always show root basename if there are multiple
129-
}
130-
131-
return relativeLabel;
132-
}
133-
}
134-
135-
return this.formatUri(resource, formatter, options.noPrefix);
136-
}
137-
138-
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWorkspace), options?: { verbose: boolean }): string {
139-
if (!isWorkspaceIdentifier(workspace) && !isSingleFolderWorkspaceIdentifier(workspace)) {
140-
const identifier = toWorkspaceIdentifier(workspace);
141-
if (!identifier) {
142-
return '';
143-
}
144-
145-
workspace = identifier;
146-
}
147-
148-
// Workspace: Single Folder
149-
if (isSingleFolderWorkspaceIdentifier(workspace)) {
150-
// Folder on disk
151-
const formatter = this.findFormatter(workspace);
152-
const label = options && options.verbose ? this.getUriLabel(workspace) : basenameOrAuthority(workspace);
153-
if (workspace.scheme === Schemas.file) {
154-
return label;
155-
}
156-
157-
const suffix = formatter && formatter.workspace && (typeof formatter.workspace.suffix === 'string') ? formatter.workspace.suffix : workspace.scheme;
158-
return suffix ? `${label} (${suffix})` : label;
159-
}
160-
161-
// Workspace: Untitled
162-
if (isParent(workspace.configPath, this.environmentService.workspacesHome, !isLinux /* ignore case */)) {
163-
return localize('untitledWorkspace', "Untitled (Workspace)");
164-
}
165-
166-
// Workspace: Saved
167-
const filename = basename(workspace.configPath);
168-
const workspaceName = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1);
169-
if (options && options.verbose) {
170-
return localize('workspaceNameVerbose', "{0} (Workspace)", this.getUriLabel(URI.file(join(dirname(workspace.configPath), workspaceName))));
171-
}
172-
173-
return localize('workspaceName', "{0} (Workspace)", workspaceName);
174-
}
175-
176-
getHostLabel(): string {
177-
if (this.windowService) {
178-
const authority = this.windowService.getConfiguration().remoteAuthority;
179-
if (authority) {
180-
const formatter = this.findFormatter(URI.from({ scheme: REMOTE_HOST_SCHEME, authority }));
181-
if (formatter && formatter.workspace) {
182-
return formatter.workspace.suffix;
183-
}
184-
}
185-
}
186-
return '';
187-
}
188-
189-
registerFormatter(selector: string, formatter: LabelRules): IDisposable {
190-
this.formatters[selector] = formatter;
191-
this._onDidRegisterFormatter.fire({ selector, formatter });
192-
193-
return {
194-
dispose: () => delete this.formatters[selector]
195-
};
196-
}
197-
198-
private formatUri(resource: URI, formatter: LabelRules, forceNoTildify?: boolean): string {
199-
let label = formatter.uri.label.replace(labelMatchingRegexp, match => {
200-
switch (match) {
201-
case '${scheme}': return resource.scheme;
202-
case '${authority}': return resource.authority;
203-
case '${path}': return resource.path;
204-
default: return '';
205-
}
206-
});
207-
208-
// convert \c:\something => C:\something
209-
if (formatter.uri.normalizeDriveLetter && hasDriveLetter(label)) {
210-
label = label.charAt(1).toUpperCase() + label.substr(2);
211-
}
212-
213-
if (formatter.uri.tildify && !forceNoTildify) {
214-
label = tildify(label, this.environmentService.userHome);
215-
}
216-
if (formatter.uri.authorityPrefix && resource.authority) {
217-
label = formatter.uri.authorityPrefix + label;
218-
}
219-
220-
return label.replace(sepRegexp, formatter.uri.separator);
221-
}
222-
}
22366

22467
export const ILabelService = createDecorator<ILabelService>(LABEL_SERVICE_ID);

src/vs/workbench/electron-browser/shell.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ import { SearchHistoryService } from 'vs/workbench/services/search/node/searchHi
9696
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
9797
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
9898
import { LogLevelSetterChannel } from 'vs/platform/log/node/logIpc';
99-
import { ILabelService, LabelService } from 'vs/platform/label/common/label';
99+
import { ILabelService } from 'vs/platform/label/common/label';
100100
import { IDownloadService } from 'vs/platform/download/common/download';
101101
import { DownloadService } from 'vs/platform/download/node/downloadService';
102102
import { DownloadServiceChannel } from 'vs/platform/download/node/downloadIpc';
@@ -106,6 +106,7 @@ import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remot
106106
import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-browser/remoteAuthorityResolverService';
107107
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
108108
import { MarkerDecorationsService } from 'vs/editor/common/services/markerDecorationsServiceImpl';
109+
import { LabelService } from 'vs/workbench/services/label/common/labelService';
109110

110111
/**
111112
* Services that we require for the Shell
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { localize } from 'vs/nls';
7+
import { URI } from 'vs/base/common/uri';
8+
import { IDisposable } from 'vs/base/common/lifecycle';
9+
import { Event, Emitter } from 'vs/base/common/event';
10+
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
11+
import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace';
12+
import { isEqual, basenameOrAuthority } from 'vs/base/common/resources';
13+
import { isLinux, isWindows } from 'vs/base/common/platform';
14+
import { tildify, getPathLabel } from 'vs/base/common/labels';
15+
import { ltrim, startsWith } from 'vs/base/common/strings';
16+
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, WORKSPACE_EXTENSION, toWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
17+
import { isParent } from 'vs/platform/files/common/files';
18+
import { basename, dirname, join } from 'vs/base/common/paths';
19+
import { Schemas } from 'vs/base/common/network';
20+
import { IWindowService } from 'vs/platform/windows/common/windows';
21+
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
22+
import { ILabelService, LabelRules, RegisterFormatterData } from 'vs/platform/label/common/label';
23+
24+
const sepRegexp = /\//g;
25+
const labelMatchingRegexp = /\$\{scheme\}|\$\{authority\}|\$\{path\}/g;
26+
27+
function hasDriveLetter(path: string): boolean {
28+
return !!(isWindows && path && path[2] === ':');
29+
}
30+
31+
32+
export class LabelService implements ILabelService {
33+
_serviceBrand: any;
34+
35+
private readonly formatters: { [prefix: string]: LabelRules } = Object.create(null);
36+
private readonly _onDidRegisterFormatter = new Emitter<RegisterFormatterData>();
37+
38+
constructor(
39+
@IEnvironmentService private readonly environmentService: IEnvironmentService,
40+
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
41+
@IWindowService private readonly windowService: IWindowService
42+
) { }
43+
44+
get onDidRegisterFormatter(): Event<RegisterFormatterData> {
45+
return this._onDidRegisterFormatter.event;
46+
}
47+
48+
findFormatter(resource: URI): LabelRules | undefined {
49+
const path = `${resource.scheme}://${resource.authority}`;
50+
let bestPrefix = '';
51+
for (let prefix in this.formatters) {
52+
if (startsWith(path, prefix) && prefix.length > bestPrefix.length) {
53+
bestPrefix = prefix;
54+
}
55+
}
56+
if (bestPrefix.length) {
57+
return this.formatters[bestPrefix];
58+
}
59+
return undefined;
60+
}
61+
62+
getUriLabel(resource: URI, options: { relative?: boolean, noPrefix?: boolean } = {}): string {
63+
const formatter = this.findFormatter(resource);
64+
if (!formatter) {
65+
return getPathLabel(resource.path, this.environmentService, options.relative ? this.contextService : undefined);
66+
}
67+
68+
if (options.relative) {
69+
const baseResource = this.contextService && this.contextService.getWorkspaceFolder(resource);
70+
if (baseResource) {
71+
let relativeLabel: string;
72+
if (isEqual(baseResource.uri, resource, !isLinux)) {
73+
relativeLabel = ''; // no label if resources are identical
74+
} else {
75+
const baseResourceLabel = this.formatUri(baseResource.uri, formatter, options.noPrefix);
76+
relativeLabel = ltrim(this.formatUri(resource, formatter, options.noPrefix).substring(baseResourceLabel.length), formatter.uri.separator);
77+
}
78+
79+
const hasMultipleRoots = this.contextService.getWorkspace().folders.length > 1;
80+
if (hasMultipleRoots && !options.noPrefix) {
81+
const rootName = (baseResource && baseResource.name) ? baseResource.name : basenameOrAuthority(baseResource.uri);
82+
relativeLabel = relativeLabel ? (rootName + ' • ' + relativeLabel) : rootName; // always show root basename if there are multiple
83+
}
84+
85+
return relativeLabel;
86+
}
87+
}
88+
89+
return this.formatUri(resource, formatter, options.noPrefix);
90+
}
91+
92+
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWorkspace), options?: { verbose: boolean }): string {
93+
if (!isWorkspaceIdentifier(workspace) && !isSingleFolderWorkspaceIdentifier(workspace)) {
94+
const identifier = toWorkspaceIdentifier(workspace);
95+
if (!identifier) {
96+
return '';
97+
}
98+
99+
workspace = identifier;
100+
}
101+
102+
// Workspace: Single Folder
103+
if (isSingleFolderWorkspaceIdentifier(workspace)) {
104+
// Folder on disk
105+
const formatter = this.findFormatter(workspace);
106+
const label = options && options.verbose ? this.getUriLabel(workspace) : basenameOrAuthority(workspace);
107+
if (workspace.scheme === Schemas.file) {
108+
return label;
109+
}
110+
111+
const suffix = formatter && formatter.workspace && (typeof formatter.workspace.suffix === 'string') ? formatter.workspace.suffix : workspace.scheme;
112+
return suffix ? `${label} (${suffix})` : label;
113+
}
114+
115+
// Workspace: Untitled
116+
if (isParent(workspace.configPath, this.environmentService.workspacesHome, !isLinux /* ignore case */)) {
117+
return localize('untitledWorkspace', "Untitled (Workspace)");
118+
}
119+
120+
// Workspace: Saved
121+
const filename = basename(workspace.configPath);
122+
const workspaceName = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1);
123+
if (options && options.verbose) {
124+
return localize('workspaceNameVerbose', "{0} (Workspace)", this.getUriLabel(URI.file(join(dirname(workspace.configPath), workspaceName))));
125+
}
126+
127+
return localize('workspaceName', "{0} (Workspace)", workspaceName);
128+
}
129+
130+
getHostLabel(): string {
131+
if (this.windowService) {
132+
const authority = this.windowService.getConfiguration().remoteAuthority;
133+
if (authority) {
134+
const formatter = this.findFormatter(URI.from({ scheme: REMOTE_HOST_SCHEME, authority }));
135+
if (formatter && formatter.workspace) {
136+
return formatter.workspace.suffix;
137+
}
138+
}
139+
}
140+
return '';
141+
}
142+
143+
registerFormatter(selector: string, formatter: LabelRules): IDisposable {
144+
this.formatters[selector] = formatter;
145+
this._onDidRegisterFormatter.fire({ selector, formatter });
146+
147+
return {
148+
dispose: () => delete this.formatters[selector]
149+
};
150+
}
151+
152+
private formatUri(resource: URI, formatter: LabelRules, forceNoTildify?: boolean): string {
153+
let label = formatter.uri.label.replace(labelMatchingRegexp, match => {
154+
switch (match) {
155+
case '${scheme}': return resource.scheme;
156+
case '${authority}': return resource.authority;
157+
case '${path}': return resource.path;
158+
default: return '';
159+
}
160+
});
161+
162+
// convert \c:\something => C:\something
163+
if (formatter.uri.normalizeDriveLetter && hasDriveLetter(label)) {
164+
label = label.charAt(1).toUpperCase() + label.substr(2);
165+
}
166+
167+
if (formatter.uri.tildify && !forceNoTildify) {
168+
label = tildify(label, this.environmentService.userHome);
169+
}
170+
if (formatter.uri.authorityPrefix && resource.authority) {
171+
label = formatter.uri.authorityPrefix + label;
172+
}
173+
174+
return label.replace(sepRegexp, formatter.uri.separator);
175+
}
176+
}

0 commit comments

Comments
 (0)