nl_tokens: accepts a readable Stream instance and makes it emit keypress events
pl_tokens: function emitKeypressEvents ( stream , iface ) { if ( stream [ KEYPRESS_DECODER ] ) return ; if ( StringDecoder === undefined ) StringDecoder = require ( 'string_decoder' ) . StringDecoder ; stream [ KEYPRESS_DECODER ] = new StringDecoder ( 'utf8' ) ; stream [ ESCAPE_DECODER ] = emitKeys ( stream ) ; stream [ ESCAPE_DECODER ] . next ( ) ; const escapeCodeTimeout = ( ) => stream [ ESCAPE_DECODER ] . next ( '' ) ; let timeoutId ; function onData ( b ) { if ( stream . listenerCount ( 'keypress' ) > 0 ) { var r = stream [ KEYPRESS_DECODER ] . write ( b ) ; if ( r ) { clearTimeout ( timeoutId ) ; if ( iface ) { iface . _sawKeyPress = r . length === 1 ; } for ( var i = 0 ; i < r . length ; i ++ ) { if ( r [ i ] === '\t' && typeof r [ i + 1 ] === 'string' && iface ) { iface . isCompletionEnabled = false ; } try { stream [ ESCAPE_DECODER ] . next ( r [ i ] ) ; // Escape letter at the tail position if ( r [ i ] === kEscape && i + 1 === r . length ) { timeoutId = setTimeout ( escapeCodeTimeout , iface ? iface . escapeCodeTimeout : ESCAPE_CODE_TIMEOUT ) ; } } catch ( err ) { // If the generator throws (it could happen in the `keypress` // event), we need to restart it. stream [ ESCAPE_DECODER ] = emitKeys ( stream ) ; stream [ ESCAPE_DECODER ] . next ( ) ; throw <mask> ; } finally { if ( iface ) { iface . isCompletionEnabled = true ; } } } } } else { // Nobody's watching anyway stream . removeListener ( 'data' , onData ) ; stream . on ( 'newListener' , onNewListener ) ; } } function onNewListener ( event ) { if ( event === 'keypress' ) { stream . on ( 'data' , onData ) ; stream . removeListener ( 'newListener' , onNewListener ) ; } } if ( stream . listenerCount ( 'keypress' ) > 0 ) { stream . on ( 'data' , onData ) ; } else { stream . on ( 'newListener' , onNewListener ) ; } }