This commit is contained in:
Chris Wanstrath 2025-09-20 11:27:12 -07:00
parent 84c182a17d
commit d80735d120
10 changed files with 72 additions and 11 deletions

View File

@ -13,6 +13,10 @@
font-size: var(--cli-font-size); font-size: var(--cli-font-size);
} }
#command-line[data-extended="true"] {
border: 1px solid red;
}
#command-prompt { #command-prompt {
position: absolute; position: absolute;
top: 10px; top: 10px;
@ -24,14 +28,13 @@
background: transparent; background: transparent;
padding: var(--cli-spacing-vertical) var(--cli-element-spacing-horizontal); padding: var(--cli-spacing-vertical) var(--cli-element-spacing-horizontal);
min-height: 1.2em;
resize: none; resize: none;
overflow: hidden; overflow: hidden;
font: inherit; font: inherit;
letter-spacing: inherit; letter-spacing: inherit;
line-height: inherit; line-height: inherit;
height: var(--cli-height); min-height: var(--cli-height);
width: 100%; width: 100%;
box-shadow: none; box-shadow: none;
box-sizing: border-box; box-sizing: border-box;
@ -54,13 +57,12 @@
background: transparent; background: transparent;
resize: none; resize: none;
overflow: hidden; overflow: hidden;
min-height: 1.2em;
height: auto; height: auto;
font: inherit; font: inherit;
letter-spacing: inherit; letter-spacing: inherit;
line-height: inherit; line-height: inherit;
height: var(--cli-height); min-height: var(--cli-height);
width: 100%; width: 100%;
box-shadow: none; box-shadow: none;
box-sizing: border-box; box-sizing: border-box;

View File

@ -1,3 +1,7 @@
////
// dom helpers and cached elements
//
// finds an element by ID // finds an element by ID
export const $ = (id: string): HTMLElement | null => export const $ = (id: string): HTMLElement | null =>
document.getElementById(id) document.getElementById(id)
@ -10,4 +14,5 @@ export const $$ = (tag: string, innerHTML = ""): HTMLElement => {
} }
// elements we know will be there... right? // elements we know will be there... right?
export const cmdTextbox = document.getElementById("command-textbox")! export const cmdLine = document.getElementById("command-line") as HTMLDivElement
export const cmdTextbox = document.getElementById("command-textbox") as HTMLTextAreaElement

View File

@ -1,3 +1,7 @@
////
// try to keep the command textbox focused at all times
//
import { cmdTextbox } from "./dom.js" import { cmdTextbox } from "./dom.js"
export function initFocus() { export function initFocus() {

28
src/js/input.ts Normal file
View File

@ -0,0 +1,28 @@
////
// this file controls the command textbox
//
import { cmdTextbox, cmdLine } from "./dom.js"
export function initInput() {
cmdTextbox.addEventListener("keydown", inputHandler)
}
function inputHandler(event: KeyboardEvent) {
const target = event.target as HTMLElement
if (target?.id !== cmdTextbox.id) return
console.log(event.key)
if (event.key === "Tab") {
event.preventDefault()
} else if (event.shiftKey && event.key === "Enter") {
cmdTextbox.rows += 1
cmdLine.dataset.extended = "true"
console.log(cmdTextbox.value)
} else if (event.key === "Enter") {
cmdTextbox.value = ""
cmdTextbox.rows = 1
cmdLine.dataset.extended = "false"
event.preventDefault()
}
}

View File

@ -1,10 +1,12 @@
import { initResize } from "./resize.js" import { initResize } from "./resize.js"
import { initInput } from "./input.js"
import { initFocus } from "./focus.js" import { initFocus } from "./focus.js"
import { startVramCounter } from "./vram.js" import { startVramCounter } from "./vram.js"
import { startConnection } from "./websocket.js" import { startConnection } from "./websocket.js"
initFocus() initFocus()
initResize() initResize()
initInput()
startConnection() startConnection()
startVramCounter() startVramCounter()

View File

@ -1,3 +1,7 @@
////
// maintain the two video modes: cinema and tall
//
const content = document.getElementById("content")! const content = document.getElementById("content")!
export function initResize() { export function initResize() {

View File

@ -1,5 +1,5 @@
// ////
// vram // fun vram counter at startup
// //
import { $ } from "./dom.js" import { $ } from "./dom.js"

View File

@ -1,3 +1,9 @@
////
// the terminal communicates with the shell via websockets
//
import type { Message } from "../shared/message.js"
let ws: WebSocket | null = null let ws: WebSocket | null = null
// open our websocket connection // open our websocket connection
@ -13,8 +19,8 @@ export function startConnection() {
} }
// send any message // send any message
export function send(obj: any) { export function send(msg: Message) {
ws?.readyState === 1 && ws.send(JSON.stringify(obj)) ws?.readyState === 1 && ws.send(JSON.stringify(msg))
} }
// close it... plz don't do this, though // close it... plz don't do this, though

View File

@ -30,8 +30,12 @@ app.use("*", async (c, next) => {
console.log(fn(`${c.res.status} ${c.req.method} ${c.req.url} (${end - start}ms)`)) console.log(fn(`${c.res.status} ${c.req.method} ${c.req.url} (${end - start}ms)`))
}) })
app.get("/js/:path{.+}", async c => { app.on("GET", ["/js/:path{.+}", "/shared/:path{.+}"], async c => {
const path = "./src/js/" + c.req.param("path") const path = "./src/" + c.req.path.replace("..", ".")
// path must end in .js
if (!path.endsWith(".js")) return c.text("File not found", 404)
const ts = path.replace(".js", ".ts") const ts = path.replace(".js", ".ts")
if (isFile(ts)) { if (isFile(ts)) {
return new Response(await transpile(ts), { headers: { "Content-Type": "text/javascript" } }) return new Response(await transpile(ts), { headers: { "Content-Type": "text/javascript" } })

6
src/shared/message.ts Normal file
View File

@ -0,0 +1,6 @@
export type Message = {
session: string
id: string
type: "output"
data: any
}