Skip to content

Add pre-prompt mode for newly booted board #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 34 additions & 10 deletions repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const CHAR_SNAKE = "🐍";

const MODE_NORMAL = 1;
const MODE_RAW = 2;
const MODE_PRE_PROMPT = 3;

const TYPE_DIR = 16384;
const TYPE_FILE = 32768;
Expand All @@ -24,11 +25,13 @@ const PROMPT_CHECK_INTERVAL = 50;

const REGEX_PROMPT_RAW_MODE = /raw REPL; CTRL-B to exit/;
const REGEX_PROMPT_NORMAL_MODE = />>> /;
const REGEX_PRE_PROMPT = /Press any key to enter the REPL./;

const modes = [
"Unknown",
"Normal",
"Raw",
"Pre-Prompt",
];

// Class to use python code to get file information
Expand Down Expand Up @@ -89,7 +92,7 @@ with open("${path}", "wb") as f:
if (modificationTime) {
code += `os.utime("${path}", (os.path.getatime("${path}"), ${modificationTime}))\n`;
}
await this._repl.execRawMode(code);
await this._repl.runCode(code);
}

async _writeTextFile(path, contents, offset=0, modificationTime=null) {
Expand All @@ -106,7 +109,7 @@ with open("${path}", "w") as f:
if (modificationTime) {
code += `os.utime("${path}", (os.path.getatime("${path}"), ${modificationTime}))\n`;
}
await this._repl.execRawMode(code);
await this._repl.runCode(code);
}

// Write a file to the device path with contents beginning at offset. Modification time can be set and if raw is true, contents is written as binary
Expand All @@ -130,7 +133,7 @@ with open("${path}", "rb") as f:
byte_string = f.read()
print(binascii.b2a_base64(byte_string, False))
`;
let result = await this._repl.execRawMode(code);
let result = await this._repl.runCode(code);
if (this._checkReplErrors()) {
return null;
}
Expand Down Expand Up @@ -160,7 +163,7 @@ with open("${path}", "rb") as f:
with open("${path}", "r") as f:
print(f.read())
`;
let result = await this._repl.execRawMode(code);
let result = await this._repl.runCode(code);
if (await this._checkReplErrors()) {
return null;
}
Expand Down Expand Up @@ -204,7 +207,7 @@ for item in contents:
result = os.stat("${path}" + item)
print(item, result[0], result[6], result[9])
`;
const result = await this._repl.execRawMode(code);
const result = await this._repl.runCode(code);

let contents = [];
if (!result) {
Expand Down Expand Up @@ -233,7 +236,7 @@ try:
except:
print(False)
`;
let result = await this._repl.execRawMode(code);
let result = await this._repl.runCode(code);
let isReadOnly = result.match("True") != null;
this._repl.terminalOutput = true;

Expand All @@ -247,7 +250,7 @@ except:
if (modificationTime) {
code += `os.utime("${path}", (os.path.getatime("${path}"), ${modificationTime}))\n`;
}
await this._repl.execRawMode(code);
await this._repl.runCode(code);
this._checkReplErrors();
this._repl.terminalOutput = true;
}
Expand All @@ -264,7 +267,7 @@ if stat[0] == ${TYPE_FILE}:
else:
os.rmdir("${path}")
`;
await this._repl.execRawMode(code);
await this._repl.runCode(code);
this._checkReplErrors();
this._repl.terminalOutput = true;
}
Expand All @@ -279,7 +282,7 @@ else:
import os
os.rename("${oldPath}", "${newPath}")
`;
await this._repl.execRawMode(code);
await this._repl.runCode(code);
let error = this._checkReplErrors();
this._repl.terminalOutput = true;
return !error;
Expand Down Expand Up @@ -457,9 +460,21 @@ export class REPL {

const rawModRegex = new RegExp(REGEX_PROMPT_RAW_MODE, 'g');
const normalModRegex = new RegExp(REGEX_PROMPT_NORMAL_MODE, 'g');
const prePromptRegex = new RegExp(REGEX_PRE_PROMPT, 'g');

let lastRawPosition = this._findLastRegexPosition(rawModRegex, buffer);
let lastNormalPosition = this._findLastRegexPosition(normalModRegex, buffer);
let lastPrePromptPosition = this._findLastRegexPosition(prePromptRegex, buffer);

if (lastPrePromptPosition > lastNormalPosition && lastPrePromptPosition > lastRawPosition) {
this._mode = MODE_PRE_PROMPT;
if (DEBUG) {
console.log("Pre-Prompt Detected");
}
this._serialInputBuffer.movePointer(lastPrePromptPosition);
await this.serialTransmit(CHAR_CTRL_C);
return;
}

if (lastRawPosition > lastNormalPosition) {
this._mode = MODE_RAW;
Expand All @@ -471,6 +486,9 @@ export class REPL {

// If no mode changes detected, we will assume normal mode with code running
if (!this._mode) {
if (DEBUG) {
console.log("No mode detected. Restarting Device.");
}
await this.softRestart();
await this.serialTransmit(CHAR_CTRL_C);
await this._sleep(1000);
Expand Down Expand Up @@ -568,6 +586,8 @@ export class REPL {
console.log("REPL at Normal Mode prompt");
}
this._pythonCodeRunning = false;
} else {
console.log("Normal Prompt not detected.");
}
}

Expand Down Expand Up @@ -652,7 +672,7 @@ export class REPL {
await this._detectCurrentMode();
await this._sleep(100);
}
}, 1000
}, 3000
);
} catch (error) {
console.log("Awaiting mode change timed out.");
Expand All @@ -662,6 +682,9 @@ export class REPL {
// Raw mode allows code execution without echoing back to the terminal
async _enterRawMode() {
if (this._mode == MODE_RAW) {
if (DEBUG) {
console.log("Already in Raw Mode");
}
await this._exitRawMode();
}
await this._waitForModeChange(MODE_RAW, CHAR_CTRL_A);
Expand Down Expand Up @@ -725,6 +748,7 @@ export class REPL {
console.error("Default serial transmit function called. Message: " + msg);
throw new Error("REPL serialTransmit must be connected to an external transmit function");
} else {
console.log("Transmitting: " + msg);
return await this.serialTransmit(msg);
}
}
Expand Down