Path: blob/main/extensions/copilot/src/util/vs/base/common/iconLabels.ts
13405 views
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'12/*---------------------------------------------------------------------------------------------3* Copyright (c) Microsoft Corporation. All rights reserved.4* Licensed under the MIT License. See License.txt in the project root for license information.5*--------------------------------------------------------------------------------------------*/67import { IMatch, matchesFuzzy } from './filters';8import { ltrim } from './strings';9import { ThemeIcon } from './themables';1011const iconStartMarker = '$(';1213const iconsRegex = new RegExp(`\\$\\(${ThemeIcon.iconNameExpression}(?:${ThemeIcon.iconModifierExpression})?\\)`, 'g'); // no capturing groups1415const escapeIconsRegex = new RegExp(`(\\\\)?${iconsRegex.source}`, 'g');16export function escapeIcons(text: string): string {17return text.replace(escapeIconsRegex, (match, escaped) => escaped ? match : `\\${match}`);18}1920const markdownEscapedIconsRegex = new RegExp(`\\\\${iconsRegex.source}`, 'g');21export function markdownEscapeEscapedIcons(text: string): string {22// Need to add an extra \ for escaping in markdown23return text.replace(markdownEscapedIconsRegex, match => `\\${match}`);24}2526const stripIconsRegex = new RegExp(`(\\s)?(\\\\)?${iconsRegex.source}(\\s)?`, 'g');2728/**29* Takes a label with icons (`$(iconId)xyz`) and strips the icons out (`xyz`)30*/31export function stripIcons(text: string): string {32if (text.indexOf(iconStartMarker) === -1) {33return text;34}3536return text.replace(stripIconsRegex, (match, preWhitespace, escaped, postWhitespace) => escaped ? match : preWhitespace || postWhitespace || '');37}383940/**41* Takes a label with icons (`$(iconId)xyz`), removes the icon syntax adds whitespace so that screen readers can read the text better.42*/43export function getCodiconAriaLabel(text: string | undefined) {44if (!text) {45return '';46}4748return text.replace(/\$\((.*?)\)/g, (_match, codiconName) => ` ${codiconName} `).trim();49}505152export interface IParsedLabelWithIcons {53readonly text: string;54readonly iconOffsets?: readonly number[];55}5657const _parseIconsRegex = new RegExp(`\\$\\(${ThemeIcon.iconNameCharacter}+\\)`, 'g');5859/**60* Takes a label with icons (`abc $(iconId)xyz`) and returns the text (`abc xyz`) and the offsets of the icons (`[3]`)61*/62export function parseLabelWithIcons(input: string): IParsedLabelWithIcons {6364_parseIconsRegex.lastIndex = 0;6566let text = '';67const iconOffsets: number[] = [];68let iconsOffset = 0;6970while (true) {71const pos = _parseIconsRegex.lastIndex;72const match = _parseIconsRegex.exec(input);7374const chars = input.substring(pos, match?.index);75if (chars.length > 0) {76text += chars;77for (let i = 0; i < chars.length; i++) {78iconOffsets.push(iconsOffset);79}80}81if (!match) {82break;83}84iconsOffset += match[0].length;85}8687return { text, iconOffsets };88}899091export function matchesFuzzyIconAware(query: string, target: IParsedLabelWithIcons, enableSeparateSubstringMatching = false): IMatch[] | null {92const { text, iconOffsets } = target;9394// Return early if there are no icon markers in the word to match against95if (!iconOffsets || iconOffsets.length === 0) {96return matchesFuzzy(query, text, enableSeparateSubstringMatching);97}9899// Trim the word to match against because it could have leading100// whitespace now if the word started with an icon101const wordToMatchAgainstWithoutIconsTrimmed = ltrim(text, ' ');102const leadingWhitespaceOffset = text.length - wordToMatchAgainstWithoutIconsTrimmed.length;103104// match on value without icon105const matches = matchesFuzzy(query, wordToMatchAgainstWithoutIconsTrimmed, enableSeparateSubstringMatching);106107// Map matches back to offsets with icon and trimming108if (matches) {109for (const match of matches) {110const iconOffset = iconOffsets[match.start + leadingWhitespaceOffset] /* icon offsets at index */ + leadingWhitespaceOffset /* overall leading whitespace offset */;111match.start += iconOffset;112match.end += iconOffset;113}114}115116return matches;117}118119120