import * as cp from "child_process" ; import * as fs from "fs" ; import * as path from "path" ; import * as util from "util" ; import * as vscode from "vscode" ; import { CONSTANTS , CPX_CONFIG_FILE , DialogResponses , GLOBAL_ENV_VARS , SERVER_INFO , } from "../constants" ; import { CPXWorkspace } from "../cpxWorkspace" ; import { DeviceContext } from "../deviceContext" ; export const exec = util . promisify ( cp . exec ) ; const errorChannel = vscode . window . createOutputChannel ( CONSTANTS . ERROR . INSTALLATION_ERROR ) ; export const getPathToScript = ( context , folderName , fileName = "" ) => { const onDiskPath = vscode . Uri . file ( path . join ( context . extensionPath , folderName , fileName ) ) ; const scriptPath = onDiskPath . with ( { scheme : "vscode-resource" } ) ; return scriptPath . fsPath ; } ; export const showPrivacyModal = ( okAction , thirdPartyDisclaimer ) => { vscode . window . showInformationMessage ( `${ thirdPartyDisclaimer }: ${ CONSTANTS . LINKS . PRIVACY }` , DialogResponses . AGREE_AND_PROCEED , DialogResponses . CANCEL ) . then ( ( privacySelection ) => { if ( privacySelection === DialogResponses . AGREE_AND_PROCEED ) { okAction ( ) ; } else if ( privacySelection === DialogResponses . CANCEL ) { } } ) ; } ; export const logToOutputChannel = ( outChannel , message , show = false ) : void => { if ( outChannel ) { if ( show ) { outChannel . show ( true ) ; } outChannel . append ( message ) ; } } ; export function tryParseJSON ( jsonString ) { try { const jsonObj = JSON . parse ( jsonString ) ; if ( jsonObj && typeof jsonObj === "object" ) { return jsonObj ; } } catch ( exception ) { } return false ; } export function fileExistsSync ( filePath ) { try { return fs . statSync ( filePath ) . isFile ( ) ; } catch ( error ) { return false ; } } export function mkdirRecursivelySync ( dirPath ) { if ( directoryExistsSync ( dirPath ) ) { return ; } const dirname = path . dirname ( dirPath ) ; if ( path . normalize ( dirname ) === path . normalize ( dirPath ) ) { fs . mkdirSync ( dirPath ) ; } else if ( directoryExistsSync ( dirname ) ) { fs . mkdirSync ( dirPath ) ; } else { mkdirRecursivelySync ( dirname ) ; fs . mkdirSync ( dirPath ) ; } } export function directoryExistsSync ( dirPath ) { try { return fs . statSync ( dirPath ) . isDirectory ( ) ; } catch ( e ) { return false ; } } /**
 * This method pads the current string with another string (repeated, if needed)
 * so that the resulting string reaches the given length.
 * The padding is applied from the start (left) of the current string.
 */ export function padStart ( sourceString , targetLength , padString ? ) { if ( ! sourceString ) { return sourceString ; } if ( ! ( String . prototype as any ) . padStart ) { padString = String ( padString || " " ) ; if ( sourceString . length > targetLength ) { return sourceString ; } else { targetLength = targetLength - sourceString . length ; if ( targetLength > padString . length ) { padString += padString . repeat ( targetLength / padString . length ) ; } return padString . slice ( 0 , targetLength ) + sourceString ; } } else { return ( sourceString as any ) . padStart ( targetLength , padString ) ; } } export function convertToHex ( num , width = 0 ) { return padStart ( num . toString ( 16 ) , width , "0" ) ; } export function generateCPXConfig ( ) { const deviceContext = DeviceContext . getInstance ( ) ; const cpxJson = { port : deviceContext . port , } ; const cpxConfigFilePath = path . join ( CPXWorkspace . rootPath , CPX_CONFIG_FILE ) ; mkdirRecursivelySync ( path . dirname ( cpxConfigFilePath ) ) ; fs . writeFileSync ( cpxConfigFilePath , JSON . stringify ( cpxJson , null , 4 ) ) ; } export const addVisibleTextEditorCallback = ( currentPanel , context ) : vscode . Disposable => { const initialPythonEditors = filterForPythonFiles ( vscode . window . visibleTextEditors ) ; currentPanel . webview . postMessage ( { command : "visible-editors" , state : { activePythonEditors : initialPythonEditors } , } ) ; return vscode . window . onDidChangeVisibleTextEditors ( ( textEditors ) => { const activePythonEditors = filterForPythonFiles ( textEditors ) ; currentPanel . webview . postMessage ( { command : "visible-editors" , state : { activePythonEditors } , } ) ; } , { } , context . subscriptions ) ; } ; export const filterForPythonFiles = ( textEditors ) => { return textEditors . filter ( editor => editor . document . languageId === GLOBAL_ENV_VARS . PYTHON ) . map ( editor => editor . document . fileName ) ; } ; export const getActiveEditorFromPath = ( filePath ) : vscode . TextDocument => { const activeEditor = vscode . window . visibleTextEditors . find ( ( editor ) => editor . document . fileName === filePath ) ; return activeEditor ? activeEditor . document : undefined ; } ; export const getServerPortConfig = ( ) : number => { if ( vscode . workspace . getConfiguration ( ) . has ( SERVER_INFO . SERVER_PORT_CONFIGURATION ) ) { return vscode . workspace . getConfiguration ( ) . get ( SERVER_INFO . SERVER_PORT_CONFIGURATION ) as number ; } return SERVER_INFO . DEFAULT_SERVER_PORT ; } ; export const checkConfig = ( configName ) : boolean => { return vscode . workspace . getConfiguration ( ) . get ( configName ) === true ; } ; export const getConfig = ( configName ) : string => { return vscode . workspace . getConfiguration ( ) . get ( configName ) ; } ; export const createEscapedPath = ( ... pieces ) => { const initialPath = path . join ( ... pieces ) ; return `"` + initialPath . replace ( /(["'$`\\])/g , "\\$1" ) + `"` ; } ; export const getTelemetryState = ( ) => { return vscode . workspace . getConfiguration ( ) . get ( "telemetry.enableTelemetry" , true ) ; } ;