1- import { OutputChannel } from "vscode" ;
2- import { EventEmitter } from "events" ;
3- import { Readable , Writable } from "stream" ;
41import * as Repl from 'repl' ;
52import * as Util from 'util' ;
3+ import { Writable , Readable } from 'stream' ;
4+
5+
6+ type ReplServer = Repl . REPLServer & { inputStream : Readable , eval : ReplEval } ;
7+ type ReplEval = ( cmd : string , context : any , filename : string , cb : ( err ?: Error , result ?: any ) => void ) => void ;
8+
9+ let lineCount = 0 ;
10+
11+ const server = Repl . start ( {
12+ prompt : '' ,
13+ input : new Readable ( { read : ( ) => { } } ) ,
14+ output : new Writable ( {
15+ write : ( chunk , encoding , callback ) => {
16+ let out = chunk . toString ( ) . trim ( ) ;
17+ switch ( out ) {
18+ case '...' : break ;
19+ case '' : break ;
20+ default :
21+ process . send ( { line : lineCount , type : 'Terminal' , value : out } ) ;
22+ break ;
23+ }
24+ callback ( ) ;
25+ }
26+ } ) ,
27+ ignoreUndefined : true ,
628
29+ } ) as ReplServer ;
730
8- export default class NodeRepl extends EventEmitter {
9- private replEval : ( cmd : string , context : any , filename : string , cb : ( err ?: Error , result ?: string ) => void ) => void ;
10-
11- constructor ( private outputChannel : OutputChannel ) {
12- super ( ) ;
13- }
14-
15- public async interpret ( code : string ) {
16- try {
17- let inputStream = new Readable ( { read : ( ) => { } } ) ,
18- lineCount = 0 ;
19-
20- let repl = Repl . start ( {
21- prompt : '' ,
22- input : inputStream ,
23- writer : ( out ) => {
24- if ( out == null ) return ;
25- } ,
26- output : new Writable ( {
27- write : ( chunk , encoding , cb ) => {
28- let out = chunk . toString ( ) . trim ( ) ;
29- switch ( out ) {
30- case 'undefined' :
31- case '...' :
32- case '' :
33- break ;
34-
35- default :
36- this . emit ( 'output' , { line : lineCount , type : 'Terminal' , text : out } )
37- break ;
38- }
39- cb ( ) ;
40- }
41- } ) ,
42- } ) as Repl . REPLServer & { eval : ( cmd : string , context : any , filename : string , cb : ( err ?: Error , result ?: any ) => void ) => void } ;
43-
44- if ( this . replEval == null )
45- this . replEval = repl . eval ; // keep a backup of original eval
46-
47- // nice place to read the result in sequence and inject it in the code
48- repl . eval = ( cmd : string , context : any , filename : string , cb : ( err ?: Error , result ?: any ) => void ) => {
49-
50- this . replEval ( cmd , context , filename , ( err , result : any ) => {
51- let regex = / \/ \* ` ( \d + ) ` \* \/ / gi,
52- match : RegExpExecArray
5331
54- if ( ! err ) {
55- while ( ( match = regex . exec ( cmd ) ) != null )
56- lineCount += + match [ 1 ] ;
32+ const originEval = server . eval ; // keep a backup of original eval
33+ const lineNumber = / \/ \* ` ( \d + ) ` \* \/ / gi;
5734
58- this . emit ( 'output' , { line : lineCount , type : 'Expression' , value : result } ) ;
59- }
35+ // nice place to read the result in sequence and inject it in the code
36+ server . eval = ( cmd , context , filename , callback ) => {
37+ originEval ( cmd , context , filename , ( err , result ) => {
38+ let match : RegExpExecArray ;
6039
61- cb ( err , result ) ;
62- } ) ;
40+ while ( ( match = lineNumber . exec ( cmd ) ) != null )
41+ lineCount += + match [ 1 ] ;
6342
64- lineCount ++ ;
65- }
43+ if ( result )
44+ process . send ( { line : lineCount , type : 'Expression' , value : result } ) ;
6645
67- const originLog = repl . context . console . log ;
68- const appendLineLog = ( lineNumber : number , text : any , ...args : any [ ] ) => {
69- originLog ( `\`{${ lineNumber } }\`${ typeof text === 'string' ? text : Util . inspect ( text ) } ` , ...args ) ;
70- }
71- Object . defineProperty ( repl . context , '`console`' , {
72- value : {
73- log : appendLineLog ,
74- debug : appendLineLog ,
75- error : appendLineLog ,
76- }
77- } )
46+ callback ( err , result ) ;
47+ } ) ;
7848
79- for ( let line of code . split ( / \r ? \n / ) ) {
80- // tell the REPL about the line of code to see if there is any result coming out of it
81- inputStream . push ( `${ line } \n` ) ;
82- }
49+ lineCount ++ ;
50+ }
8351
84- inputStream . push ( `.exit\n` ) ;
85- inputStream . push ( null ) ;
52+ const originLog = server . context . console . log ;
53+ const appendLineLog = ( lineNumber : number , text : any , ...args : any [ ] ) => {
54+ originLog ( `\`{${ lineNumber } }\`${ typeof text === 'string' ? text : Util . inspect ( text ) } ` , ...args ) ;
55+ }
56+ Object . defineProperty ( server . context , '`console`' , {
57+ value : {
58+ log : appendLineLog ,
59+ debug : appendLineLog ,
60+ error : appendLineLog ,
61+ }
62+ } ) ;
8663
87- repl . on ( 'exit' , ( ) => setTimeout ( ( ) => this . emit ( 'exit' ) , 100 ) ) ;
88- } catch ( ex ) {
89- this . outputChannel . appendLine ( ex ) ;
64+ process . on ( 'message' , data => {
65+ if ( data . code ) {
66+ try {
67+ for ( let line of data . code . split ( '\n' ) )
68+ server . inputStream . push ( line + '\n' ) ;
69+ } catch ( error ) {
70+ process . emit ( 'error' , error ) ;
9071 }
72+ } else if ( data . operation === 'exit' ) {
73+ process . exit ( ) ;
9174 }
92- }
75+ } ) ;
0 commit comments