import * as vscode from 'vscode' ; import TelemetryReporter from 'vscode-extension-telemetry' ; import { serverMsg } from '../manager' ; import { Disposable } from '../utils/dispose' ; import { TerminalColor , TerminalDeco , TerminalStyleUtil , } from '../utils/terminalStyleUtil' ; import { FormatDateTime } from '../utils/utils' ; import { ServerStartedStatus , ServerArgs } from './serverTaskProvider' ; const CHAR_CODE_CTRL_C = 3 ; description export class ServerTaskTerminal extends Disposable implements vscode . Pseudoterminal { public running = false ; private readonly _onRequestToOpenServerEmitter = this . _register ( new vscode . EventEmitter < void > ( ) ) ; public readonly onRequestToOpenServer = this . _onRequestToOpenServerEmitter . event ; private readonly _onRequestToCloseServerEmitter = this . _register ( new vscode . EventEmitter < void > ( ) ) ; public readonly onRequestToCloseServer = this . _onRequestToCloseServerEmitter . event ; private readonly _verbose ; private writeEmitter = new vscode . EventEmitter < string > ( ) ; onDidWrite : vscode . Event < string > = this . writeEmitter . event ; public closeEmitter = new vscode . EventEmitter < number > ( ) ; onDidClose ? : vscode . Event < number > = this . closeEmitter . event ; constructor ( args , private readonly _reporter , private readonly _executeServer = true ) { super ( ) ; if ( this . _executeServer ) { this . _reporter . sendTelemetryEvent ( 'tasks.terminal.start' ) ; this . _verbose = args . some ( ( x ) => x == ServerArgs . verbose ) ; } } public open ( ) { if ( this . _executeServer ) { this . running = true ; this . writeEmitter . fire ( 'Opening Server...\r\n' ) ; this . _onRequestToOpenServerEmitter . fire ( ) ; } else { this . writeEmitter . fire ( `Server already running in another task. Closing now.\r\n` ) ; this . close ( ) ; } } public close ( ) { this . running = false ; if ( this . _executeServer ) { this . _onRequestToCloseServerEmitter . fire ( ) ; this . closeEmitter . fire ( 0 ) ; } else { this . closeEmitter . fire ( 1 ) ; } } public handleInput ( data ) { if ( data . length > 0 && data . charCodeAt ( 0 ) == CHAR_CODE_CTRL_C ) { this . writeEmitter . fire ( `Closing the server...\r\n` ) ; this . _onRequestToCloseServerEmitter . fire ( ) ; } } description param { vscode . Uri } externalUri param { ServerStartedStatus } status public serverStarted ( externalUri , status ) { const formattedAddress = this . _formatAddr ( externalUri . toString ( ) ) ; if ( ! this . _verbose ) { this . writeEmitter . fire ( `This task does not have logging. To get logging, use the "--verbose" flag.\r\n` ) ; } switch ( status ) { case ServerStartedStatus . JUST_STARTED : { this . writeEmitter . fire ( `Started Server on ${ formattedAddress }\r\n` ) ; break ; } case ServerStartedStatus . STARTED_BY_EMBEDDED_PREV : { this . writeEmitter . fire ( `Server already on at ${ formattedAddress }\r\n> ` ) ; break ; } } this . writeEmitter . fire ( `Type ${ TerminalStyleUtil . ColorTerminalString ( `CTRL+C` , TerminalColor . red , TerminalDeco . bold ) } to close the server.\r\n\r\n> ` ) ; } description public serverStopped ( ) { this . writeEmitter . fire ( `Server stopped. Bye!` ) ; this . close ( ) ; } /**
     * Called the parent to tell the terminal that is it safe to end the task, but the server will continue to be on to support the embedded preview. This will end the task.
     */ public serverWillBeStopped ( ) { this . writeEmitter . fire ( `This task will finish now, but the server will stay on since you've used the embedded preview recently.\r\n` ) ; this . writeEmitter . fire ( TerminalStyleUtil . ColorTerminalString ( `Run 'Stop Live Preview Server' in the command palette to close the server and close any previews.\r\n\r\n` , TerminalColor . yellow ) ) ; this . close ( ) ; } param { serverMsg } msg public showServerMsg ( msg ) { if ( this . _verbose ) { const date = new Date ( ) ; this . writeEmitter . fire ( `[${ FormatDateTime ( date , ' ' ) }] ${ msg . method }: ${ TerminalStyleUtil . ColorTerminalString ( msg . url , TerminalColor . blue ) } | ${ this . _colorHttpStatus ( msg . status ) }\r\n> ` ) ; } } param { number } status returns { string } private _colorHttpStatus ( status ) { let color = TerminalColor . green ; if ( status >= 400 ) { color = TerminalColor . red ; } else if ( status >= 300 ) { color = TerminalColor . yellow ; } return TerminalStyleUtil . ColorTerminalString ( status . toString ( ) , color ) ; } param { string } str returns { number } private _getSecondColonPos ( str ) { const indexColon = str . indexOf ( ':' ) ; if ( indexColon == - 1 ) { return str . length ; } const indexSecondColon = str . indexOf ( ':' , indexColon + 1 ) ; return indexSecondColon == - 1 ? str . length : indexSecondColon ; } param { string } addr returns { string } private _formatAddr ( addr ) { const indexSecondColon = this . _getSecondColonPos ( addr ) ; const firstHalfOfString = addr . substr ( 0 , indexSecondColon ) ; const lastHalfOfString = addr . substr ( indexSecondColon ) ; return ( TerminalStyleUtil . ColorTerminalString ( firstHalfOfString , TerminalColor . blue , TerminalDeco . bold ) + TerminalStyleUtil . ColorTerminalString ( lastHalfOfString , TerminalColor . purple , TerminalDeco . bold ) ) ; } }