diff options
author | Ry Dahl <ry@tinyclouds.org> | 2020-01-08 17:40:59 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-08 17:40:59 -0500 |
commit | c50cab90a05d271013f741768d70c1eda6ef9a10 (patch) | |
tree | 08c8f59ed2ef449abd56455c9494a43a73058e67 | |
parent | b71d5708c603b09714a1f539f92f82392b6ee33d (diff) |
Remove xeval subcommand (#3630)
-rw-r--r-- | cli/flags.rs | 112 | ||||
-rw-r--r-- | cli/tests/030_xeval.out | 3 | ||||
-rw-r--r-- | cli/tests/031_xeval_replvar.out | 3 | ||||
-rw-r--r-- | cli/tests/032_xeval_delim.out | 3 | ||||
-rw-r--r-- | cli/tests/integration_tests.rs | 18 | ||||
-rw-r--r-- | std/manual.md | 1 | ||||
-rw-r--r-- | std/xeval/mod.ts | 170 | ||||
-rw-r--r-- | std/xeval/test.ts | 49 |
8 files changed, 1 insertions, 358 deletions
diff --git a/cli/flags.rs b/cli/flags.rs index 559cf35f9..7dff2eb75 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -32,8 +32,6 @@ const PRETTIER_URL: &str = std_url!("prettier/main.ts"); const INSTALLER_URL: &str = std_url!("installer/mod.ts"); /// Used for `deno test...` subcommand const TEST_RUNNER_URL: &str = std_url!("testing/runner.ts"); -/// Used for `deno xeval...` subcommand -const XEVAL_URL: &str = std_url!("xeval/mod.ts"); #[derive(Clone, Debug, PartialEq)] pub enum DenoSubcommand { @@ -47,7 +45,6 @@ pub enum DenoSubcommand { Repl, Run, Types, - Xeval, } impl Default for DenoSubcommand { @@ -174,8 +171,6 @@ pub fn flags_from_vec_safe(args: Vec<String>) -> clap::Result<DenoFlags> { eval_parse(&mut flags, m); } else if let Some(m) = matches.subcommand_matches("repl") { repl_parse(&mut flags, m); - } else if let Some(m) = matches.subcommand_matches("xeval") { - xeval_parse(&mut flags, m); } else if let Some(m) = matches.subcommand_matches("bundle") { bundle_parse(&mut flags, m); } else if let Some(m) = matches.subcommand_matches("install") { @@ -224,7 +219,6 @@ fn clap_root<'a, 'b>() -> App<'a, 'b> { .subcommand(run_subcommand()) .subcommand(test_subcommand()) .subcommand(types_subcommand()) - .subcommand(xeval_subcommand()) .long_about(DENO_HELP) .after_help(ENV_VARIABLES_HELP) } @@ -344,33 +338,6 @@ fn completions_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) { print!("{}", std::str::from_utf8(&buf).unwrap()); } -fn xeval_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) { - flags.subcommand = DenoSubcommand::Run; - flags.allow_net = true; - flags.allow_env = true; - flags.allow_run = true; - flags.allow_read = true; - flags.allow_write = true; - flags.allow_plugin = true; - flags.allow_hrtime = true; - flags.argv.push(XEVAL_URL.to_string()); - - if matches.is_present("delim") { - let delim = matches.value_of("delim").unwrap(); - flags.argv.push("--delim".to_string()); - flags.argv.push(delim.to_string()); - } - - if matches.is_present("replvar") { - let replvar = matches.value_of("replvar").unwrap(); - flags.argv.push("--replvar".to_string()); - flags.argv.push(replvar.to_string()); - } - - let code: &str = matches.value_of("code").unwrap(); - flags.argv.push(code.to_string()); -} - fn repl_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) { v8_flags_arg_parse(flags, matches); flags.subcommand = DenoSubcommand::Repl; @@ -804,46 +771,6 @@ Example: ) } -fn xeval_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("xeval") - .about("Eval a script on text segments from stdin") - .long_about( - "Eval a script on lines from stdin - -Read from standard input and eval code on each whitespace-delimited -string chunks. - --I/--replvar optionally sets variable name for input to be used in eval. -Otherwise '$' will be used as default variable name. - -This command has implicit access to all permissions (equivalent to deno run --allow-all) - -Print all the usernames in /etc/passwd: - - cat /etc/passwd | deno xeval \"a = $.split(':'); if (a) console.log(a[0])\" - -A complicated way to print the current git branch: - - git branch | deno xeval -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 xeval -d \" \" \"if ($ === 'MIT') console.log('MIT licensed')\"", - ).arg( - Arg::with_name("replvar") - .long("replvar") - .short("I") - .help("Set variable name to be used in eval, defaults to $") - .takes_value(true), - ).arg( - Arg::with_name("delim") - .long("delim") - .short("d") - .help("Set delimiter, defaults to newline") - .takes_value(true), - ).arg(Arg::with_name("code").takes_value(true).required(true)) -} - fn eval_subcommand<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("eval") .about("Eval script") @@ -1283,8 +1210,7 @@ fn arg_hacks(mut args: Vec<String>) -> Vec<String> { "types", "install", "help", - "version", - "xeval" + "version" ]; let modifier_flags = sset!["-h", "--help", "-V", "--version"]; // deno [subcommand|behavior modifier flags] -> do nothing @@ -1645,42 +1571,6 @@ mod tests { } #[test] - fn xeval() { - let r = flags_from_vec_safe(svec![ - "deno", - "xeval", - "-I", - "val", - "-d", - " ", - "console.log(val)" - ]); - assert_eq!( - r.unwrap(), - DenoFlags { - subcommand: DenoSubcommand::Run, - argv: svec![ - "deno", - XEVAL_URL, - "--delim", - " ", - "--replvar", - "val", - "console.log(val)" - ], - allow_net: true, - allow_env: true, - allow_run: true, - allow_read: true, - allow_write: true, - allow_plugin: true, - allow_hrtime: true, - ..DenoFlags::default() - } - ); - } - - #[test] fn allow_read_whitelist() { use tempfile::TempDir; let temp_dir = TempDir::new().expect("tempdir fail"); diff --git a/cli/tests/030_xeval.out b/cli/tests/030_xeval.out deleted file mode 100644 index b1e67221a..000000000 --- a/cli/tests/030_xeval.out +++ /dev/null @@ -1,3 +0,0 @@ -A -B -C diff --git a/cli/tests/031_xeval_replvar.out b/cli/tests/031_xeval_replvar.out deleted file mode 100644 index b1e67221a..000000000 --- a/cli/tests/031_xeval_replvar.out +++ /dev/null @@ -1,3 +0,0 @@ -A -B -C diff --git a/cli/tests/032_xeval_delim.out b/cli/tests/032_xeval_delim.out deleted file mode 100644 index b1e67221a..000000000 --- a/cli/tests/032_xeval_delim.out +++ /dev/null @@ -1,3 +0,0 @@ -A -B -C diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 83b59e1f8..70ad55e56 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -262,24 +262,6 @@ itest!(_029_eval { output: "029_eval.out", }); -itest!(_030_xeval { - args: "xeval console.log($.toUpperCase())", - input: Some("a\nb\n\nc"), - output: "030_xeval.out", -}); - -itest!(_031_xeval_replvar { - args: "xeval -I val console.log(val.toUpperCase());", - input: Some("a\nb\n\nc"), - output: "031_xeval_replvar.out", -}); - -itest!(_032_xeval_delim { - args: "xeval -d DELIM console.log($.toUpperCase());", - input: Some("aDELIMbDELIMDELIMc"), - output: "032_xeval_delim.out", -}); - itest!(_033_import_map { args: "run --reload --importmap=importmaps/import_map.json importmaps/test.ts", diff --git a/std/manual.md b/std/manual.md index 2ac31fc80..b09ce9364 100644 --- a/std/manual.md +++ b/std/manual.md @@ -629,7 +629,6 @@ SUBCOMMANDS: run Run a program given a filename or url to the source code test Run tests types Print runtime TypeScript declarations - xeval Eval a script on text segments from stdin ENVIRONMENT VARIABLES: DENO_DIR Set deno's base directory diff --git a/std/xeval/mod.ts b/std/xeval/mod.ts deleted file mode 100644 index 5843c8650..000000000 --- a/std/xeval/mod.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { parse } from "../flags/mod.ts"; -const { Buffer, EOF, args, exit, stdin, writeAll } = 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<void> {}) - .constructor; - -const HELP_MSG = `Deno xeval - -USAGE: - deno -A https://deno.land/std/xeval/mod.ts [OPTIONS] <code> - -OPTIONS: - -d, --delim <delim> Set delimiter, defaults to newline - -I, --replvar <replvar> Set variable name to be used in eval, defaults to $ - -ARGS: - <code>`; - -export type XevalFunc = (v: string) => void; - -export interface XevalOptions { - delimiter?: string; -} - -const DEFAULT_DELIMITER = "\n"; - -// Generate longest proper prefix which is also suffix array. -function createLPS(pat: Uint8Array): Uint8Array { - const lps = new Uint8Array(pat.length); - lps[0] = 0; - let prefixEnd = 0; - let i = 1; - while (i < lps.length) { - if (pat[i] == pat[prefixEnd]) { - prefixEnd++; - lps[i] = prefixEnd; - i++; - } else if (prefixEnd === 0) { - lps[i] = 0; - i++; - } else { - prefixEnd = pat[prefixEnd - 1]; - } - } - return lps; -} - -// TODO(kevinkassimo): Move this utility somewhere public in deno_std. -// Import from there once doable. -// Read from reader until EOF and emit string chunks separated -// by the given delimiter. -async function* chunks( - reader: Reader, - delim: string -): AsyncIterableIterator<string> { - const encoder = new TextEncoder(); - const decoder = new TextDecoder(); - // Avoid unicode problems - const delimArr = encoder.encode(delim); - const delimLen = delimArr.length; - const delimLPS = createLPS(delimArr); - - let inputBuffer = new Buffer(); - const inspectArr = new Uint8Array(Math.max(1024, delimLen + 1)); - - // Modified KMP - let inspectIndex = 0; - let matchIndex = 0; - while (true) { - const result = await reader.read(inspectArr); - if (result === EOF) { - // Yield last chunk. - const lastChunk = inputBuffer.toString(); - yield lastChunk; - return; - } - if ((result as number) < 0) { - // Discard all remaining and silently fail. - return; - } - const sliceRead = inspectArr.subarray(0, result as number); - await writeAll(inputBuffer, sliceRead); - - let sliceToProcess = inputBuffer.bytes(); - while (inspectIndex < sliceToProcess.length) { - if (sliceToProcess[inspectIndex] === delimArr[matchIndex]) { - inspectIndex++; - matchIndex++; - if (matchIndex === delimLen) { - // Full match - const matchEnd = inspectIndex - delimLen; - const readyBytes = sliceToProcess.subarray(0, matchEnd); - // Copy - const pendingBytes = sliceToProcess.slice(inspectIndex); - const readyChunk = decoder.decode(readyBytes); - yield readyChunk; - // Reset match, different from KMP. - sliceToProcess = pendingBytes; - inspectIndex = 0; - matchIndex = 0; - } - } else { - if (matchIndex === 0) { - inspectIndex++; - } else { - matchIndex = delimLPS[matchIndex - 1]; - } - } - } - // Keep inspectIndex and matchIndex. - inputBuffer = new Buffer(sliceToProcess); - } -} - -export async function xeval( - reader: Reader, - xevalFunc: XevalFunc, - { delimiter = DEFAULT_DELIMITER }: XevalOptions = {} -): Promise<void> { - for await (const chunk of chunks(reader, delimiter)) { - // Ignore empty chunks. - if (chunk.length > 0) { - await xevalFunc(chunk); - } - } -} - -async function main(): Promise<void> { - const parsedArgs = parse(args.slice(1), { - 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); - 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(); -} diff --git a/std/xeval/test.ts b/std/xeval/test.ts deleted file mode 100644 index 30ac6af01..000000000 --- a/std/xeval/test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { xeval } from "./mod.ts"; -import { stringsReader } from "../io/util.ts"; -import { decode, encode } from "../strings/mod.ts"; -import { assertEquals, assertStrContains } from "../testing/asserts.ts"; -import { test } from "../testing/mod.ts"; -const { execPath, run } = Deno; - -test(async function xevalSuccess(): Promise<void> { - const chunks: string[] = []; - await xeval(stringsReader("a\nb\nc"), ($): number => chunks.push($)); - assertEquals(chunks, ["a", "b", "c"]); -}); - -test(async function xevalDelimiter(): Promise<void> { - const chunks: string[] = []; - await xeval(stringsReader("!MADMADAMADAM!"), ($): number => chunks.push($), { - delimiter: "MADAM" - }); - assertEquals(chunks, ["!MAD", "ADAM!"]); -}); - -// https://github.com/denoland/deno/issues/2861 -// TODO: Use the URL constructor here when it's fixed. -const modTsUrl = import.meta.url.replace(/test.ts$/, "mod.ts"); - -test(async function xevalCliReplvar(): Promise<void> { - const p = run({ - args: [execPath(), modTsUrl, "--", "--replvar=abc", "console.log(abc)"], - stdin: "piped", - stdout: "piped", - stderr: "null" - }); - await p.stdin!.write(encode("hello")); - await p.stdin!.close(); - assertEquals(await p.status(), { code: 0, success: true }); - assertEquals(decode(await p.output()).trimEnd(), "hello"); -}); - -test(async function xevalCliSyntaxError(): Promise<void> { - const p = run({ - args: [execPath(), modTsUrl, "--", "("], - stdin: "null", - stdout: "piped", - stderr: "piped" - }); - assertEquals(await p.status(), { code: 1, success: false }); - assertEquals(decode(await p.output()), ""); - assertStrContains(decode(await p.stderrOutput()), "Uncaught SyntaxError"); -}); |