From f2c4eacc6f7984f3411f19ee618013500dcf1ee2 Mon Sep 17 00:00:00 2001 From: panzerstadt Date: Sun, 26 Nov 2023 15:18:43 +0900 Subject: [PATCH] ffi: visit: opens new tab --- components/interpreter/interface.tsx | 2 ++ components/interpreter/program.ts | 10 ++++++++++ components/interpreter/useRedirect.ts | 20 +++++++++++++++++++ .../foreignfunctions/blogInterface.ts | 16 +++++++++++++++ programs/babyjs/interpreters/interpreter.ts | 5 +++-- programs/babyjs/types.ts | 1 + 6 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 components/interpreter/useRedirect.ts diff --git a/components/interpreter/interface.tsx b/components/interpreter/interface.tsx index 1b43c01..77c3bb6 100644 --- a/components/interpreter/interface.tsx +++ b/components/interpreter/interface.tsx @@ -4,6 +4,7 @@ import { useHistory } from "./useHistory"; import { Tips } from "./tips"; import { useStd } from "./useStd"; import { Container } from "../terminals/Neumorphic/Container"; +import { useRedirect } from "./useRedirect"; export type Line = { type: LineType; value: string }; type LineType = StdEnvs | "usr" | "usr-tmp"; @@ -27,6 +28,7 @@ export const Interpreter: React.FC = ({ focus }) => { useStd(program, "debug", setLines, () => scrollToBottom()); // vvvv useStd(program, "err", setLines, () => scrollToBottom(), true); useStd(program, "info", setLines, () => scrollToBottom(), true); + useRedirect(program, true); const [userHistory, { back, forward, add, addBatch }] = useHistory(); useEffect(() => { diff --git a/components/interpreter/program.ts b/components/interpreter/program.ts index 16ff421..e5bd284 100644 --- a/components/interpreter/program.ts +++ b/components/interpreter/program.ts @@ -12,6 +12,8 @@ export class Program { stddebug = ""; stdenv = ""; + urlredirect = ""; + constructor() { this.interpreter = new BabyJs(); this.interpreter.setLogger(this.output()); @@ -60,6 +62,9 @@ export class Program { .map((s) => `${this.timestamp()}:${phase}:${s}\n`) .join(""); }, + visit: (url: string) => { + this.urlredirect = `${this.timestamp()}:${url}`; + }, }; } @@ -158,6 +163,11 @@ thrice(fn (a) { print a; }); +// you might have also realised.. uh.. there are no: +- arrays +- objects +- classes (yet) + // come back from time to time to see this list grow! ----------------- diff --git a/components/interpreter/useRedirect.ts b/components/interpreter/useRedirect.ts new file mode 100644 index 0000000..7b0676c --- /dev/null +++ b/components/interpreter/useRedirect.ts @@ -0,0 +1,20 @@ +import { MutableRefObject, useEffect } from "react"; +import { Program } from "./program"; + +const removeTimestamp = (str: string) => { + const length = Date.now().toString().length + ":".length; + return str.slice(length); +}; + +export const useRedirect = (ref: MutableRefObject, newtab?: boolean) => { + const currentRef = ref.current?.urlredirect; + useEffect(() => { + if (!currentRef) return; + + let path = removeTimestamp(currentRef); + if (!path.startsWith("http")) { + path = `https://${path}`; + } + window.open(path, newtab ? "_blank" : "_self"); + }, [currentRef, newtab]); +}; diff --git a/programs/babyjs/functions/foreignfunctions/blogInterface.ts b/programs/babyjs/functions/foreignfunctions/blogInterface.ts index 2a927ab..1d66cc1 100644 --- a/programs/babyjs/functions/foreignfunctions/blogInterface.ts +++ b/programs/babyjs/functions/foreignfunctions/blogInterface.ts @@ -2,6 +2,7 @@ import { Callable } from "../../callable"; import { Interpreter } from "../../interpreters/interpreter"; import data from "../../../blog/data.json"; +import { RuntimeError } from "../../errors"; export class Ls extends Callable { arity(): number { @@ -11,3 +12,18 @@ export class Ls extends Callable { return data.blogposts; } } + +export class Visit extends Callable { + arity(): number { + return 1; + } + call(interpreter: Interpreter, _arguments: Object[]): Object { + const path = _arguments[0]; + if (!path || typeof path !== "string") { + throw new RuntimeError(`Please enter a blogpost path to visit.`); + } + + interpreter.logger.visit?.(path); + return {}; + } +} diff --git a/programs/babyjs/interpreters/interpreter.ts b/programs/babyjs/interpreters/interpreter.ts index 94d61cc..0dd3c2b 100644 --- a/programs/babyjs/interpreters/interpreter.ts +++ b/programs/babyjs/interpreters/interpreter.ts @@ -8,7 +8,7 @@ import { PrintStyle, printAST } from "./pprinter"; import { isTruthy } from "../constants"; import { Callable } from "../callable"; import { Clock } from "../functions/foreignfunctions/clock"; -import { Ls } from "../functions/foreignfunctions/blogInterface"; +import { Ls, Visit } from "../functions/foreignfunctions/blogInterface"; import { Function } from "../functions/basefunction"; import { Return } from "../return"; @@ -26,12 +26,13 @@ export class Interpreter { private loop_upper_bound = 10_000; readonly globals = new Environment(); private environment = this.globals; - logger: Console | LoggerType = console; + logger: LoggerType = console; constructor() { // FFI (this is where we allow the users to work with files, read user input etc) this.globals.define("clock", new Clock()); this.globals.define("ls", new Ls()); + this.globals.define("visit", new Visit()); } public setLogger(newLogger: LoggerType) { diff --git a/programs/babyjs/types.ts b/programs/babyjs/types.ts index c1ff63f..3b94ce9 100644 --- a/programs/babyjs/types.ts +++ b/programs/babyjs/types.ts @@ -75,6 +75,7 @@ export interface LoggerType { error: (phase: Phase, str: string) => void; debug?: (phase: Phase, ...strs: string[]) => void; environment?: (...strs: string[]) => void; + visit?: (str: string) => void; } export type Phase = "scan" | "parse" | "interpret";