labels.ts ×12

Frontier kind: Code frontier

unlabeled · c_3b37c4bb0233

1212 tests · 5782 LOC · 30 files · introduces 0 tests · 146 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
12 ranges146 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
798 ranges5782 lines · 30 files · Browse complete extent
All tests (intent)
1212 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 146 introduced LOC across 12 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/base/common/labels.ts 146 introduced LOC · 12 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- labels.ts
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 { hasDriveLetter, toSlashes } from './extpath.js';
7 > import { posix, sep, win32 } from './path.js';
8 > import { isMacintosh, isWindows, OperatingSystem, OS } from './platform.js';
9 > import { extUri, extUriIgnorePathCase } from './resources.js';
10 > import { rtrim, startsWithIgnoreCase } from './strings.js';
11 > import { URI } from './uri.js';
12 >
13 > export interface IPathLabelFormatting {
14 >
15 > /**
16 > * The OS the path label is from to produce a label
17 > * that matches OS expectations.
18 > */
19 > readonly os: OperatingSystem;
20 >
21 > /**
22 > * Whether to add a `~` when the path is in the
23 > * user home directory.
24 > *
25 > * Note: this only applies to Linux, macOS but not
26 > * Windows.
27 > */
28 > readonly tildify?: IUserHomeProvider;
29 >
30 > /**
31 > * Whether to convert to a relative path if the path
32 > * is within any of the opened workspace folders.
33 > */
34 > readonly relative?: IRelativePathProvider;
35 > }
36 >
37 > export interface IRelativePathProvider {
38 >
39 > /**
40 > * Whether to not add a prefix when in multi-root workspace.
41 > */
42 > readonly noPrefix?: boolean;
43 >
44 > getWorkspace(): { folders: { uri: URI; name?: string }[] };
45 > getWorkspaceFolder(resource: URI): { uri: URI; name?: string } | null;
46 > }
47 >
48 > export interface IUserHomeProvider {
49 > userHome: URI;
50 > }
51 >
52 > export function getPathLabel(resource: URI, formatting: IPathLabelFormatting): string {
53 const { os, tildify: tildifier, relative: relatifier } = formatting;
54
93 return pathLib.normalize(normalizeDriveLetter(absolutePath, os === OperatingSystem.Windows));
94 }
95 > labels.ts
96 function getRelativePathLabel(resource: URI, relativePathProvider: IRelativePathProvider, os: OperatingSystem): string | undefined {
97 const pathLib = os === OperatingSystem.Windows ? win32 : posix;
137 return relativePathLabel;
138 }
139 > labels.ts
140 > export function normalizeDriveLetter(path: string, isWindowsOS: boolean = isWindows): string {
141 if (hasDriveLetter(path, isWindowsOS)) {
142 return path.charAt(0).toUpperCase() + path.slice(1);
145 return path;
146 }
147 > labels.ts
148 > let normalizedUserHomeCached: { original: string; normalized: string } = Object.create(null);
149 > export function tildify(path: string, userHome: string, os = OS): string {
150 if (os === OperatingSystem.Windows || !path || !userHome) {
151 return path; // unsupported on Windows
174 return path;
175 }
176 > labels.ts
177 > export function untildify(path: string, userHome: string): string {
178 return path.replace(/^~($|\/|\\)/, `${userHome}$1`);
179 }
180 > labels.ts
181 > /**
182 > * Shortens the paths but keeps them easy to distinguish.
183 > * Replaces not important parts with ellipsis.
184 > * Every shorten path matches only one original path and vice versa.
185 > *
186 > * Algorithm for shortening paths is as follows:
187 > * 1. For every path in list, find unique substring of that path.
188 > * 2. Unique substring along with ellipsis is shortened path of that path.
189 > * 3. To find unique substring of path, consider every segment of length from 1 to path.length of path from end of string
190 > * and if present segment is not substring to any other paths then present segment is unique path,
191 > * else check if it is not present as suffix of any other path and present segment is suffix of path itself,
192 > * if it is true take present segment as unique path.
193 > * 4. Apply ellipsis to unique segment according to whether segment is present at start/in-between/end of path.
194 > *
195 > * Example 1
196 > * 1. consider 2 paths i.e. ['a\\b\\c\\d', 'a\\f\\b\\c\\d']
197 > * 2. find unique path of first path,
198 > * a. 'd' is present in path2 and is suffix of path2, hence not unique of present path.
199 > * b. 'c' is present in path2 and 'c' is not suffix of present path, similarly for 'b' and 'a' also.
200 > * c. 'd\\c' is suffix of path2.
201 > * d. 'b\\c' is not suffix of present path.
202 > * e. 'a\\b' is not present in path2, hence unique path is 'a\\b...'.
203 > * 3. for path2, 'f' is not present in path1 hence unique is '...\\f\\...'.
204 > *
205 > * Example 2
206 > * 1. consider 2 paths i.e. ['a\\b', 'a\\b\\c'].
207 > * a. Even if 'b' is present in path2, as 'b' is suffix of path1 and is not suffix of path2, unique path will be '...\\b'.
208 > * 2. for path2, 'c' is not present in path1 hence unique path is '..\\c'.
209 > */
210 > const ellipsis = '\u2026';
211 > const unc = '\\\\';
212 > const urlSchemaRegexp = /^[^:/\\?#]+?:\/\//;
213 > const home = '~';
214 > export function shorten(paths: string[], defaultPathSeparator: string = sep): string[] {
215 const shortenedPaths: string[] = new Array(paths.length);
216
323 return shortenedPaths;
324 }
325 > labels.ts
326 > export interface ISeparator {
327 > label: string;
328 > }
329 >
330 > enum Type {
331 > TEXT,
332 > VARIABLE,
333 > SEPARATOR
334 > }
335 >
336 > interface ISegment {
337 > value: string;
338 > type: Type;
339 > }
340 >
341 > /**
342 > * Helper to insert values for specific template variables into the string. E.g. "this $(is) a $(template)" can be
343 > * passed to this function together with an object that maps "is" and "template" to strings to have them replaced.
344 > * @param value string to which template is applied
345 > * @param values the values of the templates to use
346 > */
347 > export function template(template: string, values: { [key: string]: string | ISeparator | undefined | null } = Object.create(null)): string {
348 const segments: ISegment[] = [];
349
409 }).map(segment => segment.value).join('');
410 }
411 > labels.ts
412 > /**
413 > * Handles mnemonics for menu items. Depending on OS:
414 > * - Windows: Supported via & character (replace && with &)
415 > * - Linux: Supported via & character (replace && with &)
416 > * - macOS: Unsupported (replace && with empty string)
417 > */
418 > export function mnemonicMenuLabel(label: string, forceDisableMnemonics?: boolean): string {
419 if (isMacintosh || forceDisableMnemonics) {
420 return label.replace(/\(&&\w\)|&&/g, '').replace(/&/g, isMacintosh ? '&' : '&&');
423 return label.replace(/&&|&/g, m => m === '&' ? '&&' : '&');
424 }
425 > labels.ts
426 > /**
427 > * Handles mnemonics for buttons. Depending on OS:
428 > * - Windows: Supported via & character (replace && with & and & with && for escaping)
429 > * - Linux: Supported via _ character (replace && with _)
430 > * - macOS: Unsupported (replace && with empty string)
431 > * When forceDisableMnemonics is set, returns just the label without mnemonics.
432 > */
433 > export function mnemonicButtonLabel(label: string, forceDisableMnemonics: true): string;
434 > export function mnemonicButtonLabel(label: string, forceDisableMnemonics?: false): { readonly withMnemonic: string; readonly withoutMnemonic: string };
435 > export function mnemonicButtonLabel(label: string, forceDisableMnemonics?: boolean): { readonly withMnemonic: string; readonly withoutMnemonic: string } | string {
436 const withoutMnemonic = label.replace(/\(&&\w\)|&&/g, '');
437
451 return { withMnemonic, withoutMnemonic };
452 }
453 > labels.ts
454 > export function unmnemonicLabel(label: string): string {
455 return label.replace(/&/g, '&&');
456 }
457 > labels.ts
458 > /**
459 > * Splits a recent label in name and parent path, supporting both '/' and '\' and workspace suffixes.
460 > * If the location is remote, the remote name is included in the name part.
461 > */
462 > export function splitRecentLabel(recentLabel: string): { name: string; parentPath: string } {
463 if (recentLabel.endsWith(']')) {
464 // label with workspace suffix
472 return splitName(recentLabel);
473 }
474 > labels.ts
475 function splitName(fullPath: string): { name: string; parentPath: string } {
476 const p = fullPath.indexOf('/') !== -1 ? posix : win32;