Skip to content

Commit 71dcdcc

Browse files
committed
Simplify XTermScapy handling
1 parent 5f0618e commit 71dcdcc

File tree

1 file changed

+45
-64
lines changed

1 file changed

+45
-64
lines changed

src/components/XTermScapy.vue

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
- Ctrl+arrows
1010
- Ctrl+L
1111
- Ctrl+C
12-
- code cleanup
12+
- code cleanup, greatly simplify terminal handling
1313
- bundle Scapy
1414
-->
1515

@@ -47,7 +47,6 @@ var pythonCodeY = 0;
4747
var historyCodeList: string[] = [];
4848
var lastPythonCodeLine = "";
4949
var renderingCode = true;
50-
var stdout_codes: Array<number> = [];
5150
5251
// pyodide
5352
var pyodide: any = null;
@@ -56,6 +55,12 @@ var pyodide: any = null;
5655
const terminal: Ref<HTMLElement | null> = ref(null); // container
5756
const term = new Terminal(); // xterm.js object
5857
58+
// Python terminal
59+
var pythonCode = '';
60+
var historyIndex = 0;
61+
var historyCode = "";
62+
var lastCRIndex = 0;
63+
5964
export function mountFile(file: File) {
6065
/*
6166
* Mount a File
@@ -71,13 +76,6 @@ export function mountFile(file: File) {
7176
freader.readAsArrayBuffer(file);
7277
}
7378
74-
function rawstdout(code: number) {
75-
/*
76-
* Add string to terminal output
77-
*/
78-
stdout_codes.push(code);
79-
}
80-
8179
function recalcFromPythonCode() {
8280
/*
8381
* Recalculate cursor position based on
@@ -104,19 +102,6 @@ function prompt() {
104102
term.write('\r\x1b[34m>>> ');
105103
};
106104
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-
120105
function setCursorPosition(x: Number, y: Number) {
121106
/*
122107
* Set the cursor position in the terminal
@@ -141,6 +126,17 @@ async function writeHighlightPythonCode(x: Number, y: Number, pythonCode: string
141126
});
142127
}
143128
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+
144140
function displayCurrentPrompt() {
145141
/*
146142
* Display the prompt string based on the state
@@ -237,47 +233,33 @@ term.onData(e => {
237233
let pythonCodeList = pythonCode.split('\r');
238234
let lastLine = pythonCodeList[pythonCodeList.length - 1];
239235
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);
258237
}
259238
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();
268253
}
269-
prompt();
270254
}).catch((err: any) => {
271255
term.write('\x1b[01;31m' + err.message.replaceAll('\n', '\r\n') + '\x1b[0m');
272256
prompt();
273-
pythonCode = ""
257+
pythonCode = '';
274258
});
275-
276259
} else {
277260
term.writeln('\x1b[0m');
278261
prompt();
279262
}
280-
pythonCode = '';
281263
break;
282264
case VK_CANCEL:
283265
term.write('^C\r\n');
@@ -313,7 +295,7 @@ term.onData(e => {
313295
break;
314296
default:
315297
// 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));
317299
// other key pressed
318300
if (e >= String.fromCharCode(0x20) && e <= String.fromCharCode(0x7E) || e >= '\u00a0') {
319301
// printable
@@ -368,41 +350,45 @@ async function startPyodide() {
368350
await pyodide.loadPackage("micropip")
369351
await pyodide.loadPackage("ssl")
370352
353+
// TODO: move output handlers here... when all Scapy loading issues are fixes
354+
371355
term.write('\rLoading Scapy... ');
372356
await pyodide.loadPackage(scapyWheelURL);
373357
// await scapyInstall();
374358
await pyodide.runPythonAsync(`
375359
from scapy.all import *
376360
conf.color_theme = DefaultTheme()
361+
import code
362+
_PY_EVAL = code.InteractiveInterpreter(locals=globals())
377363
`);
378364
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 });
380368
381369
let mini = "False";
382370
if (smAndDown.value) {
383371
mini = "True";
384372
}
385373
374+
term.write('\r');
386375
await pyodide.runPythonAsync(`
387376
import sys
388377
from pygments import highlight
389378
from pygments.lexers import PythonLexer
390379
from pygments.formatters import TerminalTrueColorFormatter
391380
print(get_fancy_banner(` + mini + `))
392381
`).then(() => {
393-
let result = new TextDecoder().decode(new Uint8Array(stdout_codes));
394-
term.write('\r' + result.replaceAll("\n", "\r\n") + '\r\n');
395382
prompt();
396383
renderingCode = false;
397-
}
398-
);
384+
});
399385
}
400386
401387
// Startup hook
402388
onMounted(async () => {
403389
// reset existing
390+
term.clear();
404391
term.reset();
405-
stdout_codes = [];
406392
historyCodeList = [];
407393
// start xterm.js and pyodide
408394
startXterm(term, terminal).then(startPyodide).catch((ex) => {
@@ -417,11 +403,6 @@ onMounted(async () => {
417403
} catch { }
418404
});
419405
});
420-
421-
// Exit hook
422-
onUnmounted(() => {
423-
term.dispose();
424-
});
425406
</script>
426407

427408
<style>

0 commit comments

Comments
 (0)