Skip to content

Commit

Permalink
copy command-line/ from inet-js
Browse files Browse the repository at this point in the history
  • Loading branch information
xieyuheng committed Nov 15, 2023
1 parent 3058205 commit ec30714
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 1 deletion.
1 change: 0 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
copy command-line/ from inet-js
setup the `run` command

# net
Expand Down
44 changes: 44 additions & 0 deletions src/command-line/commands/Default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Command, CommandRunner } from "@xieyuheng/command-line"
import { ty } from "@xieyuheng/ty"
import { app } from "../../app/index"
import * as Commands from "../commands"

type Args = { path?: string }
type Opts = { help?: boolean; version?: boolean }

export class Default extends Command<Args, Opts> {
name = "default"

description = "Run a file"

args = { path: ty.optional(ty.string()) }
opts = {
help: ty.optional(ty.boolean()),
version: ty.optional(ty.boolean()),
}
alias = { help: ["h"], version: ["v"] }

async execute(argv: Args & Opts, runner: CommandRunner): Promise<void> {
if (argv["help"]) {
const command = new Commands.CommonHelp()
await command.execute({}, runner)
return
}

if (argv["version"]) {
console.log(app.config.packageJson.version)
return
}

const path = argv["path"]

if (path === undefined) {
// const dir = process.cwd()
// const command = new Commands.Repl()
// await command.execute({ dir })
} else {
const command = new Commands.Run()
await command.execute({ path })
}
}
}
81 changes: 81 additions & 0 deletions src/command-line/commands/Run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { ParsingError } from "@cicada-lang/partech/lib/errors"
import { Command, CommandRunner } from "@xieyuheng/command-line"
import { ty } from "@xieyuheng/ty"
import fs from "node:fs"
import { relative } from "node:path"
import process from "node:process"
import { Fetcher } from "../../fetcher"
import { Report } from "../../lang/errors/Report"
import { Loader } from "../../loader"
import { createURL } from "../../utils/createURL"

type Args = { path: string }
type Opts = {}

export class Run extends Command<Args, Opts> {
name = "run"

description = "Run an inet program"

args = { path: ty.string() }

// prettier-ignore
help(runner: CommandRunner): string {
const { blue } = this.colors

return [
`Run a file:`,
``,
blue(` ${runner.name} ${this.name} std/datatype/Nat.test.i`),
``,
`Run a URL:`,
``,
blue(` ${runner.name} ${this.name} https://code-of-inet.fidb.app/std/datatype/Nat.test.i`),

``,
].join("\n")
}

async execute(argv: Args & Opts): Promise<void> {
const fetcher = new Fetcher()

fetcher.register("file", {
async fetchText(url) {
if (process.platform === "win32") {
return await fs.promises.readFile(url.pathname.slice(1), "utf8")
} else {
return await fs.promises.readFile(url.pathname, "utf8")
}
},

formatURL(url) {
if (process.platform === "win32") {
return relative(process.cwd(), url.pathname.slice(1)).replaceAll(
"\\",
"/",
)
} else {
return relative(process.cwd(), url.pathname)
}
},
})

const url = createURL(argv.path)
const text = await fetcher.fetchText(url)

try {
const loader = new Loader({ fetcher })
await loader.load(url)
} catch (error) {
if (error instanceof ParsingError) {
console.error(error.report(text))
process.exit(1)
} else if (error instanceof Report) {
console.error(error.format())
process.exit(1)
} else {
throw error
}
}
}
}
6 changes: 6 additions & 0 deletions src/command-line/commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from "@xieyuheng/command-line/lib/commands"
export * from "./Default"
// export * from "./Format"
// export * from "./Parse"
// export * from "./Repl"
export * from "./Run"
15 changes: 15 additions & 0 deletions src/command-line/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { CommandRunner, CommandRunners } from "@xieyuheng/command-line"
import * as Commands from "./commands"

export function createCommandRunner(): CommandRunner {
return new CommandRunners.CommonCommandRunner({
defaultCommand: new Commands.Default(),
commands: [
// new Commands.Repl(),
new Commands.Run(),
// new Commands.Parse(),
// new Commands.Format(),
new Commands.CommonHelp(),
],
})
}
1 change: 1 addition & 0 deletions src/lang/errors/ParsingError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ParsingError } from "@cicada-lang/partech/lib/errors"
39 changes: 39 additions & 0 deletions src/lang/errors/Report.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as pt from "@cicada-lang/partech"
import { Span } from "../span"

export type ReportEntry = {
message: string
context?: {
span: Span
text: string
}
}

export class Report extends Error {
constructor(public entries: Array<ReportEntry> = []) {
super()
}

format(): string {
return this.entries
.map(formatReportEntry)
.map((s) => s.trim())
.join("\n\n")
}

get message(): string {
return this.format()
}
}

function formatReportEntry(entry: ReportEntry): string {
if (entry.context === undefined) {
return entry.message
} else {
return [
entry.message,
"",
pt.report(entry.context.span, entry.context.text),
].join("\n")
}
}
14 changes: 14 additions & 0 deletions src/lang/errors/appendReport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Report, ReportEntry } from "./Report"
import { createReportEntry } from "./createReportEntry"

export function appendReport(error: unknown, entry: ReportEntry): Report {
// NOTE We put the most recent report entry at the end,
// because the end is closer to user's terminal output.

if (error instanceof Report) {
error.entries.push(entry)
return error
}

return new Report([createReportEntry(error), entry])
}
5 changes: 5 additions & 0 deletions src/lang/errors/createReport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Report, ReportEntry } from "./Report"

export function createReport(entry: ReportEntry): Report {
return new Report([entry])
}
13 changes: 13 additions & 0 deletions src/lang/errors/createReportEntry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ReportEntry } from "./Report"

export function createReportEntry(error: unknown): ReportEntry {
if (error instanceof Error) {
return {
message: error.message,
}
} else {
return {
message: String(error),
}
}
}
4 changes: 4 additions & 0 deletions src/lang/errors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./ParsingError"
export * from "./Report"
export * from "./appendReport"
export * from "./createReport"

0 comments on commit ec30714

Please sign in to comment.