From 04fcbabb358b8e5bc95057af8754e9b3d7bd5666 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 13 Jan 2017 16:35:41 +0100 Subject: [PATCH] :lipstick: --- src/vs/base/common/labels.ts | 66 +++++++++++++++++-- src/vs/base/common/paths.ts | 55 ---------------- src/vs/base/test/common/labels.test.ts | 50 ++++++++++++++ src/vs/base/test/common/paths.test.ts | 40 ----------- .../browser/parts/editor/tabsTitleControl.ts | 4 +- 5 files changed, 112 insertions(+), 103 deletions(-) create mode 100644 src/vs/base/test/common/labels.test.ts diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 04858fafbf3..c307b3cd876 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -7,8 +7,8 @@ import URI from 'vs/base/common/uri'; import platform = require('vs/base/common/platform'); import types = require('vs/base/common/types'); -import strings = require('vs/base/common/strings'); -import paths = require('vs/base/common/paths'); +import { nativeSep, isEqualOrParent, normalize } from 'vs/base/common/paths'; +import { endsWith, ltrim } from 'vs/base/common/strings'; export interface ILabelProvider { @@ -44,19 +44,19 @@ export function getPathLabel(resource: URI | string, basePathProvider?: URI | st const basepath = basePathProvider && getPath(basePathProvider); - if (basepath && paths.isEqualOrParent(absolutePath, basepath)) { + if (basepath && isEqualOrParent(absolutePath, basepath)) { if (basepath === absolutePath) { return ''; // no label if pathes are identical } - return paths.normalize(strings.ltrim(absolutePath.substr(basepath.length), paths.nativeSep), true); + return normalize(ltrim(absolutePath.substr(basepath.length), nativeSep), true); } if (platform.isWindows && absolutePath && absolutePath[1] === ':') { - return paths.normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), true); // convert c:\something => C:\something + return normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), true); // convert c:\something => C:\something } - return paths.normalize(absolutePath, true); + return normalize(absolutePath, true); } function getPath(arg1: URI | string | IWorkspaceProvider): string { @@ -74,4 +74,58 @@ function getPath(arg1: URI | string | IWorkspaceProvider): string { } return (arg1).fsPath; +} + +/** + * 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'; + let shortenedPaths: string[] = new Array(paths.length); + let match = false; + + // for every path + for (let path = 0; path < paths.length; path++) { + let segments: string[] = paths[path].split(nativeSep); + match = true; + + // pick the first shortest subpath found + for (let subpathLength = 1; match && subpathLength <= segments.length; subpathLength++) { + for (let start = segments.length - subpathLength; match && start >= 0; start--) { + match = false; + let subpath = segments.slice(start, start + subpathLength).join(nativeSep); + + // that is unique to any other path + for (let otherPath = 0; !match && otherPath < paths.length; otherPath++) { + if (otherPath !== path && paths[otherPath].indexOf(subpath) > -1) { + // suffix subpath treated specially as we consider no match 'x' and 'x/...' + let isSubpathEnding: boolean = (start + subpathLength === segments.length); + let isOtherPathEnding: boolean = endsWith(paths[otherPath], subpath); + match = !isSubpathEnding || isOtherPathEnding; + } + } + + if (!match) { + // found unique subpath + let result = subpath; + if (start + subpathLength < segments.length) { + result = result + nativeSep + ellipsis; + } + if (start > 0) { + result = ellipsis + nativeSep + result; + } + shortenedPaths[path] = result; + } + } + } + + if (match) { + // use full path if no unique subpaths found + shortenedPaths[path] = paths[path]; + } + } + + return shortenedPaths; } \ No newline at end of file diff --git a/src/vs/base/common/paths.ts b/src/vs/base/common/paths.ts index 131b271cb41..11e39ca9fc1 100644 --- a/src/vs/base/common/paths.ts +++ b/src/vs/base/common/paths.ts @@ -8,7 +8,6 @@ import { isLinux, isWindows } from 'vs/base/common/platform'; import { fill } from 'vs/base/common/arrays'; import { rtrim } from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; -import { endsWith } from 'vs/base/common/strings'; /** * The forward slash path separator. @@ -394,58 +393,4 @@ export const isAbsoluteRegex = /^((\/|[a-zA-Z]:\\)[^\(\)<>\\'\"\[\]]+)/; */ export function isAbsolute(path: string): boolean { return isAbsoluteRegex.test(path); -} - -/** - * 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'; - let shortenedPaths: string[] = new Array(paths.length); - let match = false; - - // for every path - for (let path = 0; path < paths.length; path++) { - let segments: string[] = paths[path].split(nativeSep); - match = true; - - // pick the first shortest subpath found - for (let subpathLength = 1; match && subpathLength <= segments.length; subpathLength++) { - for (let start = segments.length - subpathLength; match && start >= 0; start--) { - match = false; - let subpath = segments.slice(start, start + subpathLength).join(nativeSep); - - // that is unique to any other path - for (let otherPath = 0; !match && otherPath < paths.length; otherPath++) { - if (otherPath !== path && paths[otherPath].indexOf(subpath) > -1) { - // suffix subpath treated specially as we consider no match 'x' and 'x/...' - let isSubpathEnding: boolean = (start + subpathLength === segments.length); - let isOtherPathEnding: boolean = endsWith(paths[otherPath], subpath); - match = !isSubpathEnding || isOtherPathEnding; - } - } - - if (!match) { - // found unique subpath - let result = subpath; - if (start + subpathLength < segments.length) { - result = result + nativeSep + ellipsis; - } - if (start > 0) { - result = ellipsis + nativeSep + result; - } - shortenedPaths[path] = result; - } - } - } - - if (match) { - // use full path if no unique subpaths found - shortenedPaths[path] = paths[path]; - } - } - - return shortenedPaths; } \ No newline at end of file diff --git a/src/vs/base/test/common/labels.test.ts b/src/vs/base/test/common/labels.test.ts new file mode 100644 index 00000000000..48748e5a53e --- /dev/null +++ b/src/vs/base/test/common/labels.test.ts @@ -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. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +// import * as assert from 'assert'; +// import labels = require('vs/base/common/labels'); + +suite('Labels', () => { + test('shorten', () => { + // nothing to shorten + // assert.deepEqual(labels.shorten(['a']), ['a']); + // assert.deepEqual(labels.shorten(['a', 'b']), ['a', 'b']); + // assert.deepEqual(labels.shorten(['a', 'b', 'c']), ['a', 'b', 'c']); + + // // completely different paths + // assert.deepEqual(labels.shorten(['a\\b', 'c\\d', 'e\\f']), ['…\\b', '…\\d', '…\\f']); + + // // same beginning + // assert.deepEqual(labels.shorten(['a', 'a\\b']), ['a', '…\\b']); + // assert.deepEqual(labels.shorten(['a\\b', 'a\\b\\c']), ['…\\b', '…\\c']); + // assert.deepEqual(labels.shorten(['a', 'a\\b', 'a\\b\\c']), ['a', '…\\b', '…\\c']); + // assert.deepEqual(labels.shorten(['x:\\a\\b', 'x:\\a\\c']), ['…\\b', '…\\c'], 'TODO: drive letter (or schema) should be preserved'); + // assert.deepEqual(labels.shorten(['\\\\a\\b', '\\\\a\\c']), ['…\\b', '…\\c'], 'TODO: root uri should be preserved'); + + // // same ending + // assert.deepEqual(labels.shorten(['a', 'b\\a']), ['a', 'b\\…']); + // assert.deepEqual(labels.shorten(['a\\b\\c', 'd\\b\\c']), ['a\\…', 'd\\…']); + // assert.deepEqual(labels.shorten(['a\\b\\c\\d', 'f\\b\\c\\d']), ['a\\…', 'f\\…']); + // assert.deepEqual(labels.shorten(['d\\e\\a\\b\\c', 'd\\b\\c']), ['…\\a\\…', 'd\\b\\…']); + // assert.deepEqual(labels.shorten(['a\\b\\c\\d', 'a\\f\\b\\c\\d']), ['a\\b\\…', '…\\f\\…']); + // assert.deepEqual(labels.shorten(['a\\b\\a', 'b\\b\\a']), ['a\\b\\…', 'b\\b\\…']); + // assert.deepEqual(labels.shorten(['d\\f\\a\\b\\c', 'h\\d\\b\\c']), ['…\\a\\…', 'h\\…']); + // assert.deepEqual(labels.shorten(['a\\b\\c', 'x:\\0\\a\\b\\c']), ['a\\b\\c', '…\\0\\…'], 'TODO: drive letter (or schema) should be always preserved'); + // assert.deepEqual(labels.shorten(['x:\\a\\b', 'y:\\a\\b']), ['x:\\…', 'y:\\…']); + // assert.deepEqual(labels.shorten(['\\\\x\\b', '\\\\y\\b']), ['…\\x\\…', '…\\y\\…'], 'TODO: \\\\x instead of …\\x'); + + // // same in the middle + // assert.deepEqual(labels.shorten(['a\\b\\c', 'd\\b\\e']), ['…\\c', '…\\e']); + + // // case-sensetive + // assert.deepEqual(labels.shorten(['a\\b\\c', 'd\\b\\C']), ['…\\c', '…\\C']); + + // assert.deepEqual(labels.shorten(['a', 'a\\b', 'a\\b\\c', 'd\\b\\c', 'd\\b']), ['a', 'a\\b', 'a\\b\\c', 'd\\b\\c', 'd\\b']); + // assert.deepEqual(labels.shorten(['a', 'a\\b', 'b']), ['a', 'a\\b', 'b']); + // assert.deepEqual(labels.shorten(['', 'a', 'b', 'b\\c', 'a\\c']), ['', 'a', 'b', 'b\\c', 'a\\c']); + // assert.deepEqual(labels.shorten(['src\\vs\\workbench\\parts\\execution\\electron-browser', 'src\\vs\\workbench\\parts\\execution\\electron-browser\\something', 'src\\vs\\workbench\\parts\\terminal\\electron-browser']), ['…\\execution\\electron-browser', '…\\something', '…\\terminal\\…']); + }); +}); \ No newline at end of file diff --git a/src/vs/base/test/common/paths.test.ts b/src/vs/base/test/common/paths.test.ts index 694f77bbeb0..3a902b3826a 100644 --- a/src/vs/base/test/common/paths.test.ts +++ b/src/vs/base/test/common/paths.test.ts @@ -246,44 +246,4 @@ suite('Paths', () => { assert.equal(paths.isAbsolute('F\\a\\b\\c'), false); assert.equal(paths.isAbsolute('F:\\a'), true); }); - - test('shorten', () => { - // nothing to shorten - assert.deepEqual(paths.shorten(['a']), ['a']); - assert.deepEqual(paths.shorten(['a', 'b']), ['a', 'b']); - assert.deepEqual(paths.shorten(['a', 'b', 'c']), ['a', 'b', 'c']); - - // completely different paths - assert.deepEqual(paths.shorten(['a\\b', 'c\\d', 'e\\f']), ['…\\b', '…\\d', '…\\f']); - - // same beginning - assert.deepEqual(paths.shorten(['a', 'a\\b']), ['a', '…\\b']); - assert.deepEqual(paths.shorten(['a\\b', 'a\\b\\c']), ['…\\b', '…\\c']); - assert.deepEqual(paths.shorten(['a', 'a\\b', 'a\\b\\c']), ['a', '…\\b', '…\\c']); - assert.deepEqual(paths.shorten(['x:\\a\\b', 'x:\\a\\c']), ['…\\b', '…\\c'], 'TODO: drive letter (or schema) should be preserved'); - assert.deepEqual(paths.shorten(['\\\\a\\b', '\\\\a\\c']), ['…\\b', '…\\c'], 'TODO: root uri should be preserved'); - - // same ending - assert.deepEqual(paths.shorten(['a', 'b\\a']), ['a', 'b\\…']); - assert.deepEqual(paths.shorten(['a\\b\\c', 'd\\b\\c']), ['a\\…', 'd\\…']); - assert.deepEqual(paths.shorten(['a\\b\\c\\d', 'f\\b\\c\\d']), ['a\\…', 'f\\…']); - assert.deepEqual(paths.shorten(['d\\e\\a\\b\\c', 'd\\b\\c']), ['…\\a\\…', 'd\\b\\…']); - assert.deepEqual(paths.shorten(['a\\b\\c\\d', 'a\\f\\b\\c\\d']), ['a\\b\\…', '…\\f\\…']); - assert.deepEqual(paths.shorten(['a\\b\\a', 'b\\b\\a']), ['a\\b\\…', 'b\\b\\…']); - assert.deepEqual(paths.shorten(['d\\f\\a\\b\\c', 'h\\d\\b\\c']), ['…\\a\\…', 'h\\…']); - assert.deepEqual(paths.shorten(['a\\b\\c', 'x:\\0\\a\\b\\c']), ['a\\b\\c', '…\\0\\…'], 'TODO: drive letter (or schema) should be always preserved'); - assert.deepEqual(paths.shorten(['x:\\a\\b', 'y:\\a\\b']), ['x:\\…', 'y:\\…']); - assert.deepEqual(paths.shorten(['\\\\x\\b', '\\\\y\\b']), ['…\\x\\…', '…\\y\\…'], 'TODO: \\\\x instead of …\\x'); - - // same in the middle - assert.deepEqual(paths.shorten(['a\\b\\c', 'd\\b\\e']), ['…\\c', '…\\e']); - - // case-sensetive - assert.deepEqual(paths.shorten(['a\\b\\c', 'd\\b\\C']), ['…\\c', '…\\C']); - - assert.deepEqual(paths.shorten(['a', 'a\\b', 'a\\b\\c', 'd\\b\\c', 'd\\b']), ['a', 'a\\b', 'a\\b\\c', 'd\\b\\c', 'd\\b']); - assert.deepEqual(paths.shorten(['a', 'a\\b', 'b']), ['a', 'a\\b', 'b']); - assert.deepEqual(paths.shorten(['', 'a', 'b', 'b\\c', 'a\\c']), ['', 'a', 'b', 'b\\c', 'a\\c']); - assert.deepEqual(paths.shorten(['src\\vs\\workbench\\parts\\execution\\electron-browser', 'src\\vs\\workbench\\parts\\execution\\electron-browser\\something', 'src\\vs\\workbench\\parts\\terminal\\electron-browser']), ['…\\execution\\electron-browser', '…\\something', '…\\terminal\\…']); - }); }); \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 81abb0e8c09..d4eb29ba79d 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -12,6 +12,7 @@ import errors = require('vs/base/common/errors'); import DOM = require('vs/base/browser/dom'); import { isMacintosh } from 'vs/base/common/platform'; import { MIME_BINARY } from 'vs/base/common/mime'; +import { shorten } from 'vs/base/common/labels'; import { ActionRunner, IAction } from 'vs/base/common/actions'; import { Position, IEditorInput } from 'vs/platform/editor/common/editor'; import { IEditorGroup, toResource } from 'vs/workbench/common/editor'; @@ -37,7 +38,6 @@ import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElemen import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { extractResources } from 'vs/base/browser/dnd'; import { LinkedMap } from 'vs/base/common/map'; -import paths = require('vs/base/common/paths'); interface IEditorInputLabel { editor: IEditorInput; @@ -275,7 +275,7 @@ export class TabsTitleControl extends TitleControl { const labelDuplicates = mapLabelToDuplicates.values(); labelDuplicates.forEach(duplicates => { if (duplicates.length > 1) { - let shortenedDescriptions = paths.shorten(duplicates.map(duplicate => duplicate.editor.getDescription())); + let shortenedDescriptions = shorten(duplicates.map(duplicate => duplicate.editor.getDescription())); duplicates.forEach((duplicate, i) => { duplicate.description = shortenedDescriptions[i]; duplicate.hasAmbiguousName = true; -- GitLab