Skip to content

Commit

Permalink
code refactoring: moved some code from "main" into other classes; ren…
Browse files Browse the repository at this point in the history
…amed "prompt" to "input"
  • Loading branch information
benchmarko committed Feb 20, 2025
1 parent 10675dc commit 81d4c8c
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 74 deletions.
2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="locobasic.css">
<title>LocoBasic v0.1.41</title>
<title>LocoBasic v0.1.42</title>
</head>

<body>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "locobasic",
"version": "0.1.41",
"version": "0.1.42",
"description": "# LocoBasic - Loco BASIC",
"type": "commonjs",
"scripts": {
Expand Down
18 changes: 9 additions & 9 deletions src/BasicVmBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@ export class BasicVmBrowser extends BasicVmCore {
this.ui.setOutputText("");
}

/**
* Adds a message to the output text.
* @param msg - The message to print.
*/
public fnOnPrint(msg: string): void {
this.ui.addOutputText(msg);
}

/**
* Prompts the user with a message and returns the input.
* @param msg - The message to prompt.
* @returns A promise that resolves to the user input or null if canceled.
*/
public async fnOnPrompt(msg: string): Promise<string | null> {
public async fnOnInput(msg: string): Promise<string | null> {
const input = this.ui.prompt(msg);
return Promise.resolve(input);
}

/**
* Adds a message to the output text.
* @param msg - The message to print.
*/
public fnOnPrint(msg: string): void {
this.ui.addOutputText(msg);
}

/**
* Gets the pen color by index.
* @param num - The index of the pen color.
Expand Down
18 changes: 9 additions & 9 deletions src/BasicVmCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ export class BasicVmCore implements IVmAdmin {
// override
}

protected fnOnPrint(_msg: string): void { // eslint-disable-line @typescript-eslint/no-unused-vars
protected async fnOnInput(_msg: string): Promise<string | null> { // eslint-disable-line @typescript-eslint/no-unused-vars
// override
return "";
}

protected async fnOnPrompt(_msg: string): Promise<string | null> { // eslint-disable-line @typescript-eslint/no-unused-vars
protected fnOnPrint(_msg: string): void { // eslint-disable-line @typescript-eslint/no-unused-vars
// override
return "";
}

protected fnGetPenColor(_num: number): string { // eslint-disable-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -114,6 +114,11 @@ export class BasicVmCore implements IVmAdmin {
return Promise.resolve("");
}

public input(msg: string): Promise<string | null> {
this.flush();
return this.fnOnInput(msg);
}

public mode(num: number): void {
this.currMode = num;
this.cls();
Expand All @@ -124,7 +129,7 @@ export class BasicVmCore implements IVmAdmin {
this.output += this.fnGetPaperColor(n);
this.currPaper = n;
}
};
}

public pen(n: number): void {
if (n !== this.currPen) {
Expand All @@ -137,11 +142,6 @@ export class BasicVmCore implements IVmAdmin {
this.output += args.join('');
}

public prompt(msg: string): Promise<string | null> {
this.flush();
return this.fnOnPrompt(msg);
};

public getEscape(): boolean {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/BasicVmNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class BasicVmNode extends BasicVmCore {
console.log(msg.replace(/\n$/, ""));
}

public async fnOnPrompt(msg: string): Promise<string> {
public async fnOnInput(msg: string): Promise<string> {
console.log(msg);
return Promise.resolve("");
}
Expand Down
5 changes: 2 additions & 3 deletions src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export interface IVm {
flush(): void;
graphicsPen(num: number): void;
inkey$(): Promise<string>;
input(_msg: string): Promise<string | null>;
mode(num: number): void;
paper(color: number): void;
pen(color: number): void;
print(_msg: string): void;
prompt(_msg: string): Promise<string | null>;
getEscape(): boolean;
}

Expand Down Expand Up @@ -50,8 +50,7 @@ export interface INodeParts {
}

export interface IUI {
parseUri(urlQuery: string, config: Record<string, ConfigEntryType>): string[];
onWindowLoad(event: Event): void;
onWindowLoadContinue(core: ICore): void;
getEscape(): boolean;
addOutputText(value: string): void;
setOutputText(value: string): void;
Expand Down
32 changes: 14 additions & 18 deletions src/NodeParts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ICore, IVm } from "./Interfaces";
import { BasicVmNode } from "./BasicVmNode";

interface NodeFs {
promises: {
Expand Down Expand Up @@ -38,28 +39,22 @@ const dummyVm: DummyVm = {
flush() { if (this._output) { console.log(this._output); this._output = ""; } },
graphicsPen(num: number) { this.debug("graphicsPen:", num); },
async inkey$() { return Promise.resolve(""); },
async input(msg: string) { console.log(msg); return ""; },
mode(num: number) { this.debug("mode:", num); },
paper(num: number) { this.debug("paper:", num); },
pen(num: number) { this.debug("pen:", num); },
print(...args: (string | number)[]) { this._output += args.join(''); },
async prompt(msg: string) { console.log(msg); return ""; },
getEscape() { return false; },
getEscape() { return false; }
};

export class NodeParts {
private core: ICore;
private nodeFs?: NodeFs;
private modulePath: string;
private modulePath = "";
private nodeVm?: NodeVm;
private nodeReadline?: NodeReadline;
private readonly keyBuffer: string[] = []; // buffered pressed keys
private escape = false;

constructor(core: ICore) {
this.core = core;
this.modulePath = "";
}

private async nodeReadFile(name: string): Promise<string> {
if (!this.nodeFs) {
this.nodeFs = require("fs") as NodeFs;
Expand Down Expand Up @@ -170,8 +165,7 @@ export class NodeParts {
return this.escape;
}

private start(input: string): Promise<void> | undefined {
const core = this.core;
private start(core: ICore, input: string): Promise<void> | undefined {
const actionConfig = core.getConfigObject().action;
if (input !== "") {
core.setOnCheckSyntax((s: string) => Promise.resolve(this.nodeCheckSyntax(s)));
Expand All @@ -198,15 +192,17 @@ export class NodeParts {
}
}

public async nodeMain(): Promise<void> {
const core = this.core;
const config = this.core.getConfigObject();
public async nodeMain(core: ICore): Promise<void> {
core.setVm(new BasicVmNode(this));
const config = core.getConfigObject();
core.parseArgs(global.process.argv.slice(2), config);

let input = config.input || "";

if (config.fileName) {
return this.keepRunning(async () => {
input = await this.nodeReadFile(config.fileName);
this.start(input);
this.start(core, input);
}, 5000);
} else {
if (config.example) {
Expand All @@ -217,16 +213,16 @@ export class NodeParts {
addItem: core.addItem
});

const exampleScript = this.core.getExample(config.example);
const exampleScript = core.getExample(config.example);
if (!exampleScript) {
console.error(`ERROR: Example '${config.example}' not found.`);
return;
}
input = exampleScript;
this.start(input);
this.start(core, input);
}, 5000);
}
this.start(input);
this.start(core, input);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Semantics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ function getCodeSnippets() {
},
input: async function input(msg: string, isNum: boolean) {
await frame();
const input = await _o.prompt(msg);
const input = await _o.input(msg);
if (input === null) {
throw new Error("Input canceled");
throw new Error("INFO: Input canceled");
} else if (isNum && isNaN(Number(input))) {
throw new Error("Invalid number input");
} else {
Expand Down
30 changes: 18 additions & 12 deletions src/UI/UI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,14 @@ const workerFn = (): void => {
};

export class UI implements IUI {
private core: ICore;
private core?: ICore;
private basicCm?: Editor;
private compiledCm?: Editor;
private readonly keyBuffer: string[] = []; // buffered pressed keys
private escape = false;

private static getErrorEvent?: (s: string) => Promise<PlainErrorEventType>;

constructor(core: ICore) {
this.core = core;
}

private debounce<T extends (...args: unknown[]) => void | Promise<void>>(func: T, fngetDelay: () => number): (...args: Parameters<T>) => void {
let timeoutId: ReturnType<typeof setTimeout>;
return function (this: unknown, ...args: Parameters<T>) {
Expand Down Expand Up @@ -94,6 +90,11 @@ export class UI implements IUI {
return colorsForPens.map((color) => `<span style="color: ${color}">`);
}

/**
* Prompts the user with a message and returns the input.
* @param msg - The message to prompt.
* @returns A promise that resolves to the user input or null if canceled.
*/
public prompt(msg: string): string | null {
const input = window.prompt(msg);
return input;
Expand Down Expand Up @@ -137,7 +138,7 @@ export class UI implements IUI {
const basicText = document.getElementById("basicText") as HTMLTextAreaElement;
const compiledText = document.getElementById("compiledText") as HTMLTextAreaElement;
const input = this.basicCm ? this.basicCm.getValue() : basicText.value;
const compiledScript = this.core.compileScript(input) || "";
const compiledScript = this.core?.compileScript(input) || "";

if (this.compiledCm) {
this.compiledCm.setValue(compiledScript);
Expand Down Expand Up @@ -172,7 +173,7 @@ export class UI implements IUI {
private onExampleSelectChange(event: Event): void {
const exampleSelect = event.target as HTMLSelectElement;
const basicText = document.getElementById("basicText") as HTMLTextAreaElement;
const value = this.core.getExample(exampleSelect.value) || "";
const value = this.core?.getExample(exampleSelect.value) || "";
this.setOutputText("");

if (this.basicCm) {
Expand Down Expand Up @@ -304,7 +305,8 @@ export class UI implements IUI {
return decoded;
}

public parseUri(urlQuery: string, config: Record<string, ConfigEntryType>): string[] {
private parseUri(config: Record<string, ConfigEntryType>): string[] {
const urlQuery = window.location.search.substring(1);
const rSearch = /([^&=]+)=?([^&]*)/g;
const args: string[] = [];
let match: RegExpExecArray | null;
Expand All @@ -320,7 +322,13 @@ export class UI implements IUI {
return args;
}

public onWindowLoad(_event: Event): void { // eslint-disable-line @typescript-eslint/no-unused-vars
public onWindowLoadContinue(core: ICore): void {
this.core = core;
const config = core.getConfigObject();
const args = this.parseUri(config);
core.parseArgs(args, config);
core.setOnCheckSyntax((s: string) => Promise.resolve(this.checkSyntax(s)));

const basicText = window.document.getElementById("basicText") as HTMLTextAreaElement;
basicText.addEventListener('change', () => this.onbasicTextChange());

Expand All @@ -342,8 +350,6 @@ export class UI implements IUI {
const helpButton = window.document.getElementById("helpButton") as HTMLButtonElement;
helpButton.addEventListener('click', () => this.onHelpButtonClick());

const config = this.core.getConfigObject();

const outputText = window.document.getElementById("outputText") as HTMLPreElement;
outputText.addEventListener("keydown", (event) => this.onOutputTextKeydown(event), false);

Expand All @@ -363,7 +369,7 @@ export class UI implements IUI {
}

UI.asyncDelay(() => {
const exampleObject = this.core.getExampleObject() || {};
const exampleObject = this.core?.getExampleObject() || {};
this.setExampleSelectOptions(exampleObject);

const example = config.example;
Expand Down
22 changes: 4 additions & 18 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@ import type { ICore, IUI } from "./Interfaces";
import { Core } from "./Core";
import { NodeParts } from "./NodeParts";
import { BasicVmBrowser } from "./BasicVmBrowser";
import { BasicVmNode } from "./BasicVmNode";

interface WindowProperties {
cpcBasic: {
addItem: (key: string, input: string | (() => void)) => void
};
location: {
search: string
};
locobasicUI: {
UI: {
new(core: ICore): IUI
new(): IUI
}
};
onload: (event: Event) => void;
prompt: (msg: string) => string;
}

declare const window: WindowProperties | undefined;
Expand All @@ -37,19 +32,10 @@ if (typeof window !== "undefined") {
window.cpcBasic = { addItem: core.addItem };
window.onload = () => {
const UI = window.locobasicUI.UI; // we expect that it is already loaded in the HTML page
const ui = new UI(core);
const ui = new UI();
core.setVm(new BasicVmBrowser(ui));

const config = core.getConfigObject();
const args = ui.parseUri(window.location.search.substring(1), config);
core.parseArgs(args, config);

core.setOnCheckSyntax((s: string) => Promise.resolve(ui.checkSyntax(s)));
ui.onWindowLoad(new Event("onload"));
ui.onWindowLoadContinue(core);
};
} else { // node.js
const nodeParts = new NodeParts(core);
core.setVm(new BasicVmNode(nodeParts));
core.parseArgs(global.process.argv.slice(2), core.getConfigObject());
nodeParts.nodeMain();
new NodeParts().nodeMain(core);
}

0 comments on commit 81d4c8c

Please sign in to comment.