import { RelativePattern , WorkspaceFolder , Uri , workspace } from "vscode" ; import * as fs from "fs" ; import * as minimatch from "minimatch" ; import { configuration } from "./configuration" ; import constants from "./constants" ; import * as path from "path" ; import * as os from "os" ; import * as log from "./log" ; param name param indexUpper export function camelCase ( name , indexUpper ) { if ( ! name || indexUpper <= 0 || indexUpper >= name . length ) { return name ; } return name . replace ( /(?:^\w|[A-Za-z]|\b\w)/g , ( letter , index ) => { return index !== indexUpper ? letter . toLowerCase ( ) : letter . toUpperCase ( ) ; } ) . replace ( /[\s\-]+/g , "" ) ; } param arr param item returns export function existsInArray ( arr , item ) { for ( let i = 0 ; i < arr . length ; i ++ ) { if ( item === arr [ i ] ) { return i ; } } return false ; } export async function forEachAsync ( array , callback ) { for ( let index = 0 ; index < array . length ; index ++ ) { const result = await callback ( array [ index ] , index , array ) ; if ( result === false ) { break ; } } } export async function forEachMapAsync ( map , callback ) { for ( const entry of map . entries ( ) ) { const result = await callback ( entry [ 1 ] , entry [ 0 ] , map ) ; if ( result === false ) { break ; } } } export function getCwd ( uri ) { return uri . fsPath . substring ( 0 , uri . fsPath . lastIndexOf ( path . sep ) + 1 ) ; } export function getGroupSeparator ( ) { return configuration . get < string > ( "groupSeparator" ) || constants . DEFAULT_SEPARATOR ; } export function getAntGlobPattern ( ) { let multiFilePattern = constants . GLOB_ANT ; const includes = configuration . get ( "includeAnt" ) ; if ( includes && includes . length > 0 ) { multiFilePattern = "{" + constants . GLOB_ANT ; if ( Array . isArray ( includes ) ) { for ( const i of includes ) { multiFilePattern += "," ; multiFilePattern += i ; } } else { multiFilePattern += "," ; multiFilePattern += includes ; } multiFilePattern += "}" ; } return multiFilePattern ; } export function getExcludesGlob ( folder ) { let multiFilePattern = "{**/node_modules/**,**/work/**" ; const excludes = configuration . get ( "exclude" ) ; if ( excludes && excludes . length > 0 ) { if ( Array . isArray ( excludes ) ) { for ( const e of excludes ) { multiFilePattern += "," ; multiFilePattern += e ; } } else { multiFilePattern += "," ; multiFilePattern += excludes ; } } multiFilePattern += "}" ; return new RelativePattern ( folder , multiFilePattern ) ; } export function getPackageManager ( ) { let pkgMgr = workspace . getConfiguration ( "npm" ) . get < string > ( "packageManager" ) || "npm" ; if ( pkgMgr . match ( /(npm|auto)/ ) ) { pkgMgr = "npm" ; } return pkgMgr ; } export function getScriptTaskTypes ( ) { return [ "bash" , "batch" , "nsis" , "perl" , "powershell" , "python" , "ruby" ] ; } export function getTaskTypes ( ) { return [ "ant" , "app-publisher" , "bash" , "batch" , "gradle" , "grunt" , "gulp" , "make" , "maven" , "npm" , "nsis" , "perl" , "powershell" , "python" , "pipenv" , "ruby" , "workspace" ] ; } export function getPortableDataPath ( padding = "" ) { if ( process . env . VSCODE_PORTABLE ) { const uri = Uri . parse ( process . env . VSCODE_PORTABLE ) ; if ( uri ) { if ( fs . existsSync ( uri . fsPath ) ) { try { const fullPath = path . join ( uri . fsPath , "user-data" , "User" ) ; log . value ( padding + "found portable user data path" , fullPath , 1 ) ; return fullPath ; } catch ( e ) { log . write ( e . toString ( ) ) ; return ; } } } } return ; } export function getUserDataPath ( padding = "" ) { let userPath = "" ; log . write ( padding + "get user data path" , 1 ) ; logUserDataEnv ( padding + "   " ) ; if ( process . argv ) { let argvIdx = existsInArray ( process . argv , "--user-data-dir" ) ; if ( argvIdx !== false && typeof argvIdx === "number" && argvIdx >= 0 && argvIdx < process . argv . length ) { userPath = path . resolve ( process . argv [ ++ argvIdx ] ) ; log . value ( padding + "user path is" , userPath , 1 ) ; return userPath ; } } userPath = getPortableDataPath ( padding + "   " ) ; if ( ! userPath ) { userPath = getDefaultUserDataPath ( ) ; } userPath = path . resolve ( userPath ) ; log . value ( padding + "user path is" , userPath , 1 ) ; return userPath ; } function getDefaultUserDataPath ( ) { let appDataPath = process . env . VSCODE_APPDATA ; if ( ! appDataPath ) { switch ( process . platform ) { case "win32" : appDataPath = process . env . APPDATA ; if ( ! appDataPath ) { const userProfile = process . env . USERPROFILE ; if ( typeof userProfile !== "string" ) { throw new Error ( "Windows: Unexpected undefined %USERPROFILE% environment variable" ) ; } appDataPath = path . join ( userProfile , "AppData" , "Roaming" ) ; } break ; case "darwin" : appDataPath = path . join ( os . homedir ( ) , "Library" , "Application Support" ) ; break ; case "linux" : appDataPath = process . env . XDG_CONFIG_HOME || path . join ( os . homedir ( ) , ".config" ) ; break ; default : throw new Error ( "Platform not supported" ) ; } } return path . join ( appDataPath , "vscode" ) ; } export function getGlobPattern ( taskType ) { if ( taskType ) { taskType = taskType . replace ( /\W*\-/ , "" ) ; if ( taskType === "ant" ) { return getAntGlobPattern ( ) ; } else { return constants [ "GLOB_" + taskType . toUpperCase ( ) ] ; } } return "*/**" ; } export function getRelativePath ( folder , uri ) { let rtn = "" ; if ( folder ) { const rootUri = folder . uri ; const absolutePath = uri . path . substring ( 0 , uri . path . lastIndexOf ( "/" ) + 1 ) ; rtn = absolutePath . substring ( rootUri . path . length + 1 ) ; } return rtn ; } export function getScriptProviderType ( source ) { if ( isScriptType ( source ) ) { return "script" ; } return source ; } export function isExcluded ( uriPath , logPad = "" ) { function testForExclusionPattern ( path , pattern ) { return minimatch ( path , pattern , { dot : true , nocase : true } ) ; } const exclude = configuration . get < string [ ] > ( "exclude" , [ ] ) ; log . blank ( 4 ) ; log . write ( logPad + "Check exclusion" , 4 ) ; log . value ( logPad + "   path" , uriPath , 4 ) ; for ( const pattern of exclude ) { log . value ( logPad + "   checking pattern" , pattern , 5 ) ; if ( testForExclusionPattern ( uriPath , pattern ) ) { log . write ( logPad + "   Excluded!" , 4 ) ; return true ; } } log . write ( logPad + "   Not excluded" , 4 ) ; return false ; } export function isScriptType ( source ) { return getScriptTaskTypes ( ) . includes ( source ) ; } function logUserDataEnv ( padding = "" ) { if ( log . isLoggingEnabled ( ) ) { log . value ( padding + "os" , process . platform , 1 ) ; log . value ( padding + "portable" , process . env . VSCODE_PORTABLE , 1 ) ; log . value ( padding + "env:VSCODE_APPDATA" , process . env . VSCODE_APPDATA , 1 ) ; log . value ( padding + "env:VSCODE_APPDATA" , process . env . APPDATA , 1 ) ; log . value ( padding + "env:VSCODE_APPDATA" , process . env . USERPROFILE , 1 ) ; if ( process . platform === "linux" ) { log . value ( "env:XDG_CONFIG_HOME" , process . env . XDG_CONFIG_HOME , 1 ) ; } } } export function pathExists ( path ) { try { fs . accessSync ( path ) ; } catch ( err ) { return false ; } return true ; } export function pushIfNotExists ( arr , item ) { if ( existsInArray ( arr , item ) === false ) { arr . push ( item ) ; } } export function properCase ( name ) { if ( ! name ) { return name ; } return name . replace ( /(?:^\w|[A-Z]|\b\w)/g , ( letter , index ) => { return index !== 0 ? letter . toLowerCase ( ) : letter . toUpperCase ( ) ; } ) . replace ( /[\s]+/g , "" ) ; } export async function readFile ( file ) { return new Promise < string > ( ( resolve , reject ) => { fs . readFile ( file , ( err , data ) => { if ( err ) { reject ( err ) ; } resolve ( data ? data . toString ( ) : "" ) ; } ) ; } ) ; } export function readFileSync ( file ) { const buf = fs . readFileSync ( file ) ; return ( buf ? buf . toString ( ) : "" ) ; } export function removeFromArray ( arr , item ) { let idx = - 1 ; let idx2 = - 1 ; for ( const each of arr ) { idx ++ ; if ( item === each ) { idx2 = idx ; break ; } } if ( idx2 !== - 1 && idx2 < arr . length ) { arr . splice ( idx2 , 1 ) ; } } export async function removeFromArrayAsync ( arr , item ) { let idx = - 1 ; let idx2 = - 1 ; await forEachAsync ( arr , ( each ) => { idx ++ ; if ( item === each ) { idx2 = idx ; return false ; } } ) ; if ( idx2 !== - 1 && idx2 < arr . length ) { arr . splice ( idx2 , 1 ) ; } } export function sortMapByKey ( map ) { map = new Map ( [ ... map ] . sort ( ( a , b ) => { return a [ 0 ] ?. localeCompare ( b [ 0 ] . toString ( ) ) ; } ) ) ; } export function timeout ( ms ) { return new Promise ( resolve => setTimeout ( resolve , ms ) ) ; }