From 3afa686604a070caed11a04b5e9c294c4faaa8ac Mon Sep 17 00:00:00 2001 From: David Lee Date: Thu, 31 Aug 2023 10:13:30 +1000 Subject: [PATCH] thank fuck I finally seem to have a repl working https://nodejs.org/api/repl.html#repl https://github.com/TypeStrong/ts-node/issues/1007 some real jank around ESM vs CommonJS - we seem to have to use .js file extensions in src/repl.ts ;; let's check if we CAN use .js everywhere in our .ts files at least that would be consistent. --- package.json | 4 +++- src/parser.ts | 57 +++++++++++++++++++++++++-------------------------- src/repl.ts | 28 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 30 deletions(-) create mode 100644 src/repl.ts diff --git a/package.json b/package.json index a9e8b4f..09fbab8 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,9 @@ "prettier-check": "pnpm exec prettier --config .prettierrc -c 'src/**/*.ts' 'test/**/*.ts'", "prettier-watch": "pnpm exec onchange 'src/**/*.ts' 'test/**/*.ts' -- pnpm exec prettier --config .prettierrc -w {{changed}}", "prep": "pnpm run prettier & pnpm run lint && pnpm test", - "deps": "pnpm exec depcruise -c .dependency-cruiser.cjs -I src -T dot . | dot -T svg > graph.svg && open -a Arc graph.svg" + "deps": "pnpm exec depcruise -c .dependency-cruiser.cjs -I src -T dot . | dot -T svg > graph.svg && open -a Arc graph.svg", + "ex": "node --loader ts-node/esm src/*.ts", + "repl": "node --loader ts-node/esm src/repl.ts" }, "husky": { "hooks": { diff --git a/src/parser.ts b/src/parser.ts index 9d2bb9a..92e77af 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,23 +1,16 @@ -// import * as R from 'ramda' -// import { parseISO } from 'date-fns' -// import { parseJSON } from 'date-fns/fp' - -export function argsFromArgv(argv: string[]): string[] { - return argv.slice(2) // .filter((arg) => !(arg === '--')) -} enum TokenKind { - Command = 'commands', - Filter = 'filters', + Command = 'commands', + Filter = 'filters', Modifier = 'modifiers', - Ids = 'filters.ids', + Ids = 'filters.ids', } export type CommandConfig = { - name: string - aliases: string[] - expect: TokenKind[] - subcommands: CommandConfig[] + name: string + aliases: string[] + expect: TokenKind[] + subcommands: CommandConfig[] confirmation?: boolean } @@ -73,7 +66,6 @@ const CommandConfigs: CommandConfig[] = [ ] // no reason it should change Object.freeze(CommandConfigs) -const defaultCommandName = 'list' export type CommandConfigList = { [key: string]: CommandConfig @@ -84,15 +76,15 @@ export type TagSet = { [key: string]: string[] } -// schema? +// should use a typebox schema? export type ParsedCommandArgs = { filters: { - ids: number[] - tags: TagSet + ids: number[] + tags: TagSet words: string[] } modifiers: { - tags: TagSet + tags: TagSet words: string[] } } @@ -116,12 +108,12 @@ function buildState(tokens: string[]): State { command: [], processedIndices: [], filters: { - ids: [], - tags: {}, + ids: [], + tags: {}, words: [], }, modifiers: { - tags: {}, + tags: {}, words: [], }, } as State @@ -134,19 +126,20 @@ function extractCommand(state: State): ParsedCommand { return parsed } +const DefaultCommandName = 'list' + // https://taskwarrior.org/docs/syntax/ // task - +// // first, find the first thing that looks like a command // everything before it is a filter (ids, etc) // everything after it is a modification - export function parse(tokens: string[]): ParsedCommand { let state = buildState(tokens) state = parseCommands(state) if (state.command.length === 0) - state.command.push(defaultCommandName) + state.command.push(DefaultCommandName) // how we interpret remaining tokens depends on whether they're // before or after a command @@ -187,16 +180,14 @@ function parseCommands(state: State): State { // we've previously found a command, but matched no valid subcommand break } - return state // TODO rather than mutate the state, return an immutable update + return state // FIXME rather than mutate the state, return an immutable update } export function parseArgs(argv: string[]): ParsedCommand { return parse(argsFromArgv(argv)) } -function commandAliases( - cmds: CommandConfig[] = CommandConfigs, -): CommandConfigList { +function commandAliases(cmds: CommandConfig[]=CommandConfigs): CommandConfigList { const o: CommandConfigList = {} cmds.map((c) => c.aliases.forEach((alias) => { @@ -247,3 +238,11 @@ function recogniseIds(word: string): number[] | null { } // function recogniseTags() +// function recognisePriority() +// function recogniseParent() + +// utility functions + +export function argsFromArgv(argv: string[]): string[] { + return argv.slice(2) // .filter((arg) => !(arg === '--')) +} diff --git a/src/repl.ts b/src/repl.ts new file mode 100644 index 0000000..1117280 --- /dev/null +++ b/src/repl.ts @@ -0,0 +1,28 @@ +import * as repl from 'node:repl' +import * as E from './entry.js' +import { Value } from '@sinclair/typebox/value' + +const replServer = repl.start('> ') +replServer.context.E = E +replServer.context.Value = Value + + +// import repl from "repl"; +// import ts from "typescript"; +// import * as tsnode from "ts-node"; + +// // Create a ts-node replService +// const replService: tsnode.ReplService = tsnode.createRepl() +// const service = tsnode.create({ ...replService.evalAwarePartialHost }) +// service.ts = ts; +// replService.setService(service) + +// // create a node-repl server +// const replServer = repl.start({ +// prompt: "→º ", +// ignoreUndefined: true, +// eval: replService.nodeEval, +// }); + +// // setup environment +// replServer.setupHistory(".log", () => {})