commands are Record
This commit is contained in:
parent
9d85418293
commit
6d05b6888f
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
import { commandPath, commands } from "@/commands"
|
import { commandPath, commands } from "@/commands"
|
||||||
|
|
||||||
export default async function (cmd: string): string {
|
export default async function (cmd: string): Promise<string> {
|
||||||
if (!cmd) return "usage: help <command>"
|
if (!cmd) return "usage: help <command>"
|
||||||
|
|
||||||
const path = commandPath(cmd)
|
const path = commandPath(cmd)
|
||||||
|
|
@ -27,9 +27,9 @@ export default async function (cmd: string): string {
|
||||||
return docs.join("\n")
|
return docs.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
async function matchingCommands(cmd: string): string {
|
async function matchingCommands(cmd: string): Promise<string> {
|
||||||
let matched: string[] = []
|
let matched: string[] = []
|
||||||
for (const command of await commands()) {
|
for (const command of Object.keys(await commands())) {
|
||||||
if (command.startsWith(cmd)) matched.push(command)
|
if (command.startsWith(cmd)) matched.push(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
// Manages the commands on disk, in NOSE_ROOT_BIN and NOSE_BIN
|
// Manages the commands on disk, in NOSE_ROOT_BIN and NOSE_BIN
|
||||||
|
|
||||||
import { Glob } from "bun"
|
import { Glob } from "bun"
|
||||||
import { watch } from "fs"
|
import { watch, readFileSync } from "fs"
|
||||||
import { join } from "path"
|
import { join, basename } from "path"
|
||||||
import { isFile } from "./utils"
|
import { isFile } from "./utils"
|
||||||
import { sendAll } from "./websocket"
|
import { sendAll } from "./websocket"
|
||||||
import { expectDir } from "./utils"
|
import { expectDir } from "./utils"
|
||||||
import { unique } from "./shared/utils"
|
import type { Command, Commands } from "./shared/types"
|
||||||
import { projectBin, projectName } from "./project"
|
import { projectBin, projectName } from "./project"
|
||||||
import { DEFAULT_PROJECT, NOSE_DIR, NOSE_ROOT_BIN, NOSE_BIN } from "./config"
|
import { DEFAULT_PROJECT, NOSE_DIR, NOSE_ROOT_BIN, NOSE_BIN } from "./config"
|
||||||
|
|
||||||
|
|
@ -15,24 +15,40 @@ export function initCommands() {
|
||||||
startWatchers()
|
startWatchers()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function commands(project = DEFAULT_PROJECT): Promise<string[]> {
|
export async function commands(project = DEFAULT_PROJECT): Promise<Commands> {
|
||||||
let cmds = (await findCommands(NOSE_BIN))
|
let binCmds = await findCommands(NOSE_BIN)
|
||||||
.concat(await findCommands(NOSE_ROOT_BIN))
|
let rootCmds = await findCommands(NOSE_ROOT_BIN)
|
||||||
|
let projCmds = project === DEFAULT_PROJECT ? new Map : await findCommands(projectBin())
|
||||||
|
|
||||||
if (project !== DEFAULT_PROJECT)
|
return Object.fromEntries(
|
||||||
cmds = cmds.concat(await findCommands(projectBin()))
|
[
|
||||||
|
...Object.entries(binCmds),
|
||||||
return unique(cmds).sort()
|
...Object.entries(rootCmds),
|
||||||
|
...Object.entries(projCmds)
|
||||||
|
]
|
||||||
|
.sort((a, b) => a[0].localeCompare(b[0]))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findCommands(path: string): Promise<string[]> {
|
export async function findCommands(path: string): Promise<Commands> {
|
||||||
const glob = new Glob("**/*.{ts,tsx}")
|
const glob = new Glob("**/*.{ts,tsx}")
|
||||||
let list: string[] = []
|
let obj: Commands = {}
|
||||||
|
|
||||||
for await (const file of glob.scan(path))
|
for await (const file of glob.scan(path))
|
||||||
list.push(file.replace(".tsx", "").replace(".ts", ""))
|
obj[file.replace(/\.tsx?$/, "")] = describeCommand(join(path, file))
|
||||||
|
|
||||||
return list
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
function describeCommand(path: string): Command {
|
||||||
|
const code = readFileSync(path, "utf8")
|
||||||
|
let game = /^export const game = true$/mg.test(code)
|
||||||
|
let browser = /^\/\/\/ ?<reference lib=['"]dom['"]\s*\/mg>$/.test(code)
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: basename(path).replace(/\.tsx?$/, ""),
|
||||||
|
type: game ? "game" : browser ? "browser" : "server"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function commandPath(cmd: string): string | undefined {
|
export function commandPath(cmd: string): string | undefined {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
////
|
////
|
||||||
// temporary hack for browser commands
|
// temporary hack for browser commands
|
||||||
|
|
||||||
import type { CommandOutput } from "../shared/types"
|
import type { CommandOutput, Commands, Command } from "../shared/types"
|
||||||
import { openBrowser } from "./browser"
|
import { openBrowser } from "./browser"
|
||||||
import { scrollback, content } from "./dom"
|
import { scrollback, content } from "./dom"
|
||||||
import { focusInput } from "./focus"
|
import { focusInput } from "./focus"
|
||||||
|
|
@ -12,7 +12,7 @@ import { status } from "./statusbar"
|
||||||
import { setStatus, latestId } from "./scrollback"
|
import { setStatus, latestId } from "./scrollback"
|
||||||
import { currentAppUrl } from "./webapp"
|
import { currentAppUrl } from "./webapp"
|
||||||
|
|
||||||
export const commands: string[] = []
|
export const commands: Commands = {}
|
||||||
|
|
||||||
export const browserCommands: Record<string, (...args: string[]) => void | Promise<void> | CommandOutput> = {
|
export const browserCommands: Record<string, (...args: string[]) => void | Promise<void> | CommandOutput> = {
|
||||||
browse: (url?: string) => {
|
browse: (url?: string) => {
|
||||||
|
|
@ -27,7 +27,7 @@ export const browserCommands: Record<string, (...args: string[]) => void | Promi
|
||||||
"browser-session": () => sessionId,
|
"browser-session": () => sessionId,
|
||||||
clear: () => scrollback.innerHTML = "",
|
clear: () => scrollback.innerHTML = "",
|
||||||
commands: () => {
|
commands: () => {
|
||||||
return { html: "<div>" + commands.map(cmd => `<a href="#help ${cmd}">${cmd}</a>`).join("") + "</div>" }
|
return { html: "<div>" + Object.keys(commands).map(cmd => `<a href="#help ${cmd}">${cmd}</a>`).join("") + "</div>" }
|
||||||
},
|
},
|
||||||
fullscreen: () => document.body.requestFullscreen(),
|
fullscreen: () => document.body.requestFullscreen(),
|
||||||
mode: (mode?: string) => {
|
mode: (mode?: string) => {
|
||||||
|
|
@ -45,9 +45,9 @@ export const browserCommands: Record<string, (...args: string[]) => void | Promi
|
||||||
reload: () => window.location.reload(),
|
reload: () => window.location.reload(),
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cacheCommands(cmds: string[]) {
|
export function cacheCommands(cmds: Commands) {
|
||||||
commands.length = 0
|
for (const key in commands)
|
||||||
commands.push(...cmds)
|
delete commands[key]
|
||||||
commands.push(...Object.keys(browserCommands))
|
|
||||||
commands.sort()
|
Object.assign(commands, cmds)
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ function handleCompletion(e: KeyboardEvent) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const input = cmdInput.value
|
const input = cmdInput.value
|
||||||
|
|
||||||
for (const command of commands) {
|
for (const command of Object.keys(commands)) {
|
||||||
if (command.startsWith(input)) {
|
if (command.startsWith(input)) {
|
||||||
cmdInput.value = command
|
cmdInput.value = command
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
export type Message =
|
export type Message =
|
||||||
| ErrorMessage
|
| ErrorMessage
|
||||||
| InputMessage
|
| InputMessage
|
||||||
|
|
@ -28,7 +29,7 @@ export type ErrorMessage = {
|
||||||
|
|
||||||
export type CommandsMessage = {
|
export type CommandsMessage = {
|
||||||
type: "commands"
|
type: "commands"
|
||||||
data: string[]
|
data: Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AppsMessage = {
|
export type AppsMessage = {
|
||||||
|
|
@ -84,3 +85,10 @@ export type StreamMessage = {
|
||||||
session: string
|
session: string
|
||||||
data: CommandOutput
|
data: CommandOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Commands = Record<string, Command>
|
||||||
|
|
||||||
|
export type Command = {
|
||||||
|
name: string
|
||||||
|
type: "server" | "browser" | "game"
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user