mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
Merge pull request #54951 from Microsoft/isidorn/uriLabelProvider
uriLabelProvider
This commit is contained in:
commit
db9ce80baf
114
src/vs/platform/uriDisplay/common/uriDisplay.ts
Normal file
114
src/vs/platform/uriDisplay/common/uriDisplay.ts
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { isEqual, basenameOrAuthority } from 'vs/base/common/resources';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { tildify } from 'vs/base/common/labels';
|
||||
import { ltrim } from 'vs/base/common/strings';
|
||||
|
||||
export interface IUriDisplayService {
|
||||
_serviceBrand: any;
|
||||
getLabel(resource: URI, relative: boolean): string;
|
||||
registerFormater(schema: string, formater: UriDisplayRules): IDisposable;
|
||||
}
|
||||
|
||||
export interface UriDisplayRules {
|
||||
label: string; // myLabel:/${path}
|
||||
separator: '/' | '\\' | '';
|
||||
tildify?: boolean;
|
||||
normalizeDriveLetter?: boolean;
|
||||
}
|
||||
|
||||
const URI_DISPLAY_SERVICE_ID = 'uriDisplay';
|
||||
const sepRegexp = /\//g;
|
||||
const labelMatchingRegexp = /\$\{scheme\}|\$\{authority\}|\$\{path\}/g;
|
||||
|
||||
function hasDriveLetter(path: string): boolean {
|
||||
return isWindows && path && path[2] === ':';
|
||||
}
|
||||
|
||||
export class UriDisplayService implements IUriDisplayService {
|
||||
_serviceBrand: any;
|
||||
|
||||
private formaters = new Map<string, UriDisplayRules>();
|
||||
|
||||
constructor(
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService
|
||||
) { }
|
||||
|
||||
getLabel(resource: URI, relative: boolean): string {
|
||||
if (!resource) {
|
||||
return undefined;
|
||||
}
|
||||
const formater = this.formaters.get(resource.scheme);
|
||||
if (!formater) {
|
||||
return resource.with({ query: null, fragment: null }).toString(true);
|
||||
}
|
||||
|
||||
if (relative) {
|
||||
const baseResource = this.contextService.getWorkspaceFolder(resource);
|
||||
if (baseResource) {
|
||||
let relativeLabel: string;
|
||||
if (isEqual(baseResource.uri, resource, !isLinux)) {
|
||||
relativeLabel = ''; // no label if resources are identical
|
||||
} else {
|
||||
const baseResourceLabel = this.formatUri(baseResource.uri, formater);
|
||||
relativeLabel = ltrim(this.formatUri(resource, formater).substring(baseResourceLabel.length), formater.separator);
|
||||
}
|
||||
|
||||
const hasMultipleRoots = this.contextService.getWorkspace().folders.length > 1;
|
||||
if (hasMultipleRoots) {
|
||||
const rootName = (baseResource && baseResource.name) ? baseResource.name : basenameOrAuthority(baseResource.uri);
|
||||
relativeLabel = relativeLabel ? (rootName + ' • ' + relativeLabel) : rootName; // always show root basename if there are multiple
|
||||
}
|
||||
|
||||
return relativeLabel;
|
||||
}
|
||||
}
|
||||
|
||||
return this.formatUri(resource, formater);
|
||||
}
|
||||
|
||||
registerFormater(scheme: string, formater: UriDisplayRules): IDisposable {
|
||||
this.formaters.set(scheme, formater);
|
||||
|
||||
return {
|
||||
dispose: () => this.formaters.delete(scheme)
|
||||
};
|
||||
}
|
||||
|
||||
private formatUri(resource: URI, formater: UriDisplayRules): string {
|
||||
let label = formater.label.replace(labelMatchingRegexp, match => {
|
||||
switch (match) {
|
||||
case '${scheme}': return resource.scheme;
|
||||
case '${authority}': return resource.authority;
|
||||
case '${path}': return resource.path;
|
||||
default: return '';
|
||||
}
|
||||
});
|
||||
|
||||
// convert \c:\something => C:\something
|
||||
if (formater.normalizeDriveLetter && hasDriveLetter(label)) {
|
||||
label = label.charAt(1).toUpperCase() + label.substr(2);
|
||||
}
|
||||
|
||||
if (formater.tildify) {
|
||||
label = tildify(label, this.environmentService.userHome);
|
||||
}
|
||||
|
||||
return label.replace(sepRegexp, formater.separator);
|
||||
}
|
||||
}
|
||||
|
||||
// register service
|
||||
export const IUriDisplayService = createDecorator<IUriDisplayService>(URI_DISPLAY_SERVICE_ID);
|
||||
registerSingleton(IUriDisplayService, UriDisplayService);
|
50
src/vs/platform/uriDisplay/test/uriDisplay.test.ts
Normal file
50
src/vs/platform/uriDisplay/test/uriDisplay.test.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { IUriDisplayService, UriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
|
||||
import { TestEnvironmentService, TestContextService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { nativeSep } from 'vs/base/common/paths';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
|
||||
suite('URI Display', () => {
|
||||
|
||||
let uriDisplayService: IUriDisplayService;
|
||||
|
||||
setup(() => {
|
||||
uriDisplayService = new UriDisplayService(TestEnvironmentService, new TestContextService());
|
||||
});
|
||||
|
||||
test('file scheme', function () {
|
||||
uriDisplayService.registerFormater(Schemas.file, {
|
||||
label: '${path}',
|
||||
separator: nativeSep,
|
||||
tildify: !isWindows,
|
||||
normalizeDriveLetter: isWindows
|
||||
});
|
||||
|
||||
const uri1 = TestWorkspace.folders[0].uri.with({ path: TestWorkspace.folders[0].uri.path.concat('/a/b/c/d') });
|
||||
assert.equal(uriDisplayService.getLabel(uri1, true), isWindows ? 'a\\b\\c\\d' : 'a/b/c/d');
|
||||
assert.equal(uriDisplayService.getLabel(uri1, false), isWindows ? 'C:\\testWorkspace\\a\\b\\c\\d' : '/testWorkspace/a/b/c/d');
|
||||
|
||||
const uri2 = URI.file('c:\\1/2/3');
|
||||
assert.equal(uriDisplayService.getLabel(uri2, false), isWindows ? 'C:\\1\\2\\3' : '/c:\\1/2/3');
|
||||
});
|
||||
|
||||
test('custom scheme', function () {
|
||||
uriDisplayService.registerFormater(Schemas.vscode, {
|
||||
label: 'LABEL/${path}/${authority}/END',
|
||||
separator: '/',
|
||||
tildify: true,
|
||||
normalizeDriveLetter: true
|
||||
});
|
||||
|
||||
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
|
||||
assert.equal(uriDisplayService.getLabel(uri1, false), 'LABEL//1/2/3/4/5/microsoft.com/END');
|
||||
});
|
||||
});
|
|
@ -12,7 +12,7 @@ import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/
|
|||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IEditorInputFactory, EditorInput, IFileEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions } from 'vs/workbench/common/editor';
|
||||
import { AutoSaveConfiguration, HotExitConfiguration, SUPPORTED_ENCODINGS } from 'vs/platform/files/common/files';
|
||||
import { VIEWLET_ID, SortOrderConfiguration, FILE_EDITOR_INPUT_ID } from 'vs/workbench/parts/files/common/files';
|
||||
|
@ -34,6 +34,9 @@ import { DataUriEditorInput } from 'vs/workbench/common/editor/dataUriEditorInpu
|
|||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { nativeSep } from 'vs/base/common/paths';
|
||||
|
||||
// Viewlet Action
|
||||
export class OpenExplorerViewletAction extends ToggleViewletAction {
|
||||
|
@ -50,6 +53,18 @@ export class OpenExplorerViewletAction extends ToggleViewletAction {
|
|||
}
|
||||
}
|
||||
|
||||
class FileUriDisplayContribution implements IWorkbenchContribution {
|
||||
|
||||
constructor(@IUriDisplayService uriDisplayService: IUriDisplayService) {
|
||||
uriDisplayService.registerFormater(Schemas.file, {
|
||||
label: '${path}',
|
||||
separator: nativeSep,
|
||||
tildify: !platform.isWindows,
|
||||
normalizeDriveLetter: platform.isWindows
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Register Viewlet
|
||||
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(new ViewletDescriptor(
|
||||
ExplorerViewlet,
|
||||
|
@ -156,6 +171,10 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
|||
// Register Dirty Files Tracker
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DirtyFilesTracker, LifecyclePhase.Starting);
|
||||
|
||||
// Register uri display for file uris
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(FileUriDisplayContribution, LifecyclePhase.Starting);
|
||||
|
||||
|
||||
// Configuration
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
|
||||
|
|
Loading…
Reference in a new issue