import { parse } from "../flags/mod.ts"; import { readStringDelim } from "../io/bufio.ts"; const { args, exit, stdin } = Deno; type Reader = Deno.Reader; /* eslint-disable-next-line max-len */ // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction. const AsyncFunction = Object.getPrototypeOf(async function(): Promise {}) .constructor; /* eslint-disable max-len */ const HELP_MSG = `xeval Run a script for each new-line or otherwise delimited chunk of standard input. Print all the usernames in /etc/passwd: cat /etc/passwd | deno -A https://deno.land/std/examples/xeval.ts "a = $.split(':'); if (a) console.log(a[0])" A complicated way to print the current git branch: git branch | deno -A https://deno.land/std/examples/xeval.ts -I 'line' "if (line.startsWith('*')) console.log(line.slice(2))" Demonstrates breaking the input up by space delimiter instead of by lines: cat LICENSE | deno -A https://deno.land/std/examples/xeval.ts -d " " "if ($ === 'MIT') console.log('MIT licensed')", USAGE: deno -A https://deno.land/std/examples/xeval.ts [OPTIONS] OPTIONS: -d, --delim Set delimiter, defaults to newline -I, --replvar Set variable name to be used in eval, defaults to $ ARGS: `; /* eslint-enable max-len */ export type XevalFunc = (v: string) => void; export interface XevalOptions { delimiter?: string; } const DEFAULT_DELIMITER = "\n"; export async function xeval( reader: Reader, xevalFunc: XevalFunc, { delimiter = DEFAULT_DELIMITER }: XevalOptions = {} ): Promise { for await (const chunk of readStringDelim(reader, delimiter)) { // Ignore empty chunks. if (chunk.length > 0) { await xevalFunc(chunk); } } } async function main(): Promise { const parsedArgs = parse(args, { boolean: ["help"], string: ["delim", "replvar"], alias: { delim: ["d"], replvar: ["I"], help: ["h"] }, default: { delim: DEFAULT_DELIMITER, replvar: "$" } }); if (parsedArgs._.length != 1) { console.error(HELP_MSG); console.log(parsedArgs._); exit(1); } if (parsedArgs.help) { return console.log(HELP_MSG); } const delimiter = parsedArgs.delim; const replVar = parsedArgs.replvar; const code = parsedArgs._[0]; // new AsyncFunction()'s error message for this particular case isn't great. if (!replVar.match(/^[_$A-z][_$A-z0-9]*$/)) { console.error(`Bad replvar identifier: "${replVar}"`); exit(1); } const xEvalFunc = new AsyncFunction(replVar, code); await xeval(stdin, xEvalFunc, { delimiter }); } if (import.meta.main) { main(); }