import Emitter from 'events' ; import readline from 'readline' ; const logger = require ( '../logger' ) ( 'connection' ) ; export default class Connection extends Emitter { private _ready : boolean ; private _channel : number ; constructor ( private readable , private writeable ) { super ( ) ; this . _ready = false ; this . readable = process . stdin ; this . writeable = process . stdout ; const rl = readline . createInterface ( this . readable ) ; rl . on ( 'line' , ( line ) => { this . parseData ( line ) ; } ) ; rl . on ( 'close' , ( ) => { logger . error ( 'stdin get closed' ) ; process . exit ( 0 ) ; } ) ; } private parseData ( str ) { if ( str . length == 0 ) return ; let arr ; try { arr = JSON . parse ( str ) ; } catch ( e ) { logger . error ( 'Invalid data from vim' , str ) ; this . echoerr ( `Invalid data: ${ str }` ) ; return ; } let [ id , obj ] = arr ; logger . debug ( 'received request' , id , obj ) ; if ( arr . length > 2 ) { logger . error ( 'Result array length > 2' , arr ) ; } if ( id > 0 ) { this . emit ( 'request' , id , obj ) ; } else if ( id == 0 ) { if ( obj [ 0 ] == 'ready' ) { let [ channel ] = obj [ 1 ] ; this . _channel = channel ; this . _ready = true ; this . emit ( 'ready' , channel ) ; } else { this . emit ( 'notification' , obj ) ; } } else { this . emit ( 'response' , id , obj ) ; } } public get channelId ( ) : Promise < number > { if ( this . _ready ) { return Promise . resolve ( this . _channel ) ; } return new Promise ( resolve => { this . once ( 'ready' , ( ) => { resolve ( this . _channel ) ; } ) ; } ) ; } public get isReady ( ) : boolean { return this . _ready ; } public response ( requestId , data ? ) { this . send ( [ requestId , data || null ] ) ; } public notify ( event , data ? ) { this . send ( [ 0 , [ event , data || null ] ] ) ; } public send ( arr ) { logger . debug ( 'send response' , arr [ 0 ] , arr . slice ( 1 ) ) ; this . writeable . write ( JSON . stringify ( arr ) + '\n' ) ; } public redraw ( force = false ) { this . send ( [ 'redraw' , force ? 'force' : '' ] ) ; } public commmand ( cmd ) { this . send ( [ 'ex' , cmd ] ) ; } private echoerr ( msg ) { this . commmand ( `echoerr '${ msg . replace ( /'/ , "''" ) }'` ) ; } public normal ( cmd ) { this . send ( [ 'normal' , cmd ] ) ; } public expr ( isNotify , expr ) ; public expr ( requestId , expr ) { if ( typeof requestId === 'boolean' && requestId === true ) { this . send ( [ 'expr' , expr ] ) ; return ; } this . send ( [ 'expr' , expr , requestId ] ) ; } public call ( isNotify , func , args ) ; public call ( requestId , func , args ) { if ( typeof requestId === 'boolean' && requestId === true ) { this . send ( [ 'call' , func , args ] ) ; return ; } this . send ( [ 'call' , func , args , requestId ] ) ; } }