/**
 * Copyright (c) 2012-2015, Christopher Jeffrey, Peter Sunde (MIT License)
 * Copyright (c) 2016, Daniel Imms (MIT License).
 * Copyright (c) 2018, Microsoft Corporation (MIT License).
 */ import { Socket } from 'net' ; import { Terminal , DEFAULT_COLS , DEFAULT_ROWS } from './terminal' ; import { WindowsPtyAgent } from './windowsPtyAgent' ; import { IPtyForkOptions , IPtyOpenOptions } from './interfaces' ; import { ArgvOrCommandLine } from './types' ; import { assign } from './utils' ; const DEFAULT_FILE = 'cmd.exe' ; const DEFAULT_NAME = 'Windows Shell' ; export class WindowsTerminal extends Terminal { private _isReady : boolean ; private _deferreds : any [ ] ; private _agent : WindowsPtyAgent ; constructor ( file ? , args ? , opt ? ) { super ( opt ) ; args = args || [ ] ; file = file || DEFAULT_FILE ; opt = opt || { } ; opt . env = opt . env || process . env ; if ( opt . encoding ) { console . warn ( 'Setting encoding on Windows is not supported' ) ; } const env = assign ( { } , opt . env ) ; const cols = opt . cols || DEFAULT_COLS ; const rows = opt . rows || DEFAULT_ROWS ; const cwd = opt . cwd || process . cwd ( ) ; const name = opt . name || env . TERM || DEFAULT_NAME ; const parsedEnv = this . _parseEnv ( env ) ; this . _isReady = false ; this . _deferreds = [ ] ; this . _agent = new WindowsPtyAgent ( file , args , parsedEnv , cwd , cols , rows , false , opt . experimentalUseConpty ) ; this . _socket = this . _agent . outSocket ; this . _pid = this . _agent . innerPid ; this . _fd = this . _agent . fd ; this . _pty = this . _agent . pty ; this . _socket . on ( 'ready_datapipe' , ( ) => { [ 'connect' , 'data' , 'end' , 'timeout' , 'drain' ] . forEach ( event => { this . _socket . on ( event , ( ) => { if ( ! this . _isReady && event === 'data' ) { this . _isReady = true ; this . _deferreds . forEach ( fn => { fn . run ( ) ; } ) ; this . _deferreds = [ ] ; } } ) ; } ) ; this . _socket . on ( 'error' , err => { this . _close ( ) ; if ( ( < any > err ) . code ) { if ( ~ ( < any > err ) . code . indexOf ( 'errno 5' ) || ~ ( < any > err ) . code . indexOf ( 'EIO' ) ) return ; } if ( this . listeners ( 'error' ) . length < 2 ) { throw err ; } } ) ; this . _socket . on ( 'close' , ( ) => { this . emit ( 'exit' , this . _agent . exitCode ) ; this . _close ( ) ; } ) ; } ) ; this . _file = file ; this . _name = name ; this . _readable = true ; this . _writable = true ; } /**
     * openpty
     */ public static open ( options ? ) { throw new Error ( 'open() not supported on windows, use Fork() instead.' ) ; } /**
     * Events
     */ public write ( data ) { this . _defer ( ( ) => { this . _agent . inSocket . write ( data ) ; } ) ; } /**
     * TTY
     */ public resize ( cols , rows ) { if ( cols <= 0 || rows <= 0 ) { throw new Error ( 'resizing must be done using positive cols and rows' ) ; } this . _defer ( ( ) => { this . _agent . resize ( cols , rows ) ; } ) ; } public destroy ( ) { this . _defer ( ( ) => { this . kill ( ) ; } ) ; } public kill ( signal ? ) { this . _defer ( ( ) => { if ( signal ) { throw new Error ( 'Signals not supported on windows.' ) ; } this . _close ( ) ; this . _agent . kill ( ) ; } ) ; } private _defer ( deferredFn ) { if ( ! ( this instanceof WindowsTerminal ) ) { throw new Error ( 'Must be instanceof WindowsTerminal' ) ; } if ( this . _isReady ) { deferredFn . apply ( this , null ) ; return ; } this . _deferreds . push ( { run : ( ) => deferredFn . apply ( this , null ) } ) ; } public get process ( ) : string { return this . _name ; } public get master ( ) : Socket { throw new Error ( 'master is not supported on Windows' ) ; } public get slave ( ) : Socket { throw new Error ( 'slave is not supported on Windows' ) ; } }