From 83fe9ed9f73d303465de7d06a9ee14960bb02b69 Mon Sep 17 00:00:00 2001 From: Erich Gamma Date: Thu, 20 Jul 2017 15:13:05 +0200 Subject: [PATCH] Use the root folder name for the short path --- extensions/npm/src/main.ts | 318 +------------------------------------ 1 file changed, 5 insertions(+), 313 deletions(-) diff --git a/extensions/npm/src/main.ts b/extensions/npm/src/main.ts index ff448c1ec80..9c81fe2e143 100644 --- a/extensions/npm/src/main.ts +++ b/extensions/npm/src/main.ts @@ -100,19 +100,16 @@ async function provideNpmScripts(): Promise { return emptyTasks; } - let folderPaths = folders.map(each => each.uri.fsPath); - let shortPaths = shorten(folderPaths); - - const isSingleRoot = allTasks.length === 1; + const isSingleRoot = folders.length === 1; for (let i = 0; i < folders.length; i++) { - let tasks = await provideNpmScriptsForFolder(folders[i], shortPaths[i], isSingleRoot); + let tasks = await provideNpmScriptsForFolder(folders[i], isSingleRoot); allTasks.push(...tasks); } return allTasks; } -async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder, shortPath: string, singleRoot: boolean): Promise { +async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder, singleRoot: boolean): Promise { let rootPath = folder.uri.fsPath; let emptyTasks: vscode.Task[] = []; @@ -130,7 +127,7 @@ async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder, shortP const result: vscode.Task[] = []; Object.keys(json.scripts).filter(isNotPreOrPostScript).forEach(each => { - const task = createTask(each, `run ${each}`, rootPath, shortPath, singleRoot); + const task = createTask(each, `run ${each}`, rootPath, folder.name, singleRoot); const lowerCaseTaskName = each.toLowerCase(); if (isBuildTask(lowerCaseTaskName)) { task.group = vscode.TaskGroup.Build; @@ -140,7 +137,7 @@ async function provideNpmScriptsForFolder(folder: vscode.WorkspaceFolder, shortP result.push(task); }); // always add npm install (without a problem matcher) - result.push(createTask('install', 'install', rootPath, shortPath, singleRoot, [])); + result.push(createTask('install', 'install', rootPath, folder.name, singleRoot, [])); return result; } catch (e) { return emptyTasks; @@ -171,309 +168,4 @@ function createTask(script: string, cmd: string, rootPath: string, shortPath: st let taskName = getTaskName(script, shortPath, singleRoot); return new vscode.Task(kind, taskName, 'npm', new vscode.ShellExecution(getNpmCommandLine(cmd), { cwd: rootPath }), matcher); -} - -// tslint:disable:no-unused-variable - -// TODO code to shorten paths - this should be available as a utility module/API - -// copied from base/platform.ts - -// --- THIS FILE IS TEMPORARY UNTIL ENV.TS IS CLEANED UP. IT CAN SAFELY BE USED IN ALL TARGET EXECUTION ENVIRONMENTS (node & dom) --- - -let _isWindows = false; -let _isMacintosh = false; -let _isLinux = false; -let _isRootUser = false; -let _isNative = false; -let _isWeb = false; -let _locale: string = ''; -let _language: string = ''; - -interface NLSConfig { - locale: string; - availableLanguages: { [key: string]: string; }; -} - -export interface IProcessEnvironment { - [key: string]: string; -} - -interface INodeProcess { - platform: string; - env: IProcessEnvironment; - getuid(): number; -} -declare let process: INodeProcess; -declare let global: any; - -interface INavigator { - userAgent: string; - language: string; -} -declare let navigator: INavigator; -declare let self: any; - -export const LANGUAGE_DEFAULT = 'en'; - -// OS detection -if (typeof process === 'object') { - _isWindows = (process.platform === 'win32'); - _isMacintosh = (process.platform === 'darwin'); - _isLinux = (process.platform === 'linux'); - _isRootUser = !_isWindows && (process.getuid() === 0); - let rawNlsConfig = process.env['VSCODE_NLS_CONFIG']; - if (rawNlsConfig) { - try { - let nlsConfig: NLSConfig = JSON.parse(rawNlsConfig); - let resolved = nlsConfig.availableLanguages['*']; - _locale = nlsConfig.locale; - // VSCode's default language is 'en' - _language = resolved ? resolved : LANGUAGE_DEFAULT; - } catch (e) { - } - } - _isNative = true; -} else if (typeof navigator === 'object') { - let userAgent = navigator.userAgent; - _isWindows = userAgent.indexOf('Windows') >= 0; - _isMacintosh = userAgent.indexOf('Macintosh') >= 0; - _isLinux = userAgent.indexOf('Linux') >= 0; - _isWeb = true; - _locale = navigator.language; - _language = _locale; -} - -export enum Platform { - Web, - Mac, - Linux, - Windows -} - -let _platform: Platform = Platform.Web; -if (_isNative) { - if (_isMacintosh) { - _platform = Platform.Mac; - } else if (_isWindows) { - _platform = Platform.Windows; - } else if (_isLinux) { - _platform = Platform.Linux; - } -} - -export const isWindows = _isWindows; -export const isMacintosh = _isMacintosh; -export const isLinux = _isLinux; -export const isRootUser = _isRootUser; -export const isNative = _isNative; -export const isWeb = _isWeb; -export const platform = _platform; - -/** - * The language used for the user interface. The format of - * the string is all lower case (e.g. zh-tw for Traditional - * Chinese) - */ -export const language = _language; - -/** - * The OS locale or the locale specified by --locale. The format of - * the string is all lower case (e.g. zh-tw for Traditional - * Chinese). The UI is not necessarily shown in the provided locale. - */ -export const locale = _locale; - -export interface TimeoutToken { -} - -export interface IntervalToken { -} - -interface IGlobals { - Worker?: any; - setTimeout(callback: (...args: any[]) => void, delay: number, ...args: any[]): TimeoutToken; - clearTimeout(token: TimeoutToken): void; - - setInterval(callback: (...args: any[]) => void, delay: number, ...args: any[]): IntervalToken; - clearInterval(token: IntervalToken): void; -} - -const _globals = (typeof self === 'object' ? self : global); -export const globals: any = _globals; - -export function hasWebWorkerSupport(): boolean { - return typeof _globals.Worker !== 'undefined'; -} -export const setTimeout = _globals.setTimeout.bind(_globals); -export const clearTimeout = _globals.clearTimeout.bind(_globals); - -export const setInterval = _globals.setInterval.bind(_globals); -export const clearInterval = _globals.clearInterval.bind(_globals); - -export const enum OperatingSystem { - Windows = 1, - Macintosh = 2, - Linux = 3 -} -export const OS = (_isMacintosh ? OperatingSystem.Macintosh : (_isWindows ? OperatingSystem.Windows : OperatingSystem.Linux)); - -export const enum AccessibilitySupport { - /** - * This should be the browser case where it is not known if a screen reader is attached or no. - */ - Unknown = 0, - - Disabled = 1, - - Enabled = 2 -} - -// copied from vscode/src/base/common/label.ts - -const nativeSep = isWindows ? '\\' : '/'; - -/** - * 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. - * - * Algorithm for shortening paths is as follows: - * 1. For every path in list, find unique substring of that path. - * 2. Unique substring along with ellipsis is shortened path of that path. - * 3. To find unique substring of path, consider every segment of length from 1 to path.length of path from end of string - * and if present segment is not substring to any other paths then present segment is unique path, - * else check if it is not present as suffix of any other path and present segment is suffix of path itself, - * if it is true take present segment as unique path. - * 4. Apply ellipsis to unique segment according to whether segment is present at start/in-between/end of path. - * - * Example 1 - * 1. consider 2 paths i.e. ['a\\b\\c\\d', 'a\\f\\b\\c\\d'] - * 2. find unique path of first path, - * a. 'd' is present in path2 and is suffix of path2, hence not unique of present path. - * b. 'c' is present in path2 and 'c' is not suffix of present path, similarly for 'b' and 'a' also. - * c. 'd\\c' is suffix of path2. - * d. 'b\\c' is not suffix of present path. - * e. 'a\\b' is not present in path2, hence unique path is 'a\\b...'. - * 3. for path2, 'f' is not present in path1 hence unique is '...\\f\\...'. - * - * Example 2 - * 1. consider 2 paths i.e. ['a\\b', 'a\\b\\c']. - * 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'. - * 2. for path2, 'c' is not present in path1 hence unique path is '..\\c'. - */ -const ellipsis = '\u2026'; -const unc = '\\\\'; -export function shorten(paths: string[]): string[] { - const shortenedPaths: string[] = new Array(paths.length); - - // for every path - let match = false; - for (let pathIndex = 0; pathIndex < paths.length; pathIndex++) { - let path = paths[pathIndex]; - - if (path === '') { - shortenedPaths[pathIndex] = `.${nativeSep}`; - continue; - } - - if (!path) { - shortenedPaths[pathIndex] = path; - continue; - } - - match = true; - - // trim for now and concatenate unc path (e.g. \\network) or root path (/etc) later - let prefix = ''; - if (path.indexOf(unc) === 0) { - prefix = path.substr(0, path.indexOf(unc) + unc.length); - path = path.substr(path.indexOf(unc) + unc.length); - } else if (path.indexOf(nativeSep) === 0) { - prefix = path.substr(0, path.indexOf(nativeSep) + nativeSep.length); - path = path.substr(path.indexOf(nativeSep) + nativeSep.length); - } - - // pick the first shortest subpath found - 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; - let 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] && paths[otherPathIndex].indexOf(subpath) > -1) { - const isSubpathEnding: boolean = (start + subpathLength === segments.length); - - // Adding separator as prefix for subpath, such that 'endsWith(src, trgt)' considers subpath as directory name instead of plain string. - // prefix is not added when either subpath is root directory or path[otherPathIndex] does not have multiple directories. - const subpathWithSep: string = (start > 0 && paths[otherPathIndex].indexOf(nativeSep) > -1) ? nativeSep + subpath : subpath; - const isOtherPathEnding: boolean = endsWith(paths[otherPathIndex], subpathWithSep); - - match = !isSubpathEnding || isOtherPathEnding; - } - } - - // found unique subpath - if (!match) { - let result = ''; - - // preserve disk drive or root prefix - if (endsWith(segments[0], ':') || prefix !== '') { - if (start === 1) { - // extend subpath to include disk drive prefix - start = 0; - subpathLength++; - subpath = segments[0] + nativeSep + subpath; - } - - if (start > 0) { - result = segments[0] + nativeSep; - } - - result = prefix + result; - } - - // add ellipsis at the beginning if neeeded - if (start > 0) { - result = result + ellipsis + nativeSep; - } - - result = result + subpath; - - // add ellipsis at the end if needed - if (start + subpathLength < segments.length) { - result = result + nativeSep + ellipsis; - } - - shortenedPaths[pathIndex] = result; - } - } - } - - if (match) { - shortenedPaths[pathIndex] = path; // use full path if no unique subpaths found - } - } - - return shortenedPaths; -} - -// copied from base/strings.ts - -/** - * Determines if haystack ends with needle. - */ -export function endsWith(haystack: string, needle: string): boolean { - let diff = haystack.length - needle.length; - if (diff > 0) { - return haystack.indexOf(needle, diff) === diff; - } else if (diff === 0) { - return haystack === needle; - } else { - return false; - } } \ No newline at end of file