labels.ts 4.1 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

7
import URI from 'vs/base/common/uri';
E
Erich Gamma 已提交
8 9
import platform = require('vs/base/common/platform');
import types = require('vs/base/common/types');
B
Benjamin Pasero 已提交
10 11
import { nativeSep, isEqualOrParent, normalize } from 'vs/base/common/paths';
import { endsWith, ltrim } from 'vs/base/common/strings';
E
Erich Gamma 已提交
12 13 14 15 16 17 18 19 20 21 22

export interface ILabelProvider {

	/**
	 * Given an element returns a label for it to display in the UI.
	 */
	getLabel(element: any): string;
}

export interface IWorkspaceProvider {
	getWorkspace(): {
23
		resource: URI;
B
Benjamin Pasero 已提交
24
	};
E
Erich Gamma 已提交
25 26 27 28 29
}

export class PathLabelProvider implements ILabelProvider {
	private root: string;

30
	constructor(arg1?: URI | string | IWorkspaceProvider) {
E
Erich Gamma 已提交
31 32 33
		this.root = arg1 && getPath(arg1);
	}

34
	public getLabel(arg1: URI | string | IWorkspaceProvider): string {
E
Erich Gamma 已提交
35 36 37 38
		return getPathLabel(getPath(arg1), this.root);
	}
}

39 40 41 42 43 44 45
export function getPathLabel(resource: URI | string, basePathProvider?: URI | string | IWorkspaceProvider): string {
	const absolutePath = getPath(resource);
	if (!absolutePath) {
		return null;
	}

	const basepath = basePathProvider && getPath(basePathProvider);
E
Erich Gamma 已提交
46

B
Benjamin Pasero 已提交
47
	if (basepath && isEqualOrParent(absolutePath, basepath)) {
48 49 50 51
		if (basepath === absolutePath) {
			return ''; // no label if pathes are identical
		}

B
Benjamin Pasero 已提交
52
		return normalize(ltrim(absolutePath.substr(basepath.length), nativeSep), true);
E
Erich Gamma 已提交
53 54
	}

55
	if (platform.isWindows && absolutePath && absolutePath[1] === ':') {
B
Benjamin Pasero 已提交
56
		return normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), true); // convert c:\something => C:\something
E
Erich Gamma 已提交
57 58
	}

B
Benjamin Pasero 已提交
59
	return normalize(absolutePath, true);
E
Erich Gamma 已提交
60 61
}

62
function getPath(arg1: URI | string | IWorkspaceProvider): string {
E
Erich Gamma 已提交
63 64 65 66 67 68 69 70 71
	if (!arg1) {
		return null;
	}

	if (typeof arg1 === 'string') {
		return arg1;
	}

	if (types.isFunction((<IWorkspaceProvider>arg1).getWorkspace)) {
72
		const ws = (<IWorkspaceProvider>arg1).getWorkspace();
E
Erich Gamma 已提交
73 74 75
		return ws ? ws.resource.fsPath : void 0;
	}

76
	return (<URI>arg1).fsPath;
B
Benjamin Pasero 已提交
77 78 79 80 81 82 83 84 85
}

/**
 * Shortens the paths but keeps them easy to distinguish.
 * Replaces not important parts with ellipsis.
 * Every shorten path matches only one original path and vice versa.
 */
export function shorten(paths: string[]): string[] {
	const ellipsis = '\u2026';
B
Benjamin Pasero 已提交
86
	const shortenedPaths: string[] = new Array(paths.length);
B
Benjamin Pasero 已提交
87 88

	// for every path
B
Benjamin Pasero 已提交
89 90
	let match = false;
	for (let pathIndex = 0; pathIndex < paths.length; pathIndex++) {
91
		const path = paths[pathIndex];
B
Benjamin Pasero 已提交
92 93 94
		match = true;

		// pick the first shortest subpath found
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
		if (typeof path === 'string') { // protect against paths which are not provided if any
			const segments: string[] = path.split(nativeSep);
			for (let subpathLength = 1; match && subpathLength <= segments.length; subpathLength++) {
				for (let start = segments.length - subpathLength; match && start >= 0; start--) {
					match = false;
					const subpath = segments.slice(start, start + subpathLength).join(nativeSep);

					// that is unique to any other path
					for (let otherPathIndex = 0; !match && otherPathIndex < paths.length; otherPathIndex++) {

						// suffix subpath treated specially as we consider no match 'x' and 'x/...'
						if (otherPathIndex !== pathIndex && paths[otherPathIndex].indexOf(subpath) > -1) {
							const isSubpathEnding: boolean = (start + subpathLength === segments.length);
							const isOtherPathEnding: boolean = endsWith(paths[otherPathIndex], subpath);

							match = !isSubpathEnding || isOtherPathEnding;
						}
B
Benjamin Pasero 已提交
112 113
					}

114 115 116 117 118 119
					// found unique subpath
					if (!match) {
						let result = subpath;
						if (start + subpathLength < segments.length) {
							result = result + nativeSep + ellipsis;
						}
B
Benjamin Pasero 已提交
120

121 122 123
						if (start > 0) {
							result = ellipsis + nativeSep + result;
						}
B
Benjamin Pasero 已提交
124

125 126
						shortenedPaths[pathIndex] = result;
					}
B
Benjamin Pasero 已提交
127 128 129 130 131
				}
			}
		}

		if (match) {
132
			shortenedPaths[pathIndex] = path; // use full path if no unique subpaths found
B
Benjamin Pasero 已提交
133 134 135 136
		}
	}

	return shortenedPaths;
E
Erich Gamma 已提交
137
}