HeyPuter / phoenix

🔥 Puter's pure-javascript shell
https://puter.com/app/terminal
GNU Affero General Public License v3.0
88 stars 15 forks source link

Up/Down/Left/Right keys don't work in Node.js runtime #20

Closed AtkinsSJ closed 4 months ago

AtkinsSJ commented 4 months ago

When running in node.js, pressing arrow keys (or any other control-sequence characters) prints them out, instead of them doing their intended job (eg, up for previous input). This seems to be because in non-raw mode, we only get given data from stdin when <return> is pressed.

I experimented with enabling raw mode, and readline.js does now recognise when the arrow keys are pressed, but this also breaks command input, which is less than ideal. :sweat_smile:

In any case, here's as far as I got, having Ctrl-C work.

diff --git a/src/pty/NodeStdioPTT.js b/src/pty/NodeStdioPTT.js
index 8e45d32..39d1b17 100644
--- a/src/pty/NodeStdioPTT.js
+++ b/src/pty/NodeStdioPTT.js
@@ -1,4 +1,5 @@
 import { ReadableStream, WritableStream } from 'stream/web';
+import { signals } from "../ansi-shell/signals.js";

 const writestream_node_to_web = node_stream => {
     return node_stream;
@@ -24,8 +25,20 @@ export class NodeStdioPTT {
             }
         });
         this.in = readableStream.getReader();
+        process.stdin.setRawMode(true);
         process.stdin.on('data', chunk => {
-            readController.enqueue(chunk);
+            const input = new Uint8Array(chunk);
+            readController.enqueue(input);
+            // SIGINT
+            if (input.length === 1 && input[0] === signals.SIGINT) {
+                process.exit(1);
+                return;
+            }
+            // SIGQUIT
+            if (input.length === 1 && input[0] === signals.SIGQUIT) {
+                globalThis.force_eot = true;
+                return;
+            }
         });

         this.out = writestream_node_to_web(process.stdout);
@@ -44,15 +57,15 @@ export class NodeStdioPTT {
             });
         });

-        // Trap SIGINT and SIGQUIT
-        process.on('SIGINT', () => {
-            readController.enqueue(new Uint8Array([3]));
-            process.exit(1);
-        });
-        process.stdin.on('end', () => {
-            globalThis.force_eot = true;
-            readController.enqueue(new Uint8Array([4]));
-        });
+        // // Trap SIGINT and SIGQUIT
+        // process.on('SIGINT', () => {
+        //     readController.enqueue(new Uint8Array([3]));
+        //     process.exit(1);
+        // });
+        // process.stdin.on('end', () => {
+        //     globalThis.force_eot = true;
+        //     readController.enqueue(new Uint8Array([4]));
+        // });
     }

     on (name, listener) {