9
9
- Ctrl+arrows
10
10
- Ctrl+L
11
11
- Ctrl+C
12
- - code cleanup
12
+ - code cleanup, greatly simplify terminal handling
13
13
- bundle Scapy
14
14
-->
15
15
@@ -47,7 +47,6 @@ var pythonCodeY = 0;
47
47
var historyCodeList: string [] = [];
48
48
var lastPythonCodeLine = " " ;
49
49
var renderingCode = true ;
50
- var stdout_codes: Array <number > = [];
51
50
52
51
// pyodide
53
52
var pyodide: any = null ;
@@ -56,6 +55,12 @@ var pyodide: any = null;
56
55
const terminal: Ref <HTMLElement | null > = ref (null ); // container
57
56
const term = new Terminal (); // xterm.js object
58
57
58
+ // Python terminal
59
+ var pythonCode = ' ' ;
60
+ var historyIndex = 0 ;
61
+ var historyCode = " " ;
62
+ var lastCRIndex = 0 ;
63
+
59
64
export function mountFile(file : File ) {
60
65
/*
61
66
* Mount a File
@@ -71,13 +76,6 @@ export function mountFile(file: File) {
71
76
freader .readAsArrayBuffer (file );
72
77
}
73
78
74
- function rawstdout(code : number ) {
75
- /*
76
- * Add string to terminal output
77
- */
78
- stdout_codes .push (code );
79
- }
80
-
81
79
function recalcFromPythonCode() {
82
80
/*
83
81
* Recalculate cursor position based on
@@ -104,19 +102,6 @@ function prompt() {
104
102
term .write (' \r\x1b [34m>>> ' );
105
103
};
106
104
107
- var pythonCode = ' ' ;
108
- var blockFlag = " " ;
109
- var blockMap: { [type : string ]: string } = {
110
- " :" : " \r " ,
111
- " \\ " : " \r " ,
112
- " {" : " }" ,
113
- " [" : " ]" ,
114
- " (" : " )" ,
115
- }
116
- var historyIndex = 0 ;
117
- var historyCode = " " ;
118
- var lastCRIndex = 0 ;
119
-
120
105
function setCursorPosition(x : Number , y : Number ) {
121
106
/*
122
107
* Set the cursor position in the terminal
@@ -141,6 +126,17 @@ async function writeHighlightPythonCode(x: Number, y: Number, pythonCode: string
141
126
});
142
127
}
143
128
129
+ function writeByteOnTerm(data : number ) {
130
+ /*
131
+ * Write to terminal output. Called directly by pyodide
132
+ */
133
+ if (data == 10 ) { // \n
134
+ term .write (" \r\n " );
135
+ } else {
136
+ term .write (new Uint8Array ([data ]));
137
+ }
138
+ }
139
+
144
140
function displayCurrentPrompt() {
145
141
/*
146
142
* Display the prompt string based on the state
@@ -237,47 +233,33 @@ term.onData(e => {
237
233
let pythonCodeList = pythonCode .split (' \r ' );
238
234
let lastLine = pythonCodeList [pythonCodeList .length - 1 ];
239
235
if (lastLine .length > 0 ) {
240
- historyCodeList = historyCodeList .concat (lastLine )
241
- }
242
- if (((pythonCode [pythonCode .length - 1 ] in blockMap )) && (blockFlag === " " )) {
243
- blockFlag = pythonCode [pythonCode .length - 1 ];
244
- pythonCode += e ;
245
- term .writeln (" \r " );
246
- term .write (' ... ' );
247
- break ;
248
- }
249
- if (blockFlag != " " ) {
250
- if (pythonCode [pythonCode .length - 1 ] === blockMap [blockFlag ]) {
251
- blockFlag = " " ;
252
- } else {
253
- pythonCode += e ;
254
- term .writeln (" \r " );
255
- term .write (' ... ' );
256
- break ;
257
- }
236
+ historyCodeList = historyCodeList .concat (lastLine );
258
237
}
259
238
term .writeln (' \x1b [0m' );
260
-
261
- stdout_codes = []
262
- pyodide .runPythonAsync (pythonCode ).then ((output : string ) => {
263
- let result = new TextDecoder ().decode (new Uint8Array (stdout_codes ));
264
- if (result .length > 0 ) {
265
- term .write (result .replaceAll (" \n " , " \r\n " ));
266
- } else if (output != undefined ) {
267
- term .write (output .toString ().replaceAll (" \n " , " \r\n " ) + ' \r\n ' );
239
+ // We use code.InteractiveInterpreter to take detect incomplete inputs
240
+ pyodide .runPythonAsync (`
241
+ _PY_code = """
242
+ ${pythonCode .replaceAll (" \\ " , " \\\\ " )}
243
+ """
244
+ _PY_EVAL.runsource(_PY_code)
245
+ ` ).then ((incomplete : boolean ) => {
246
+ if (incomplete ) {
247
+ pythonCode += " \r " ;
248
+ term .write (" \r " );
249
+ term .write (' ... ' );
250
+ } else {
251
+ pythonCode = ' ' ;
252
+ prompt ();
268
253
}
269
- prompt ();
270
254
}).catch ((err : any ) => {
271
255
term .write (' \x1b [01;31m' + err .message .replaceAll (' \n ' , ' \r\n ' ) + ' \x1b [0m' );
272
256
prompt ();
273
- pythonCode = " "
257
+ pythonCode = ' ' ;
274
258
});
275
-
276
259
} else {
277
260
term .writeln (' \x1b [0m' );
278
261
prompt ();
279
262
}
280
- pythonCode = ' ' ;
281
263
break ;
282
264
case VK_CANCEL :
283
265
term .write (' ^C\r\n ' );
@@ -313,7 +295,7 @@ term.onData(e => {
313
295
break ;
314
296
default :
315
297
// debug
316
- for (let i = 0 ; i < e .length ; i ++ ) console .log (e .charCodeAt (i ));
298
+ // for (let i = 0; i < e.length; i++) console.log(e.charCodeAt(i));
317
299
// other key pressed
318
300
if (e >= String .fromCharCode (0x20 ) && e <= String .fromCharCode (0x7E ) || e >= ' \u00a0 ' ) {
319
301
// printable
@@ -368,41 +350,45 @@ async function startPyodide() {
368
350
await pyodide .loadPackage (" micropip" )
369
351
await pyodide .loadPackage (" ssl" )
370
352
353
+ // TODO: move output handlers here... when all Scapy loading issues are fixes
354
+
371
355
term .write (' \r Loading Scapy... ' );
372
356
await pyodide .loadPackage (scapyWheelURL );
373
357
// await scapyInstall();
374
358
await pyodide .runPythonAsync (`
375
359
from scapy.all import *
376
360
conf.color_theme = DefaultTheme()
361
+ import code
362
+ _PY_EVAL = code.InteractiveInterpreter(locals=globals())
377
363
` );
378
364
379
- pyodide .setStdout ({ raw: rawstdout , isatty: true });
365
+ // Register output stdout / stderr
366
+ pyodide .setStdout ({ raw: writeByteOnTerm , isatty: true });
367
+ pyodide .setStderr ({ raw: writeByteOnTerm , isatty: true });
380
368
381
369
let mini = " False" ;
382
370
if (smAndDown .value ) {
383
371
mini = " True" ;
384
372
}
385
373
374
+ term .write (' \r ' );
386
375
await pyodide .runPythonAsync (`
387
376
import sys
388
377
from pygments import highlight
389
378
from pygments.lexers import PythonLexer
390
379
from pygments.formatters import TerminalTrueColorFormatter
391
380
print(get_fancy_banner( ` + mini + ` ))
392
381
` ).then (() => {
393
- let result = new TextDecoder ().decode (new Uint8Array (stdout_codes ));
394
- term .write (' \r ' + result .replaceAll (" \n " , " \r\n " ) + ' \r\n ' );
395
382
prompt ();
396
383
renderingCode = false ;
397
- }
398
- );
384
+ });
399
385
}
400
386
401
387
// Startup hook
402
388
onMounted (async () => {
403
389
// reset existing
390
+ term .clear ();
404
391
term .reset ();
405
- stdout_codes = [];
406
392
historyCodeList = [];
407
393
// start xterm.js and pyodide
408
394
startXterm (term , terminal ).then (startPyodide ).catch ((ex ) => {
@@ -417,11 +403,6 @@ onMounted(async () => {
417
403
} catch { }
418
404
});
419
405
});
420
-
421
- // Exit hook
422
- onUnmounted (() => {
423
- term.dispose();
424
- });
425
406
</script >
426
407
427
408
<style >
0 commit comments