diff --git a/bin/cli_commands.json b/bin/cli_commands.json index bb3c9e94231f..c2734b707317 100644 --- a/bin/cli_commands.json +++ b/bin/cli_commands.json @@ -1,956 +1,956 @@ [ - { - "command": "help [command]", - "description": "Print a help message.", - "path": "", - "group": "general" - }, - { - "command": "arch", - "description": "Operating system CPU architecture.", - "path": "@stdlib/os/arch", - "group": "system" - }, - { - "command": "bench", - "description": "Run JavaScript benchmark files.", - "path": "@stdlib/bench", - "group": "benchmarking" - }, - { - "command": "bundle-pkg-list", - "description": "Bundle a list of stdlib packages.", - "path": "@stdlib/_tools/bundle/pkg-list", - "group": "tools" - }, - { - "command": "capitalize", - "description": "Capitalize the first character in a string.", - "path": "@stdlib/string/capitalize", - "group": "utilities" - }, - { - "command": "configdir", - "description": "Configuration directory path.", - "path": "@stdlib/os/configdir", - "group": "system" - }, - { - "command": "convert-path", - "description": "Convert between Windows and POSIX paths.", - "path": "@stdlib/utils/convert-path", - "group": "utilities" - }, - { - "command": "cwd", - "description": "Current working directory.", - "path": "@stdlib/process/cwd", - "group": "system" - }, - { - "command": "datasets", - "description": "Retrieve a dataset.", - "path": "@stdlib/datasets", - "group": "general" - }, - { - "command": "day-of-quarter", - "description": "Calculate day of quarter.", - "path": "@stdlib/time/day-of-quarter", - "group": "time" - }, - { - "command": "day-of-year", - "description": "Calculate day of year.", - "path": "@stdlib/time/day-of-year", - "group": "time" - }, - { - "command": "days-in-month", - "description": "Calculate the number of days in a month.", - "path": "@stdlib/time/days-in-month", - "group": "time" - }, - { - "command": "days-in-year", - "description": "Calculate the number of days in a year.", - "path": "@stdlib/time/days-in-year", - "group": "time" - }, - { - "command": "ends-with", - "description": "Test if a string ends with another string.", - "path": "@stdlib/string/ends-with", - "group": "utilities" - }, - { - "command": "exists", - "description": "Test if a file exists.", - "path": "@stdlib/fs/exists", - "group": "filesystem" - }, - { - "command": "from-code-point", - "description": "Create a string from code points.", - "path": "@stdlib/string/from-code-point", - "group": "utilities" - }, - { - "command": "has-arraybuffer-support", - "description": "Detect ArrayBuffer support.", - "path": "@stdlib/assert/has-arraybuffer-support", - "group": "assert" - }, - { - "command": "has-async-await-support", - "description": "Detect async/await support.", - "path": "@stdlib/assert/has-async-await-support", - "group": "assert" - }, - { - "command": "has-async-iterator-symbol-support", - "description": "Detect Symbol.asyncIterator support.", - "path": "@stdlib/assert/has-async-iterator-symbol-support", - "group": "assert" - }, - { - "command": "has-class-support", - "description": "Detect ES6 class support.", - "path": "@stdlib/assert/has-class-support", - "group": "assert" - }, - { - "command": "has-float32array-support", - "description": "Detect Float32Array support.", - "path": "@stdlib/assert/has-float32array-support", - "group": "assert" - }, - { - "command": "has-float64array-support", - "description": "Detect Float64Array support.", - "path": "@stdlib/assert/has-float64array-support", - "group": "assert" - }, - { - "command": "has-function-name-support", - "description": "Detect function name support.", - "path": "@stdlib/assert/has-function-name-support", - "group": "assert" - }, - { - "command": "has-generator-support", - "description": "Detect generator support.", - "path": "@stdlib/assert/has-generator-support", - "group": "assert" - }, - { - "command": "has-int16array-support", - "description": "Detect Int16Array support.", - "path": "@stdlib/assert/has-int16array-support", - "group": "assert" - }, - { - "command": "has-int32array-support", - "description": "Detect Int32Array support.", - "path": "@stdlib/assert/has-int32array-support", - "group": "assert" - }, - { - "command": "has-int8array-support", - "description": "Detect Int8Array support.", - "path": "@stdlib/assert/has-int8array-support", - "group": "assert" - }, - { - "command": "has-iterator-symbol-support", - "description": "Detect Symbol.iterator support.", - "path": "@stdlib/assert/has-iterator-symbol-support", - "group": "assert" - }, - { - "command": "has-map-support", - "description": "Detect Map support.", - "path": "@stdlib/assert/has-map-support", - "group": "assert" - }, - { - "command": "has-node-buffer-support", - "description": "Detect Node buffer support.", - "path": "@stdlib/assert/has-node-buffer-support", - "group": "assert" - }, - { - "command": "has-proxy-support", - "description": "Detect Proxy support.", - "path": "@stdlib/assert/has-proxy-support", - "group": "assert" - }, - { - "command": "has-set-support", - "description": "Detect Set support.", - "path": "@stdlib/assert/has-set-support", - "group": "assert" - }, - { - "command": "has-sharedarraybuffer-support", - "description": "Detect SharedArrayBuffer support.", - "path": "@stdlib/assert/has-sharedarraybuffer-support", - "group": "assert" - }, - { - "command": "has-symbol-support", - "description": "Detect Symbol support.", - "path": "@stdlib/assert/has-symbol-support", - "group": "assert" - }, - { - "command": "has-tostringtag-support", - "description": "Detect Symbol.toStringTag support.", - "path": "@stdlib/assert/has-tostringtag-support", - "group": "assert" - }, - { - "command": "has-uint16array-support", - "description": "Detect Uit16Array support.", - "path": "@stdlib/assert/has-uint16array-support", - "group": "assert" - }, - { - "command": "has-uint32array-support", - "description": "Detect Uit32Array support.", - "path": "@stdlib/assert/has-uint32array-support", - "group": "assert" - }, - { - "command": "has-uint8array-support", - "description": "Detect Uit8Array support.", - "path": "@stdlib/assert/has-uint8array-support", - "group": "assert" - }, - { - "command": "has-uint8clampedarray-support", - "description": "Detect Uit8ClampedArray support.", - "path": "@stdlib/assert/has-uint8clampedarray-support", - "group": "assert" - }, - { - "command": "has-wasm-support", - "description": "Detect WebAssembly support.", - "path": "@stdlib/assert/has-wasm-support", - "group": "assert" - }, - { - "command": "has-weakmap-support", - "description": "Detect WeakMap support.", - "path": "@stdlib/assert/has-weakmap-support", - "group": "assert" - }, - { - "command": "has-weakset-support", - "description": "Detect WeakSet support.", - "path": "@stdlib/assert/has-weakset-support", - "group": "assert" - }, - { - "command": "homedir", - "description": "Home directory path.", - "path": "@stdlib/os/homedir", - "group": "system" - }, - { - "command": "hours-in-month", - "description": "Calculate the number of hours in a month.", - "path": "@stdlib/time/hours-in-month", - "group": "time" - }, - { - "command": "hours-in-year", - "description": "Calculate the number of hours in a year.", - "path": "@stdlib/time/hours-in-year", - "group": "time" - }, - { - "command": "iso-weeks-in-year", - "description": "Calculate the number of ISO weeks in a year.", - "path": "@stdlib/time/iso-weeks-in-year", - "group": "time" - }, - { - "command": "is-absolute-path", - "description": "Assert an absolute path.", - "path": "@stdlib/assert/is-absolute-path", - "group": "assert" - }, - { - "command": "is-alphagram", - "description": "Assert if a value is an alphagram.", - "path": "@stdlib/assert/is-alphagram", - "group": "assert" - }, - { - "command": "is-alphanumeric", - "description": "Assert if a value is alphanumeric.", - "path": "@stdlib/assert/is-alphanumeric", - "group": "assert" - }, - { - "command": "is-anagram", - "description": "Assert if a value is an anagram.", - "path": "@stdlib/assert/is-anagram", - "group": "assert" - }, - { - "command": "is-ascii", - "description": "Assert if a value is ASCII.", - "path": "@stdlib/assert/is-ascii", - "group": "assert" - }, - { - "command": "is-binary-string", - "description": "Assert if a value is a binary string.", - "path": "@stdlib/assert/is-binary-string", - "group": "assert" - }, - { - "command": "is-capitalized", - "description": "Assert if a value is capitalized.", - "path": "@stdlib/assert/is-capitalized", - "group": "assert" - }, - { - "command": "is-digit-string", - "description": "Assert if a value is a digit string.", - "path": "@stdlib/assert/is-digit-string", - "group": "assert" - }, - { - "command": "is-email-address", - "description": "Assert if a value is an email address.", - "path": "@stdlib/assert/is-email-address", - "group": "assert" - }, - { - "command": "is-hex-string", - "description": "Assert if a value is a hexadecimal string.", - "path": "@stdlib/assert/is-hex-string", - "group": "assert" - }, - { - "command": "is-leap-year", - "description": "Assert if a leap year.", - "path": "@stdlib/assert/is-leap-year", - "group": "assert" - }, - { - "command": "is-little-endian", - "description": "Assert if little endian.", - "path": "@stdlib/assert/is-little-endian", - "group": "assert" - }, - { - "command": "is-lowercase", - "description": "Assert if a value is lowercase.", - "path": "@stdlib/assert/is-lowercase", - "group": "assert" - }, - { - "command": "is-regexp-string", - "description": "Assert if a value is a regexp string.", - "path": "@stdlib/assert/is-regexp-string", - "group": "assert" - }, - { - "command": "is-unc-path", - "description": "Assert a UNC path.", - "path": "@stdlib/assert/is-unc-path", - "group": "assert" - }, - { - "command": "is-uppercase", - "description": "Assert if a value is uppercase.", - "path": "@stdlib/assert/is-uppercase", - "group": "assert" - }, - { - "command": "is-uri", - "description": "Assert if a value is a URI.", - "path": "@stdlib/assert/is-uri", - "group": "assert" - }, - { - "command": "is-whitespace", - "description": "Assert if a value is only whitespace.", - "path": "@stdlib/assert/is-whitespace", - "group": "assert" - }, - { - "command": "js-eval", - "description": "Evaluate a JavaScript string.", - "path": "@stdlib/utils/eval", - "group": "utilities" - }, - { - "command": "library-manifest", - "description": "Load a manifest for compiling source files.", - "path": "@stdlib/utils/library-manifest", - "group": "meta" - }, - { - "command": "lpad", - "description": "Left pad a string.", - "path": "@stdlib/string/left-pad", - "group": "utilities" - }, - { - "command": "ltrim", - "description": "Left trim a string.", - "path": "@stdlib/string/left-trim", - "group": "utilities" - }, - { - "command": "lowercase", - "description": "Lowercase a string.", - "path": "@stdlib/string/lowercase", - "group": "utilities" - }, - { - "command": "ls", - "description": "List stdlib package names.", - "path": "@stdlib/_tools/pkgs/names", - "group": "meta" - }, - { - "command": "ls-tree", - "description": "Show stdlib package tree.", - "path": "@stdlib/_tools/pkgs/tree", - "group": "meta" - }, - { - "command": "minutes-in-month", - "description": "Calculate the number of minutes in a month.", - "path": "@stdlib/time/minutes-in-month", - "group": "time" - }, - { - "command": "minutes-in-year", - "description": "Calculate the number of minutes in a year.", - "path": "@stdlib/time/minutes-in-year", - "group": "time" - }, - { - "command": "node-version", - "description": "Node.js version.", - "path": "@stdlib/process/node-version", - "group": "meta" - }, - { - "command": "now", - "description": "Number of seconds since the epoch.", - "path": "@stdlib/time/now", - "group": "time" - }, - { - "command": "ns", - "description": "Print stdlib namespace.", - "path": "@stdlib/namespace", - "group": "meta" - }, - { - "command": "num-cpus", - "description": "Number of CPUs.", - "path": "@stdlib/os/num-cpus", - "group": "system" - }, - { - "command": "random-arcsine", - "description": "Arcsine distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/arcsine", - "group": "random" - }, - { - "command": "random-bernoulli", - "description": "Bernoulli distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/bernoulli", - "group": "random" - }, - { - "command": "random-beta", - "description": "Beta distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/beta", - "group": "random" - }, - { - "command": "random-betaprime", - "description": "Beta prime distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/betaprime", - "group": "random" - }, - { - "command": "random-box-muller", - "description": "Box-Muller pseudorandom numbers.", - "path": "@stdlib/random/streams/box-muller", - "group": "random" - }, - { - "command": "random-cauchy", - "description": "Cauchy distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/cauchy", - "group": "random" - }, - { - "command": "random-chi", - "description": "Chi distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/chi", - "group": "random" - }, - { - "command": "random-chisquare", - "description": "Chi-square distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/chisquare", - "group": "random" - }, - { - "command": "random-cosine", - "description": "Raised cosine distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/cosine", - "group": "random" - }, - { - "command": "random-discrete-uniform", - "description": "Uniformly distributed pseudorandom integers.", - "path": "@stdlib/random/streams/discrete-uniform", - "group": "random" - }, - { - "command": "random-erlang", - "description": "Erlang distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/erlang", - "group": "random" - }, - { - "command": "random-exponential", - "description": "Exponentially distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/exponential", - "group": "random" - }, - { - "command": "random-f", - "description": "F distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/f", - "group": "random" - }, - { - "command": "random-gamma", - "description": "Gamma distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/gamma", - "group": "random" - }, - { - "command": "random-geometric", - "description": "Geometric distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/geometric", - "group": "random" - }, - { - "command": "random-gumbel", - "description": "Gumbel distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/gumbel", - "group": "random" - }, - { - "command": "random-improved-ziggurat", - "description": "Improved Ziggurat pseudorandom numbers.", - "path": "@stdlib/random/streams/improved-ziggurat", - "group": "random" - }, - { - "command": "random-invgamma", - "description": "Inverse gamma distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/invgamma", - "group": "random" - }, - { - "command": "random-kumaraswamy", - "description": "Kumaraswamy distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/kumaraswamy", - "group": "random" - }, - { - "command": "random-laplace", - "description": "Laplace distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/laplace", - "group": "random" - }, - { - "command": "random-levy", - "description": "Lévy distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/levy", - "group": "random" - }, - { - "command": "random-logistic", - "description": "Logistic distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/logistic", - "group": "random" - }, - { - "command": "random-lognormal", - "description": "Lognormal distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/lognormal", - "group": "random" - }, - { - "command": "random-minstd", - "description": "Park and Miller LCG pseudorandom numbers.", - "path": "@stdlib/random/streams/minstd", - "group": "random" - }, - { - "command": "random-minstd-shuffle", - "description": "Shuffled LCG pseudorandom numbers.", - "path": "@stdlib/random/streams/minstd-shuffle", - "group": "random" - }, - { - "command": "random-mt19937", - "description": "32-bit Mersenne Twister pseudorandom numbers.", - "path": "@stdlib/random/streams/mt19937", - "group": "random" - }, - { - "command": "random-normal", - "description": "Normally distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/normal", - "group": "random" - }, - { - "command": "random-pareto-type1", - "description": "Pareto (type 1) distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/pareto-type1", - "group": "random" - }, - { - "command": "random-poisson", - "description": "Poisson distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/poisson", - "group": "random" - }, - { - "command": "random-randi", - "description": "Pseudorandom numbers having integer values.", - "path": "@stdlib/random/streams/randi", - "group": "random" - }, - { - "command": "random-randn", - "description": "Normally distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/randn", - "group": "random" - }, - { - "command": "random-randu", - "description": "Pseudorandom numbers between 0 and 1.", - "path": "@stdlib/random/streams/randu", - "group": "random" - }, - { - "command": "random-Rayleigh", - "description": "Rayleigh distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/rayleigh", - "group": "random" - }, - { - "command": "random-t", - "description": "Student's t distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/t", - "group": "random" - }, - { - "command": "random-uniform", - "description": "Uniformly distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/uniform", - "group": "random" - }, - { - "command": "random-weibull", - "description": "Weibull distributed pseudorandom numbers.", - "path": "@stdlib/random/streams/weibull", - "group": "random" - }, - { - "command": "open-url", - "description": "Open a URL.", - "path": "@stdlib/utils/open-url", - "group": "utilities" - }, - { - "command": "padstr", - "description": "Pad a string.", - "path": "@stdlib/string/pad", - "group": "utilities" - }, - { - "command": "parallel", - "description": "Execute scripts in parallel.", - "path": "@stdlib/utils/parallel", - "group": "utilities" - }, - { - "command": "percent-encode", - "description": "Percent-encode a UTF-16 encoded string.", - "path": "@stdlib/string/percent-encode", - "group": "utilities" - }, - { - "command": "platform", - "description": "Platform.", - "path": "@stdlib/os/platform", - "group": "system" - }, - { - "command": "quarter-of-year", - "description": "Calculate the quarter of a year.", - "path": "@stdlib/time/quarter-of-year", - "group": "time" - }, - { - "command": "read-dir", - "description": "Read all files in a directory.", - "path": "@stdlib/fs/read-dir", - "group": "filesystem" - }, - { - "command": "read-file", - "description": "Read a file.", - "path": "@stdlib/fs/read-file", - "group": "filesystem" - }, - { - "command": "read-file-list", - "description": "Read a list of files.", - "path": "@stdlib/fs/read-file-list", - "group": "filesystem" - }, - { - "command": "realmax", - "description": "Maximum representable finite value.", - "path": "@stdlib/utils/real-max", - "group": "utilities" - }, - { - "command": "realmin", - "description": "Minimum representable finite value.", - "path": "@stdlib/utils/real-min", - "group": "utilities" - }, - { - "command": "remove-first", - "description": "Remove the first character in a string.", - "path": "@stdlib/string/remove-first", - "group": "utilities" - }, - { - "command": "remove-last", - "description": "Remove the last character in a string.", - "path": "@stdlib/string/remove-last", - "group": "utilities" - }, - { - "command": "remove-punctuation", - "description": "Remove punctuation characters from a string.", - "path": "@stdlib/string/remove-punctuation", - "group": "utilities" - }, - { - "command": "remove-utf8-bom", - "description": "Remove a UTF-8 byte order mark (BOM).", - "path": "@stdlib/string/remove-first", - "group": "utilities" - }, - { - "command": "remove-words", - "description": "Remove a list of words from a string.", - "path": "@stdlib/string/remove-words", - "group": "utilities" - }, - { - "command": "rename", - "description": "Rename a file.", - "path": "@stdlib/fs/rename", - "group": "filesystem" - }, - { - "command": "repstr", - "description": "Repeat a string.", - "path": "@stdlib/string/repeat", - "group": "utilities" - }, - { - "command": "repl", - "description": "Start a REPL.", - "path": "@stdlib/repl", - "group": "general" - }, - { - "command": "repl-presentation", - "description": "Start a REPL presentation.", - "path": "@stdlib/repl/presentation", - "group": "general" - }, - { - "command": "replace", - "description": "Replace search occurrences in a string.", - "path": "@stdlib/string/replace", - "group": "utilities" - }, - { - "command": "resolve-parent-path", - "description": "Resolve a path by walking parent directories.", - "path": "@stdlib/fs/resolve-parent-path", - "group": "filesystem" - }, - { - "command": "reverse", - "description": "Reverse a string.", - "path": "@stdlib/string/reverse", - "group": "utilities" - }, - { - "command": "rpad", - "description": "Right pad a string.", - "path": "@stdlib/string/right-pad", - "group": "utilities" - }, - { - "command": "rtrim", - "description": "Right trim a string.", - "path": "@stdlib/string/right-trim", - "group": "utilities" - }, - { - "command": "safeintmax", - "description": "Maximum representable safe integer value.", - "path": "@stdlib/utils/safe-int-max", - "group": "utilities" - }, - { - "command": "safeintmin", - "description": "Minimum representable safe integer value.", - "path": "@stdlib/utils/safe-int-min", - "group": "utilities" - }, - { - "command": "seconds-in-month", - "description": "Calculate the number of seconds in a month.", - "path": "@stdlib/time/seconds-in-month", - "group": "time" - }, - { - "command": "seconds-in-year", - "description": "Calculate the number of seconds in a year.", - "path": "@stdlib/time/seconds-in-year", - "group": "time" - }, - { - "command": "sizeof", - "description": "Size (in bytes) of a numeric data type.", - "path": "@stdlib/utils/size-of", - "group": "utilities" - }, - { - "command": "sparkline", - "description": "Plot a sparkline.", - "path": "@stdlib/plot/sparklines/unicode", - "group": "plot" - }, - { - "command": "startcase", - "description": "Capitalize each word in a string.", - "path": "@stdlib/string/startcase", - "group": "utilities" - }, - { - "command": "starts-with", - "description": "Test if a string starts with another string.", - "path": "@stdlib/string/starts-with", - "group": "utilities" - }, - { - "command": "temp-http-server", - "description": "Create a temporary HTTP server.", - "path": "@stdlib/net/disposable-http-server", - "group": "utilities" - }, - { - "command": "timeit", - "description": "Time a JavaScript snippet.", - "path": "@stdlib/utils/timeit", - "group": "benchmarking" - }, - { - "command": "tmpdir", - "description": "Directory path for storing temporary files.", - "path": "@stdlib/os/tmpdir", - "group": "system" - }, - { - "command": "trim", - "description": "Trim a string.", - "path": "@stdlib/string/trim", - "group": "utilities" - }, - { - "command": "typemax", - "description": "Maximum value for a numeric data type.", - "path": "@stdlib/utils/type-max", - "group": "utilities" - }, - { - "command": "typemin", - "description": "Minimum value for a numeric data type.", - "path": "@stdlib/utils/type-min", - "group": "utilities" - }, - { - "command": "umask", - "description": "Process mask.", - "path": "@stdlib/process/umask", - "group": "system" - }, - { - "command": "uncapitalize", - "description": "Uncapitalize a string.", - "path": "@stdlib/string/uncapitalize", - "group": "utilities" - }, - { - "command": "unlink", - "description": "Remove a file.", - "path": "@stdlib/fs/unlink", - "group": "filesystem" - }, - { - "command": "uppercase", - "description": "Uppercase a string.", - "path": "@stdlib/string/uppercase", - "group": "utilities" - }, - { - "command": "write-file", - "description": "Write to file.", - "path": "@stdlib/fs/write-file", - "group": "filesystem" - }, - { - "command": "constant-stream", - "description": "Stream a constant value.", - "path": "@stdlib/streams/node/from-constant", - "group": "utilities" - }, - { - "command": "empty-stream", - "description": "Empty stream.", - "path": "@stdlib/streams/node/empty", - "group": "utilities" - } + { + "command": "help [command]", + "description": "Print a help message.", + "path": "", + "group": "general" + }, + { + "command": "arch", + "description": "Operating system CPU architecture.", + "path": "@stdlib/os/arch", + "group": "system" + }, + { + "command": "bench", + "description": "Run JavaScript benchmark files.", + "path": "@stdlib/bench", + "group": "benchmarking" + }, + { + "command": "bundle-pkg-list", + "description": "Bundle a list of stdlib packages.", + "path": "@stdlib/_tools/bundle/pkg-list", + "group": "tools" + }, + { + "command": "capitalize", + "description": "Capitalize the first character in a string.", + "path": "@stdlib/string/capitalize", + "group": "utilities" + }, + { + "command": "configdir", + "description": "Configuration directory path.", + "path": "@stdlib/os/configdir", + "group": "system" + }, + { + "command": "convert-path", + "description": "Convert between Windows and POSIX paths.", + "path": "@stdlib/utils/convert-path", + "group": "utilities" + }, + { + "command": "cwd", + "description": "Current working directory.", + "path": "@stdlib/process/cwd", + "group": "system" + }, + { + "command": "datasets", + "description": "Retrieve a dataset.", + "path": "@stdlib/datasets", + "group": "general" + }, + { + "command": "day-of-quarter", + "description": "Calculate day of quarter.", + "path": "@stdlib/time/day-of-quarter", + "group": "time" + }, + { + "command": "day-of-year", + "description": "Calculate day of year.", + "path": "@stdlib/time/day-of-year", + "group": "time" + }, + { + "command": "days-in-month", + "description": "Calculate the number of days in a month.", + "path": "@stdlib/time/days-in-month", + "group": "time" + }, + { + "command": "days-in-year", + "description": "Calculate the number of days in a year.", + "path": "@stdlib/time/days-in-year", + "group": "time" + }, + { + "command": "ends-with", + "description": "Test if a string ends with another string.", + "path": "@stdlib/string/ends-with", + "group": "utilities" + }, + { + "command": "exists", + "description": "Test if a file exists.", + "path": "@stdlib/fs/exists", + "group": "filesystem" + }, + { + "command": "from-code-point", + "description": "Create a string from code points.", + "path": "@stdlib/string/from-code-point", + "group": "utilities" + }, + { + "command": "has-arraybuffer-support", + "description": "Detect ArrayBuffer support.", + "path": "@stdlib/assert/has-arraybuffer-support", + "group": "assert" + }, + { + "command": "has-async-await-support", + "description": "Detect async/await support.", + "path": "@stdlib/assert/has-async-await-support", + "group": "assert" + }, + { + "command": "has-async-iterator-symbol-support", + "description": "Detect Symbol.asyncIterator support.", + "path": "@stdlib/assert/has-async-iterator-symbol-support", + "group": "assert" + }, + { + "command": "has-class-support", + "description": "Detect ES6 class support.", + "path": "@stdlib/assert/has-class-support", + "group": "assert" + }, + { + "command": "has-float32array-support", + "description": "Detect Float32Array support.", + "path": "@stdlib/assert/has-float32array-support", + "group": "assert" + }, + { + "command": "has-float64array-support", + "description": "Detect Float64Array support.", + "path": "@stdlib/assert/has-float64array-support", + "group": "assert" + }, + { + "command": "has-function-name-support", + "description": "Detect function name support.", + "path": "@stdlib/assert/has-function-name-support", + "group": "assert" + }, + { + "command": "has-generator-support", + "description": "Detect generator support.", + "path": "@stdlib/assert/has-generator-support", + "group": "assert" + }, + { + "command": "has-int16array-support", + "description": "Detect Int16Array support.", + "path": "@stdlib/assert/has-int16array-support", + "group": "assert" + }, + { + "command": "has-int32array-support", + "description": "Detect Int32Array support.", + "path": "@stdlib/assert/has-int32array-support", + "group": "assert" + }, + { + "command": "has-int8array-support", + "description": "Detect Int8Array support.", + "path": "@stdlib/assert/has-int8array-support", + "group": "assert" + }, + { + "command": "has-iterator-symbol-support", + "description": "Detect Symbol.iterator support.", + "path": "@stdlib/assert/has-iterator-symbol-support", + "group": "assert" + }, + { + "command": "has-map-support", + "description": "Detect Map support.", + "path": "@stdlib/assert/has-map-support", + "group": "assert" + }, + { + "command": "has-node-buffer-support", + "description": "Detect Node buffer support.", + "path": "@stdlib/assert/has-node-buffer-support", + "group": "assert" + }, + { + "command": "has-proxy-support", + "description": "Detect Proxy support.", + "path": "@stdlib/assert/has-proxy-support", + "group": "assert" + }, + { + "command": "has-set-support", + "description": "Detect Set support.", + "path": "@stdlib/assert/has-set-support", + "group": "assert" + }, + { + "command": "has-sharedarraybuffer-support", + "description": "Detect SharedArrayBuffer support.", + "path": "@stdlib/assert/has-sharedarraybuffer-support", + "group": "assert" + }, + { + "command": "has-symbol-support", + "description": "Detect Symbol support.", + "path": "@stdlib/assert/has-symbol-support", + "group": "assert" + }, + { + "command": "has-tostringtag-support", + "description": "Detect Symbol.toStringTag support.", + "path": "@stdlib/assert/has-tostringtag-support", + "group": "assert" + }, + { + "command": "has-uint16array-support", + "description": "Detect Uit16Array support.", + "path": "@stdlib/assert/has-uint16array-support", + "group": "assert" + }, + { + "command": "has-uint32array-support", + "description": "Detect Uit32Array support.", + "path": "@stdlib/assert/has-uint32array-support", + "group": "assert" + }, + { + "command": "has-uint8array-support", + "description": "Detect Uit8Array support.", + "path": "@stdlib/assert/has-uint8array-support", + "group": "assert" + }, + { + "command": "has-uint8clampedarray-support", + "description": "Detect Uit8ClampedArray support.", + "path": "@stdlib/assert/has-uint8clampedarray-support", + "group": "assert" + }, + { + "command": "has-wasm-support", + "description": "Detect WebAssembly support.", + "path": "@stdlib/assert/has-wasm-support", + "group": "assert" + }, + { + "command": "has-weakmap-support", + "description": "Detect WeakMap support.", + "path": "@stdlib/assert/has-weakmap-support", + "group": "assert" + }, + { + "command": "has-weakset-support", + "description": "Detect WeakSet support.", + "path": "@stdlib/assert/has-weakset-support", + "group": "assert" + }, + { + "command": "homedir", + "description": "Home directory path.", + "path": "@stdlib/os/homedir", + "group": "system" + }, + { + "command": "hours-in-month", + "description": "Calculate the number of hours in a month.", + "path": "@stdlib/time/hours-in-month", + "group": "time" + }, + { + "command": "hours-in-year", + "description": "Calculate the number of hours in a year.", + "path": "@stdlib/time/hours-in-year", + "group": "time" + }, + { + "command": "iso-weeks-in-year", + "description": "Calculate the number of ISO weeks in a year.", + "path": "@stdlib/time/iso-weeks-in-year", + "group": "time" + }, + { + "command": "is-absolute-path", + "description": "Assert an absolute path.", + "path": "@stdlib/assert/is-absolute-path", + "group": "assert" + }, + { + "command": "is-alphagram", + "description": "Assert if a value is an alphagram.", + "path": "@stdlib/assert/is-alphagram", + "group": "assert" + }, + { + "command": "is-alphanumeric", + "description": "Assert if a value is alphanumeric.", + "path": "@stdlib/assert/is-alphanumeric", + "group": "assert" + }, + { + "command": "is-anagram", + "description": "Assert if a value is an anagram.", + "path": "@stdlib/assert/is-anagram", + "group": "assert" + }, + { + "command": "is-ascii", + "description": "Assert if a value is ASCII.", + "path": "@stdlib/assert/is-ascii", + "group": "assert" + }, + { + "command": "is-binary-string", + "description": "Assert if a value is a binary string.", + "path": "@stdlib/assert/is-binary-string", + "group": "assert" + }, + { + "command": "is-capitalized", + "description": "Assert if a value is capitalized.", + "path": "@stdlib/assert/is-capitalized", + "group": "assert" + }, + { + "command": "is-digit-string", + "description": "Assert if a value is a digit string.", + "path": "@stdlib/assert/is-digit-string", + "group": "assert" + }, + { + "command": "is-email-address", + "description": "Assert if a value is an email address.", + "path": "@stdlib/assert/is-email-address", + "group": "assert" + }, + { + "command": "is-hex-string", + "description": "Assert if a value is a hexadecimal string.", + "path": "@stdlib/assert/is-hex-string", + "group": "assert" + }, + { + "command": "is-leap-year", + "description": "Assert if a leap year.", + "path": "@stdlib/assert/is-leap-year", + "group": "assert" + }, + { + "command": "is-little-endian", + "description": "Assert if little endian.", + "path": "@stdlib/assert/is-little-endian", + "group": "assert" + }, + { + "command": "is-lowercase", + "description": "Assert if a value is lowercase.", + "path": "@stdlib/assert/is-lowercase", + "group": "assert" + }, + { + "command": "is-regexp-string", + "description": "Assert if a value is a regexp string.", + "path": "@stdlib/assert/is-regexp-string", + "group": "assert" + }, + { + "command": "is-unc-path", + "description": "Assert a UNC path.", + "path": "@stdlib/assert/is-unc-path", + "group": "assert" + }, + { + "command": "is-uppercase", + "description": "Assert if a value is uppercase.", + "path": "@stdlib/assert/is-uppercase", + "group": "assert" + }, + { + "command": "is-uri", + "description": "Assert if a value is a URI.", + "path": "@stdlib/assert/is-uri", + "group": "assert" + }, + { + "command": "is-whitespace", + "description": "Assert if a value is only whitespace.", + "path": "@stdlib/assert/is-whitespace", + "group": "assert" + }, + { + "command": "js-eval", + "description": "Evaluate a JavaScript string.", + "path": "@stdlib/utils/eval", + "group": "utilities" + }, + { + "command": "library-manifest", + "description": "Load a manifest for compiling source files.", + "path": "@stdlib/utils/library-manifest", + "group": "meta" + }, + { + "command": "lpad", + "description": "Left pad a string.", + "path": "@stdlib/string/left-pad", + "group": "utilities" + }, + { + "command": "ltrim", + "description": "Left trim a string.", + "path": "@stdlib/string/left-trim", + "group": "utilities" + }, + { + "command": "lowercase", + "description": "Lowercase a string.", + "path": "@stdlib/string/lowercase", + "group": "utilities" + }, + { + "command": "ls", + "description": "List stdlib package names.", + "path": "@stdlib/_tools/pkgs/names", + "group": "meta" + }, + { + "command": "ls-tree", + "description": "Show stdlib package tree.", + "path": "@stdlib/_tools/pkgs/tree", + "group": "meta" + }, + { + "command": "minutes-in-month", + "description": "Calculate the number of minutes in a month.", + "path": "@stdlib/time/minutes-in-month", + "group": "time" + }, + { + "command": "minutes-in-year", + "description": "Calculate the number of minutes in a year.", + "path": "@stdlib/time/minutes-in-year", + "group": "time" + }, + { + "command": "node-version", + "description": "Node.js version.", + "path": "@stdlib/process/node-version", + "group": "meta" + }, + { + "command": "now", + "description": "Number of seconds since the epoch.", + "path": "@stdlib/time/now", + "group": "time" + }, + { + "command": "ns", + "description": "Print stdlib namespace.", + "path": "@stdlib/namespace", + "group": "meta" + }, + { + "command": "num-cpus", + "description": "Number of CPUs.", + "path": "@stdlib/os/num-cpus", + "group": "system" + }, + { + "command": "random-arcsine", + "description": "Arcsine distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/arcsine", + "group": "random" + }, + { + "command": "random-bernoulli", + "description": "Bernoulli distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/bernoulli", + "group": "random" + }, + { + "command": "random-beta", + "description": "Beta distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/beta", + "group": "random" + }, + { + "command": "random-betaprime", + "description": "Beta prime distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/betaprime", + "group": "random" + }, + { + "command": "random-box-muller", + "description": "Box-Muller pseudorandom numbers.", + "path": "@stdlib/random/streams/box-muller", + "group": "random" + }, + { + "command": "random-cauchy", + "description": "Cauchy distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/cauchy", + "group": "random" + }, + { + "command": "random-chi", + "description": "Chi distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/chi", + "group": "random" + }, + { + "command": "random-chisquare", + "description": "Chi-square distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/chisquare", + "group": "random" + }, + { + "command": "random-cosine", + "description": "Raised cosine distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/cosine", + "group": "random" + }, + { + "command": "random-discrete-uniform", + "description": "Uniformly distributed pseudorandom integers.", + "path": "@stdlib/random/streams/discrete-uniform", + "group": "random" + }, + { + "command": "random-erlang", + "description": "Erlang distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/erlang", + "group": "random" + }, + { + "command": "random-exponential", + "description": "Exponentially distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/exponential", + "group": "random" + }, + { + "command": "random-f", + "description": "F distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/f", + "group": "random" + }, + { + "command": "random-gamma", + "description": "Gamma distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/gamma", + "group": "random" + }, + { + "command": "random-geometric", + "description": "Geometric distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/geometric", + "group": "random" + }, + { + "command": "random-gumbel", + "description": "Gumbel distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/gumbel", + "group": "random" + }, + { + "command": "random-improved-ziggurat", + "description": "Improved Ziggurat pseudorandom numbers.", + "path": "@stdlib/random/streams/improved-ziggurat", + "group": "random" + }, + { + "command": "random-invgamma", + "description": "Inverse gamma distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/invgamma", + "group": "random" + }, + { + "command": "random-kumaraswamy", + "description": "Kumaraswamy distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/kumaraswamy", + "group": "random" + }, + { + "command": "random-laplace", + "description": "Laplace distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/laplace", + "group": "random" + }, + { + "command": "random-levy", + "description": "Lévy distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/levy", + "group": "random" + }, + { + "command": "random-logistic", + "description": "Logistic distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/logistic", + "group": "random" + }, + { + "command": "random-lognormal", + "description": "Lognormal distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/lognormal", + "group": "random" + }, + { + "command": "random-minstd", + "description": "Park and Miller LCG pseudorandom numbers.", + "path": "@stdlib/random/streams/minstd", + "group": "random" + }, + { + "command": "random-minstd-shuffle", + "description": "Shuffled LCG pseudorandom numbers.", + "path": "@stdlib/random/streams/minstd-shuffle", + "group": "random" + }, + { + "command": "random-mt19937", + "description": "32-bit Mersenne Twister pseudorandom numbers.", + "path": "@stdlib/random/streams/mt19937", + "group": "random" + }, + { + "command": "random-normal", + "description": "Normally distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/normal", + "group": "random" + }, + { + "command": "random-pareto-type1", + "description": "Pareto (type 1) distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/pareto-type1", + "group": "random" + }, + { + "command": "random-poisson", + "description": "Poisson distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/poisson", + "group": "random" + }, + { + "command": "random-randi", + "description": "Pseudorandom numbers having integer values.", + "path": "@stdlib/random/streams/randi", + "group": "random" + }, + { + "command": "random-randn", + "description": "Normally distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/randn", + "group": "random" + }, + { + "command": "random-randu", + "description": "Pseudorandom numbers between 0 and 1.", + "path": "@stdlib/random/streams/randu", + "group": "random" + }, + { + "command": "random-Rayleigh", + "description": "Rayleigh distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/rayleigh", + "group": "random" + }, + { + "command": "random-t", + "description": "Student's t distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/t", + "group": "random" + }, + { + "command": "random-uniform", + "description": "Uniformly distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/uniform", + "group": "random" + }, + { + "command": "random-weibull", + "description": "Weibull distributed pseudorandom numbers.", + "path": "@stdlib/random/streams/weibull", + "group": "random" + }, + { + "command": "open-url", + "description": "Open a URL.", + "path": "@stdlib/utils/open-url", + "group": "utilities" + }, + { + "command": "padstr", + "description": "Pad a string.", + "path": "@stdlib/string/pad", + "group": "utilities" + }, + { + "command": "parallel", + "description": "Execute scripts in parallel.", + "path": "@stdlib/utils/parallel", + "group": "utilities" + }, + { + "command": "percent-encode", + "description": "Percent-encode a UTF-16 encoded string.", + "path": "@stdlib/string/percent-encode", + "group": "utilities" + }, + { + "command": "platform", + "description": "Platform.", + "path": "@stdlib/os/platform", + "group": "system" + }, + { + "command": "quarter-of-year", + "description": "Calculate the quarter of a year.", + "path": "@stdlib/time/quarter-of-year", + "group": "time" + }, + { + "command": "read-dir", + "description": "Read all files in a directory.", + "path": "@stdlib/fs/read-dir", + "group": "filesystem" + }, + { + "command": "read-file", + "description": "Read a file.", + "path": "@stdlib/fs/read-file", + "group": "filesystem" + }, + { + "command": "read-file-list", + "description": "Read a list of files.", + "path": "@stdlib/fs/read-file-list", + "group": "filesystem" + }, + { + "command": "realmax", + "description": "Maximum representable finite value.", + "path": "@stdlib/utils/real-max", + "group": "utilities" + }, + { + "command": "realmin", + "description": "Minimum representable finite value.", + "path": "@stdlib/utils/real-min", + "group": "utilities" + }, + { + "command": "remove-first", + "description": "Remove the first character in a string.", + "path": "@stdlib/string/remove-first", + "group": "utilities" + }, + { + "command": "remove-last", + "description": "Remove the last character in a string.", + "path": "@stdlib/string/remove-last", + "group": "utilities" + }, + { + "command": "remove-punctuation", + "description": "Remove punctuation characters from a string.", + "path": "@stdlib/string/remove-punctuation", + "group": "utilities" + }, + { + "command": "remove-utf8-bom", + "description": "Remove a UTF-8 byte order mark (BOM).", + "path": "@stdlib/string/remove-first", + "group": "utilities" + }, + { + "command": "remove-words", + "description": "Remove a list of words from a string.", + "path": "@stdlib/string/remove-words", + "group": "utilities" + }, + { + "command": "rename", + "description": "Rename a file.", + "path": "@stdlib/fs/rename", + "group": "filesystem" + }, + { + "command": "repstr", + "description": "Repeat a string.", + "path": "@stdlib/string/repeat", + "group": "utilities" + }, + { + "command": "repl", + "description": "Start a REPL.", + "path": "@stdlib/repl", + "group": "general" + }, + { + "command": "repl-presentation", + "description": "Start a REPL presentation.", + "path": "@stdlib/repl/presentation", + "group": "general" + }, + { + "command": "replace", + "description": "Replace search occurrences in a string.", + "path": "@stdlib/string/replace", + "group": "utilities" + }, + { + "command": "resolve-parent-path", + "description": "Resolve a path by walking parent directories.", + "path": "@stdlib/fs/resolve-parent-path", + "group": "filesystem" + }, + { + "command": "reverse", + "description": "Reverse a string.", + "path": "@stdlib/string/reverse", + "group": "utilities" + }, + { + "command": "rpad", + "description": "Right pad a string.", + "path": "@stdlib/string/right-pad", + "group": "utilities" + }, + { + "command": "rtrim", + "description": "Right trim a string.", + "path": "@stdlib/string/right-trim", + "group": "utilities" + }, + { + "command": "safeintmax", + "description": "Maximum representable safe integer value.", + "path": "@stdlib/utils/safe-int-max", + "group": "utilities" + }, + { + "command": "safeintmin", + "description": "Minimum representable safe integer value.", + "path": "@stdlib/utils/safe-int-min", + "group": "utilities" + }, + { + "command": "seconds-in-month", + "description": "Calculate the number of seconds in a month.", + "path": "@stdlib/time/seconds-in-month", + "group": "time" + }, + { + "command": "seconds-in-year", + "description": "Calculate the number of seconds in a year.", + "path": "@stdlib/time/seconds-in-year", + "group": "time" + }, + { + "command": "sizeof", + "description": "Size (in bytes) of a numeric data type.", + "path": "@stdlib/utils/size-of", + "group": "utilities" + }, + { + "command": "sparkline", + "description": "Plot a sparkline.", + "path": "@stdlib/plot/sparklines/unicode", + "group": "plot" + }, + { + "command": "startcase", + "description": "Capitalize each word in a string.", + "path": "@stdlib/string/startcase", + "group": "utilities" + }, + { + "command": "starts-with", + "description": "Test if a string starts with another string.", + "path": "@stdlib/string/starts-with", + "group": "utilities" + }, + { + "command": "temp-http-server", + "description": "Create a temporary HTTP server.", + "path": "@stdlib/net/disposable-http-server", + "group": "utilities" + }, + { + "command": "timeit", + "description": "Time a JavaScript snippet.", + "path": "@stdlib/utils/timeit", + "group": "benchmarking" + }, + { + "command": "tmpdir", + "description": "Directory path for storing temporary files.", + "path": "@stdlib/os/tmpdir", + "group": "system" + }, + { + "command": "trim", + "description": "Trim a string.", + "path": "@stdlib/string/trim", + "group": "utilities" + }, + { + "command": "typemax", + "description": "Maximum value for a numeric data type.", + "path": "@stdlib/utils/type-max", + "group": "utilities" + }, + { + "command": "typemin", + "description": "Minimum value for a numeric data type.", + "path": "@stdlib/utils/type-min", + "group": "utilities" + }, + { + "command": "umask", + "description": "Process mask.", + "path": "@stdlib/process/umask", + "group": "system" + }, + { + "command": "uncapitalize", + "description": "Uncapitalize a string.", + "path": "@stdlib/string/uncapitalize", + "group": "utilities" + }, + { + "command": "unlink", + "description": "Remove a file.", + "path": "@stdlib/fs/unlink", + "group": "filesystem" + }, + { + "command": "uppercase", + "description": "Uppercase a string.", + "path": "@stdlib/string/uppercase", + "group": "utilities" + }, + { + "command": "write-file", + "description": "Write to file.", + "path": "@stdlib/fs/write-file", + "group": "filesystem" + }, + { + "command": "constant-stream", + "description": "Stream a constant value.", + "path": "@stdlib/streams/node/from-constant", + "group": "utilities" + }, + { + "command": "empty-stream", + "description": "Empty stream.", + "path": "@stdlib/streams/node/empty", + "group": "utilities" + } ] diff --git a/lib/node_modules/@stdlib/repl/README.md b/lib/node_modules/@stdlib/repl/README.md index 7647a61919fd..3b9735819d0d 100644 --- a/lib/node_modules/@stdlib/repl/README.md +++ b/lib/node_modules/@stdlib/repl/README.md @@ -290,7 +290,6 @@ The syntax-highlighter supports the following tokens and associated theme fields - **number**: numeric literals. - **literal**: reserved literals (e.g., `true`, `false`, `null`, and `undefined`). - **regexp**: regular expressions. -- **command**: built-in REPL commands. - **function**: function identifiers. - **object**: object identifiers. - **variable**: literal identifiers. diff --git a/lib/node_modules/@stdlib/repl/base/README.md b/lib/node_modules/@stdlib/repl/base/README.md new file mode 100644 index 000000000000..be4dbb3c7849 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/README.md @@ -0,0 +1,89 @@ + + +# Base + +> Base REPL functionality. + +
+ +## Usage + +```javascript +var ns = require( '@stdlib/repl/base' ); +``` + +#### ns + +Namespace containing "base" (i.e., lower-level) REPL functionality. + +```javascript +var o = ns; +// returns {...} +``` + + + +
+ +
+ + + +
+ + + +
+ +## Examples + + + +```javascript +var objectKeys = require( '@stdlib/utils/keys' ); +var ns = require( '@stdlib/repl/base' ); + +console.log( objectKeys( ns ) ); +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/repl/base/ctor/README.md b/lib/node_modules/@stdlib/repl/base/ctor/README.md new file mode 100644 index 000000000000..9458a0bfcdc8 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/README.md @@ -0,0 +1,711 @@ + + +# REPL + +> Base class for Read-Eval-Print Loop (REPL) environment. + + + +
+ +A Read-Eval-Print Loop (REPL) environment is an interactive programming environment which takes individual user inputs (e.g., single expressions), evaluates those inputs, and returns the result. Accordingly, a program written in a REPL environment is executed piecewise and sequentially. + +REPL environments find common use in exploratory programming, prototyping, and debugging. + +The REPL environment exposed here is available both as a standalone application and as a library which is embeddable in other libraries and applications. + +
+ + + + + +
+ +## Usage + +```javascript +var REPL = require( '@stdlib/repl/base/ctor' ); +``` + +#### REPL( \[options] ) + +Returns a `REPL` instance. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Execute a command: +repl.emit( 'input', '2 + 3' ); + +// ... + +// Close the REPL: +repl.close(); +``` + +The function accepts the following `options`: + +- **output**: output (writable) stream. Default: [`stdout`][@stdlib/streams/node/stdout]. +- **error**: error (writable) stream. Default: [`stderr`][@stdlib/streams/node/stderr]. +- **sandbox**: boolean indicating whether to run a REPL in a sandboxed context. Default: `false`. +- **timeout**: number of milliseconds to execute a command before terminating execution. Default: `4294967295`. +- **save**: file path specifying where to save REPL command history. +- **log**: file path specifying where to save REPL commands and printed output. +- **quiet**: boolean indicating whether log information, confirmation messages, and other possible REPL diagnostics should be silenced. Default: `false`. + +### Readable Properties + +#### REPL.prototype.currentWorkspace + +Name of the current workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Get current workspace name: +var ws = repl.currentWorkspace; + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.quiet + +Boolean indicating whether log information, confirmation messages, and other possible REPL diagnostics should be silenced. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Check if the REPL is quiet: +var out = repl.quiet; + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.closed + +Boolean indicating whether the REPL is closed. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Check if the REPL is closed: +var out = repl.closed; + +// Close the REPL: +repl.close(); + +// Check if the REPL was closed: +out = repl.closed; +``` + +#### REPL.prototype.count + +Command count. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Get command count: +var cnt = repl.count; + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.ans + +Result of the last successfully evaluated command. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Execute a command: +repl.emit( 'input', '2 + 3' ); + +// Get the cached result: +var res = repl.ans; + +// Close the REPL: +repl.close(); +``` + +### Methods + +#### REPL.prototype.isMultilineInput( input ) + +Checks if the given input is a possible multi-line command. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Check if an input is a possible multi-line command: +var input = 'for( var i = 0; i < 10; i++ ) {'; +var out = repl.isMultilineInput( input ); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.processCommand( code ) + +Processes a "raw" input command. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Process raw command: +var code = 'var y = 10;'; +var out = repl.processCommand( code ); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.compileCommand( cmd ) + +Compiles a command. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Process raw command: +var code = 'var y = 10;'; +var cmd = repl.processCommand( code ); + +// Compile processed command: +var out = repl.compileCommand( cmd ); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.runCommand( exe, opts ) + +Runs a compiled command. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Process and compile a raw command: +var cmd = '1 + 1'; +var code = repl.processCommand( cmd ); +var exe = repl.compileCommand( code ); + +// Run the compiled command: +var out = repl.runCommand( exe, {} ); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.completer( line, clbk ) + +Generates completions for a given line. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Generate completions for a line: +var line = 'var x = M'; +repl.completer( line, clbk ); + +function clbk( error, completions ) { + if ( error ) { + throw error; + } + console.log( completions ); +} + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.tokenizer( line ) + +Tokenizes the input line based on ECMAScript specification. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Tokenize an input line: +var line = 'var x = 5;'; +var out = repl.tokenizer( line ); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.resolveContextVarByName( name ) + +Resolves the value of a context variable for a given alias name. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Create a new REPL context: +var ctx = repl.createContext({ + 'a': 5, + 'b': 10 +}); + +// Resolve a context variable by name: +var out = repl.resolveContextVarByName( 'a' ); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.resolveContextVarByRef( ref ) + +Resolves the name of the context variable for a given reference. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Create a new REPL context: +var obj = {}; +var ctx = repl.createContext({ + 'a': obj +}); + +// Resolve a context variable by reference: +var out = repl.resolveContextVarByRef( obj ); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.resolveAliasByRef( ref ) + +Resolves the name of an alias for a given reference. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Resolve alias by reference to the actual alias in context: +var alias = repl.resolveAliasByRef({}); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.resolveAliasByProp( ref ) + +Resolves the name of an alias for a given property reference. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// Create a new REPL context: +var ctx = repl.createContext(); + +// Resolve alias by reference to the actual alias in context: +var alias = repl.resolveAliasByRef({}); + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.createContext() + +Returns a REPL context. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Return a new REPL context: +var ctx = repl.createContext(); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.resetContext() + +Resets a REPL's execution context. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Reset the REPL context: +repl.resetContext(); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.setCommands( context, commands ) + +Sets commands on a context object. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Initialize empty context: +var ctx = {}; + +// Define custom commands: +function helloWorld() { + console.log( 'Hello World!' ); +} +var cmds = [ [ 'helloWorld', helloWorld, false ] ]; + +// Set custom commands on context: +repl.setCommands( ctx, cmds ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.createWorkspace( name ) + +Creates a new workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Create new workspace: +repl.createWorkspace( 'myWorkspace' ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.switchWorkspace( name ) + +Switches to a specified workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Create new workspace: +repl.createWorkspace( 'myWorkspace' ); + +// Switch to newly created workspace: +repl.switchWorkspace( 'myWorkspace' ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.loadWorkspace( name, \[options] ) + +Loads variables from a specified workspace into the current workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Create new workspace: +repl.createWorkspace( 'myWorkspace' ); + +// Load variables from a workspace: +var count = repl.loadWorkspace( 'myWorkspace', {} ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.workspaces() + +Returns list of all workspaces. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// List all workspaces: +var list = repl.workspaces(); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.varsWorkspace( name, \[options] ) + +Returns a list of variable names in a specified workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Get list of variables in current workspace: +var list = repl.varsWorkspace( repl.currentWorkspace ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.evalin( workspace, expression ) + +Evaluates an expression in a specified workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Evaluate in base workspace: +repl.evalin( 'base', 'var x = 5;' ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.renameWorkspace( oldName, newName ) + +Renames a workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Create new workspace: +repl.createWorkspace( 'myWorkspace' ); + +// Rename workspace: +repl.renameWorkspace( 'myWorkspace', 'yourWorkspace' ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.deleteWorkspace( name ) + +Deletes a workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Create new workspace: +repl.createWorkspace( 'yourWorkspace' ); + +// Delete workspace: +repl.deleteWorkspace( 'yourWorkspace' ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.clearWorkspace( name, \[options] ) + +Deletes user-defined variables in a specified workspace. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Clear user workspace: +var d = repl.clearWorkspace( 'base' ); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.reset() + +Resets a REPL. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Reset the REPL: +repl.reset(); + +// ... + +// Close the REPL: +repl.close(); +``` + +#### REPL.prototype.close() + +Closes a REPL. + +```javascript +// Create a new REPL: +var repl = new REPL(); + +// ... + +// Close the REPL: +repl.close(); +``` + +* * * + +
+ + + + + +
+ +
+ + + + + +* * * + +
+ +## Examples + + + +```javascript +var REPL = require( '@stdlib/repl/base/ctor' ); + +function onCommand( cmd, success, res ) { + console.log( cmd + ' = ' + res.toString() ); +} + +// Create a new REPL: +var repl = new REPL(); +repl.on( 'command', onCommand ); + +// Execute a command: +repl.emit( 'input', '3 + 2' ); + +// Close the REPL: +repl.close(); +console.log( 'REPL closed.' ); +``` + +
+ + + +* * * + +
+ +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/repl/base/ctor/benchmark/benchmark.js b/lib/node_modules/@stdlib/repl/base/ctor/benchmark/benchmark.js new file mode 100644 index 000000000000..364db7818d05 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/benchmark/benchmark.js @@ -0,0 +1,95 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var inspectSinkStream = require( '@stdlib/streams/node/inspect-sink' ); +var randu = require( '@stdlib/random/streams/randu' ); +var noop = require( '@stdlib/utils/noop' ); +var pkg = require( './../package.json' ).name; +var REPL = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::new', function benchmark( b ) { + var sopts; + var opts; + var r; + var i; + + opts = { + 'output': inspectSinkStream( noop ), + 'error': inspectSinkStream( noop ) + }; + sopts = { + 'iter': 1 + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + opts.input = randu( sopts ); // Note: this is slow, but should not be rate-limiting + r = new REPL( opts ); + if ( typeof r !== 'object' ) { + b.fail( 'should return an object' ); + } + r.close(); + } + b.toc(); + if ( !( r instanceof REPL ) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::no_new', function benchmark( b ) { + var sopts; + var repl; + var opts; + var r; + var i; + + repl = REPL; + opts = { + 'output': inspectSinkStream( noop ), + 'error': inspectSinkStream( noop ) + }; + sopts = { + 'iter': 1 + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + opts.input = randu( sopts ); // Note: this is slow, but should not be rate-limiting + r = repl( opts ); + if ( typeof r !== 'object' ) { + b.fail( 'should return an object' ); + } + r.close(); + } + b.toc(); + if ( !( r instanceof REPL ) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/repl/base/ctor/examples/index.js b/lib/node_modules/@stdlib/repl/base/ctor/examples/index.js new file mode 100644 index 000000000000..19ad97ab2eac --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/examples/index.js @@ -0,0 +1,36 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var REPL = require( './../lib' ); + +function onCommand( cmd, success, res ) { + console.log( cmd + ' = ' + res.toString() ); +} + +// Create a new REPL: +var repl = new REPL(); +repl.on( 'command', onCommand ); + +// Execute a command: +repl.emit( 'input', '3 + 2' ); + +// Close the REPL: +repl.close(); +console.log( 'REPL closed.' ); diff --git a/lib/node_modules/@stdlib/repl/lib/acorn_detect_multiline_input.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/acorn_detect_multiline_input.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/acorn_detect_multiline_input.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/acorn_detect_multiline_input.js diff --git a/lib/node_modules/@stdlib/repl/lib/alias_overrides.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/alias_overrides.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/alias_overrides.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/alias_overrides.js diff --git a/lib/node_modules/@stdlib/repl/lib/aliases.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/aliases.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/aliases.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/aliases.js diff --git a/lib/node_modules/@stdlib/repl/lib/append_unique.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/append_unique.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/append_unique.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/append_unique.js diff --git a/lib/node_modules/@stdlib/repl/lib/compile_code.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/compile_code.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/compile_code.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/compile_code.js diff --git a/lib/node_modules/@stdlib/repl/lib/compile_command.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/compile_command.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/compile_command.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/compile_command.js diff --git a/lib/node_modules/@stdlib/repl/lib/complete_expression.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/complete_expression.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/complete_expression.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/complete_expression.js diff --git a/lib/node_modules/@stdlib/repl/lib/complete_fs.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/complete_fs.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/complete_fs.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/complete_fs.js diff --git a/lib/node_modules/@stdlib/repl/lib/complete_require.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/complete_require.js similarity index 98% rename from lib/node_modules/@stdlib/repl/lib/complete_require.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/complete_require.js index 03888ac53a42..6f367dbb2b87 100644 --- a/lib/node_modules/@stdlib/repl/lib/complete_require.js +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/complete_require.js @@ -27,7 +27,7 @@ var readDir = require( '@stdlib/fs/read-dir' ).sync; var startsWith = require( '@stdlib/string/starts-with' ); var extname = require( '@stdlib/utils/extname' ); var cwd = require( '@stdlib/process/cwd' ); -var indexRegExp = require( './regexp_index.js' ); // eslint-disable-line stdlib/no-require-index +var indexRegExp = require( './regexp_index.js' ); var relativePathRegExp = require( './regexp_relative_require_path.js' ); var pathRegExp = require( './regexp_path.js' ); var contains = require( './contains.js' ); diff --git a/lib/node_modules/@stdlib/repl/lib/complete_walk_find_last.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/complete_walk_find_last.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/complete_walk_find_last.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/complete_walk_find_last.js diff --git a/lib/node_modules/@stdlib/repl/lib/complete_workspace.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/complete_workspace.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/complete_workspace.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/complete_workspace.js diff --git a/lib/node_modules/@stdlib/repl/lib/completer.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/completer.js similarity index 74% rename from lib/node_modules/@stdlib/repl/lib/completer.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/completer.js index ce393c6e5b43..4eed458261df 100644 --- a/lib/node_modules/@stdlib/repl/lib/completer.js +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/completer.js @@ -28,14 +28,10 @@ var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var fsRegExp = require( './regexp_fs_aliases.js' ); var requireRegExp = require( './regexp_require.js' ); var workspaceRegExp = require( './regexp_workspace.js' ); -var tutorialRegExp = require( './regexp_tutorial.js' ); -var settingsRegExp = require( './regexp_settings.js' ); var reservedCharsRegExp = require( './regexp_reserved_syntax_characters.js' ); var completeRequire = require( './complete_require.js' ); var completeFS = require( './complete_fs.js' ); var completeWorkspace = require( './complete_workspace.js' ); -var completeTutorial = require( './complete_tutorial.js' ); -var completeSettings = require( './complete_settings.js' ); var completeExpression = require( './complete_expression.js' ); @@ -78,7 +74,7 @@ function normalize( list ) { // MAIN // /** -* Returns a callback for supporting TAB completion in a REPL environment. +* Returns a callback for generating completions in a REPL environment. * * @private * @param {REPL} repl - REPL instance @@ -88,7 +84,7 @@ function completer( repl ) { return complete; /** - * Callback invoked upon a user entering the TAB character at the command prompt. + * Generates completions for a given line. * * @private * @param {string} line - current line @@ -150,38 +146,8 @@ function completer( repl ) { debug( 'Results: %s', res.join( ', ' ) ); return clbk( null, [ res, line ] ); } - // Test if the line has an incomplete tutorial expression: - match = line.match( tutorialRegExp() ); - if ( match ) { - debug( 'Detected incomplete tutorial expression.' ); - - debug( 'Expression: %s', match[ 0 ] ); - debug( 'Tutorial API: %s', match[ 1 ] ); - debug( 'Value to complete: %s', match[ 3 ] ); - line = completeTutorial( res, repl, match[ 0 ], match[ 1 ], match[ 3 ] ); // eslint-disable-line max-len - res = normalize( res ); - - debug( 'Completion filter: %s', line ); - debug( 'Results: %s', res.join( ', ' ) ); - return clbk( null, [ res, line ] ); - } - // Test if the line has an incomplete settings expression: - match = line.match( settingsRegExp() ); - if ( match ) { - debug( 'Detected incomplete settings expression.' ); - - debug( 'Expression: %s', match[ 0 ] ); - debug( 'Settings API: %s', match[ 1 ] ); - debug( 'Value to complete: %s', match[ 3 ] ); - line = completeSettings( res, repl, match[ 0 ], match[ 1 ], match[ 3 ] ); // eslint-disable-line max-len - res = normalize( res ); - - debug( 'Completion filter: %s', line ); - debug( 'Results: %s', res.join( ', ' ) ); - return clbk( null, [ res, line ] ); - } // Sanity check that we are attempting to complete something which is completable: - if ( reservedCharsRegExp().test( line[ repl._rli.cursor-1 ] ) ) { + if ( reservedCharsRegExp().test( line[ line.length-1 ] ) ) { debug( 'Detected attempt to trigger completion after a special character.' ); debug( 'Results: %s', res.join( ', ' ) ); return clbk( null, [ res, line ] ); diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/contains.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/contains.js new file mode 100644 index 000000000000..c525a07d7d24 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/contains.js @@ -0,0 +1,60 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Returns a boolean indicating if a strided array-like object contains a provided value. +* +* @private +* @param {NonNegativeInteger} N - number of elements to search +* @param {ArrayLike} arr - array to search +* @param {integer} stride - index stride +* @param {NonNegativeInteger} offset - index offset +* @param {*} value - search value +* @returns {boolean} boolean indicating if an array-like object contains a provided value +* +* @example +* var arr = [ 1, 2, 3 ]; +* +* var bool = contains( arr.length, arr, 1, 0, 2 ); +* // returns true +* +* bool = contains( arr.length, arr, 1, 0, 4 ); +* // returns false +*/ +function contains( N, arr, stride, offset, value ) { + var idx; + var i; + + idx = offset; + for ( i = 0; i < N; i++ ) { + if ( arr[ idx ] === value ) { + return true; + } + idx += stride; + } + return false; +} + + +// EXPORTS // + +module.exports = contains; diff --git a/lib/node_modules/@stdlib/repl/lib/create_accessor.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/create_accessor.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/create_accessor.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/create_accessor.js diff --git a/lib/node_modules/@stdlib/repl/lib/create_evaluation_context.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/create_evaluation_context.js similarity index 91% rename from lib/node_modules/@stdlib/repl/lib/create_evaluation_context.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/create_evaluation_context.js index 1850354df078..d70a0a5f46f9 100644 --- a/lib/node_modules/@stdlib/repl/lib/create_evaluation_context.js +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/create_evaluation_context.js @@ -43,20 +43,21 @@ var resolveLookupPaths = Module._resolveLookupPaths; // eslint-disable-line no-u * Creates a REPL evaluation context. * * @private +* @param {Object} context - context object * @param {Array} out - strided output array for storing variables added to the evaluation context * @param {Stream} ostream - output stream +* @param {Stream} estream - error stream * @param {boolean} sandbox - boolean indicating whether the evaluation context should be "sandboxed" * @returns {Object} context */ -function createContext( out, ostream, sandbox ) { - var context; +function createContext( context, out, ostream, estream, sandbox ) { var keys; var i; // Create the REPL context... if ( sandbox ) { // Create a sandboxed context: - context = vm.createContext(); + context = vm.createContext( context ); // Assign globals from the current global context to the sandboxed context (note: shallow copy!)... keys = objectKeys( GLOBALS ); @@ -67,7 +68,7 @@ function createContext( out, ostream, sandbox ) { setReadOnly( context, 'global', context ); // Create a new `console` interface: - setReadOnly( context, 'console', new Console( ostream ) ); + setReadOnly( context, 'console', new Console( ostream, estream ) ); // Create a new `module` object: setReadOnly( context, 'module', new Module( '' ) ); diff --git a/lib/node_modules/@stdlib/repl/lib/create_require.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/create_require.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/create_require.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/create_require.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/defaults.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/defaults.js new file mode 100644 index 000000000000..b6c32e95ca3e --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/defaults.js @@ -0,0 +1,67 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var stdout = require( '@stdlib/streams/node/stdout' ); +var stderr = require( '@stdlib/streams/node/stderr' ); + + +// MAIN // + +/** +* Returns default options. +* +* @private +* @returns {Object} default options +* +* @example +* var opts = defaults(); +* // returns {...} +*/ +function defaults() { + return { + // Default output stream: + 'output': stdout, + + // Default error stream: + 'error': stderr, + + // Number of milliseconds to execute a command before terminating execution: + 'timeout': 4294967295, + + // Flag indicating whether to run a REPL in a sandboxed context: + 'sandbox': true, + + // File path specifying where to save REPL command history: + 'save': '', + + // File path specifying where to save REPL commands and printed output: + 'log': '', + + // Flag indicating whether log information, confirmation messages, and other possible REPL diagnostics should be silenced: + 'quiet': false + }; +} + + +// EXPORTS // + +module.exports = defaults; diff --git a/lib/node_modules/@stdlib/repl/lib/drain.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/drain.js similarity index 73% rename from lib/node_modules/@stdlib/repl/lib/drain.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/drain.js index 84187842c4c5..78aab49df7ce 100644 --- a/lib/node_modules/@stdlib/repl/lib/drain.js +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/drain.js @@ -22,13 +22,9 @@ // MODULES // -var inspect = require( 'util' ).inspect; var logger = require( 'debug' ); -var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' ); -var replace = require( '@stdlib/string/replace' ); var noop = require( '@stdlib/utils/noop' ); var nextTick = require( '@stdlib/utils/next-tick' ); -var displayPrompt = require( './display_prompt.js' ); var updateRegExpCache = require( './update_regexp_cache.js' ); var restoreRegExpMatches = require( './restore_regexp_matches.js' ); @@ -53,8 +49,6 @@ function drain( repl ) { var opts; var code; var res; - var pre; - var tmp; if ( repl._busy ) { debug( 'Waiting on a command to finish...' ); @@ -62,9 +56,6 @@ function drain( repl ) { } if ( repl._queue.length === 0 ) { debug( 'Command queue is empty.' ); - if ( !repl._closed ) { - displayPrompt( repl, false ); - } repl.emit( 'drain' ); return; } @@ -100,12 +91,10 @@ function drain( repl ) { } } catch ( error ) { debug( 'Error: %s', error.message ); - repl._ostream.write( 'Error: '+error.message+'\n' ); - repl.emit( 'command', code.raw, false ); // command failed + repl.emit( 'command', code.raw, false, error, false ); // command failed updateRegExpCache( repl._regexp ); repl._busy = false; - displayPrompt( repl, false ); // Clear the command queue, as an error may cause downstream "dependencies" to not be fulfilled, etc: repl._queue.clear(); @@ -125,17 +114,6 @@ function drain( repl ) { // Cache the result: repl._ans = res; - if ( code.silent === false && res !== void 0 ) { - pre = replace( repl._outputPrompt, '%d', (repl._count+1).toString() ); - - // TODO: pretty printing (can defer to `util.inspect` for now, but will invariably want more control over this later, possibly including default configuration, etc, either at startup, during runtime, or according to an external configuration file) - if ( isndarrayLike( res ) ) { - tmp = res.toString(); // FIXME: this is a hack in order to avoid printing private ndarray properties in the REPL, as done by the built-in `util.inspect`. Ideally, we'd roll our own inspector which specifically accommodates stdlib's ndarray and other specialized classes. - } else { - tmp = repl._ans; - } - repl._ostream.write( pre+inspect( tmp )+'\n' ); - } // Finish processing: return beforeNextTick(); @@ -178,9 +156,7 @@ function drain( repl ) { if ( error ) { debug( 'Error: %s', error.message ); - repl._ostream.write( 'Error: '+error.message+'\n' ); - repl.emit( 'command', code.raw, false ); // command failed - displayPrompt( repl, false ); + repl.emit( 'command', code.raw, false, error, false ); // command failed // Indicate that command execution has completed: repl._busy = false; @@ -193,12 +169,6 @@ function drain( repl ) { // Cache the result: repl._ans = [ res, results ]; - if ( code.silent === false && ( res !== void 0 || results !== void 0 ) ) { // eslint-disable-line max-len - pre = replace( repl._outputPrompt, '%d', (repl._count+1).toString() ); - - // TODO: pretty printing (can defer to `util.inspect` for now, but will invariably want more control over this later, possibly including default configuration, etc, either at startup, during runtime, or according to an external configuration file) - repl._ostream.write( pre+inspect( repl._ans )+'\n' ); - } // Finish processing: beforeNextTick(); @@ -220,7 +190,7 @@ function drain( repl ) { function beforeNextTick() { // Announce that the command succeeded: debug( 'Finished evaluating command.' ); - repl.emit( 'command', code.raw, true ); + repl.emit( 'command', code.raw, true, repl._ans, code.silent ); nextTick( onTick ); } diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/filter.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/filter.js new file mode 100644 index 000000000000..f4b515e08b09 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/filter.js @@ -0,0 +1,93 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var contains = require( './contains.js' ); + + +// MAIN // + +/** +* Filters a variable list based on include and exclude filters. +* +* @private +* @param {Array} list - variable list to filter +* @param {(RegExp|ArrayLikeObject|void)} include - name inclusion filter +* @param {boolean} isArrInc - boolean indicating whether the inclusion filter is an array +* @param {(RegExp|ArrayLikeObject|void)} exclude - name exclusion filter +* @param {boolean} isArrExc - boolean indicating whether the exclusion filter is an array +* @returns {Array} input list +*/ +function filter( list, include, isArrInc, exclude, isArrExc ) { + var FLG; + var v; + var i; + var j; + + // Perform list "compression" without using temporary data structures... + j = 0; + for ( i = 0; i < list.length; i += 2 ) { + // Note: we can only delete "configurable" variables... + if ( list[ i+1 ].configurable === false ) { + // Variable is non-configurable and, hence, cannot be deleted... + continue; + } + v = list[ i ]; + FLG = false; + + // Note: exclude/include order matters!!! + if ( exclude ) { + if ( isArrExc ) { + if ( contains( exclude, v ) ) { + // The variable is in the explicit exclude list: + FLG = true; + } + } else if ( exclude.test( v ) ) { + // The variable passes the exclusion test: + FLG = true; + } + } + // Only apply inclusion filters if the variable has not been already excluded from deletion... + if ( FLG === false && include ) { + if ( isArrInc ) { + if ( !contains( include, v ) ) { + // The variable is *not* in the include list: + FLG = true; + } + } else if ( !include.test( v ) ) { + // The variable does *not* pass the include test: + FLG = true; + } + } + if ( FLG ) { + list[ j ] = list[ i ]; + list[ j+1 ] = list[ i+1 ]; + j += 2; + } + } + list.length = j; + return list; +} + + +// EXPORTS // + +module.exports = filter; diff --git a/lib/node_modules/@stdlib/repl/lib/filter_by_prefix.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/filter_by_prefix.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/filter_by_prefix.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/filter_by_prefix.js diff --git a/lib/node_modules/@stdlib/repl/lib/find_unique_entry.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/find_unique_entry.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/find_unique_entry.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/find_unique_entry.js diff --git a/lib/node_modules/@stdlib/repl/lib/fs_alias_args.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/fs_alias_args.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/fs_alias_args.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/fs_alias_args.js diff --git a/lib/node_modules/@stdlib/repl/lib/fs_aliases.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/fs_aliases.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/fs_aliases.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/fs_aliases.js diff --git a/lib/node_modules/@stdlib/repl/lib/globals.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/globals.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/globals.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/globals.js diff --git a/lib/node_modules/@stdlib/repl/lib/has_async_directive.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/has_async_directive.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/has_async_directive.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/has_async_directive.js diff --git a/lib/node_modules/@stdlib/repl/lib/tutorial_alias_args.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/index.js similarity index 58% rename from lib/node_modules/@stdlib/repl/lib/tutorial_alias_args.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/index.js index 92da3c082457..f7da2d9723dd 100644 --- a/lib/node_modules/@stdlib/repl/lib/tutorial_alias_args.js +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/index.js @@ -18,31 +18,33 @@ 'use strict'; -// MODULES // - -var TUTORIAL_ALIASES = require( './tutorial_aliases.js' ); - - -// MAIN // - /** -* Returns a list of argument completion flags for a specified tutorial API. +* Base class for REPL. +* +* @module @stdlib/repl/base/ctor +* +* @example +* var REPL = require( '@stdlib/repl/base/ctor' ); * -* @private -* @param {string} alias - alias -* @returns {(Array|null)} argument completion flags +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Execute a command: +* repl.emit( 'input', '2 + 3' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); */ -function argFlags( alias ) { - var i; - for ( i = 0; i < TUTORIAL_ALIASES.length; i++ ) { - if ( TUTORIAL_ALIASES[ i ][ 0 ] === alias ) { - return TUTORIAL_ALIASES[ i ].slice( 1 ); - } - } - return null; -} + +// MODULES // + +var main = require( './main.js' ); // EXPORTS // -module.exports = argFlags; +module.exports = main; diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/index_of.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/index_of.js new file mode 100644 index 000000000000..a68e866ca3e2 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/index_of.js @@ -0,0 +1,60 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Returns the index of a search value in a strided array-like object. +* +* @private +* @param {NonNegativeInteger} N - number of elements to search +* @param {ArrayLike} arr - array to search +* @param {integer} stride - index stride +* @param {NonNegativeInteger} offset - index offset +* @param {*} value - search value +* @returns {integer} search value index +* +* @example +* var arr = [ 1, 2, 3 ]; +* +* var bool = indexOf( arr.length, arr, 1, 0, 2 ); +* // returns 1 +* +* bool = indexOf( arr.length, arr, 1, 0, 4 ); +* // returns -1 +*/ +function indexOf( N, arr, stride, offset, value ) { + var idx; + var i; + + idx = offset; + for ( i = 0; i < N; i++ ) { + if ( arr[ idx ] === value ) { + return idx; + } + idx += stride; + } + return -1; +} + + +// EXPORTS // + +module.exports = indexOf; diff --git a/lib/node_modules/@stdlib/repl/lib/is_block_scope.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/is_block_scope.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/is_block_scope.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/is_block_scope.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/is_multiline_input.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/is_multiline_input.js new file mode 100644 index 000000000000..ecad93e6c39c --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/is_multiline_input.js @@ -0,0 +1,94 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var Parser = require( 'acorn' ).Parser; +var parseLoose = require( 'acorn-loose' ).parse; +var logger = require( 'debug' ); +var processCommand = require( './process_command.js' ); +var multilinePlugin = require( './acorn_detect_multiline_input.js' ); + + +// VARIABLES // + +var debug = logger( 'repl:is-multiline-input' ); +var hasMultilineError = Parser.extend( multilinePlugin ).hasMultilineError; +var RE_WHITESPACE = /^\s*$/; +var RE_SINGLE_LINE_COMMENT = /^\s*\/\//; +var RE_MULTI_LINE_COMMENT = /^\s*\/\*.*\*\/$/; +var AOPTS = { + 'ecmaVersion': 'latest' +}; + + +// MAIN // + +/** +* Checks if the given input is a possible multi-line command. +* +* @private +* @param {string} input - input command +* @returns {boolean} boolean indicating whether the given input is a possible multi-line command +*/ +function isMultilineInput( input ) { + var node; + var tmp; + var ast; + + debug( 'Attempting to detect multi-line input...' ); + if ( RE_WHITESPACE.test( input ) ) { + debug( 'Multi-line input not detected.' ); + return false; + } + if ( RE_SINGLE_LINE_COMMENT.test( input ) || RE_MULTI_LINE_COMMENT.test( input ) ) { // eslint-disable-line max-len + debug( 'Multi-line input not detected.' ); + return false; + } + // Check if the command has valid syntax... + tmp = processCommand( input ); + if ( !( tmp instanceof Error ) ) { + debug( 'Multi-line input not detected.' ); + return false; + } + if ( hasMultilineError( input, AOPTS ) ) { + debug( 'Detected multi-line input. Triggering multi-line mode...' ); + return true; + } + // Still possible that a user is attempting to enter an object literal across multiple lines... + ast = parseLoose( input, AOPTS ); + + // Check for a trailing node which is being interpreted as a block statement, as this could be an object literal... + node = ast.body[ ast.body.length-1 ]; + if ( node.type === 'BlockStatement' && node.end === ast.end ) { + tmp = input.slice( node.start, node.end ); + if ( hasMultilineError( tmp, AOPTS ) ) { + debug( 'Detected multi-line input. Triggering multi-line mode...' ); + return true; + } + } + debug( 'Multi-line input not detected.' ); + return false; +} + + +// EXPORTS // + +module.exports = isMultilineInput; diff --git a/lib/node_modules/@stdlib/repl/lib/is_scope.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/is_scope.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/is_scope.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/is_scope.js diff --git a/lib/node_modules/@stdlib/repl/lib/is_silent_command.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/is_silent_command.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/is_silent_command.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/is_silent_command.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/longest_common_prefix.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/longest_common_prefix.js new file mode 100644 index 000000000000..08812654674a --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/longest_common_prefix.js @@ -0,0 +1,101 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TODO: move implementation to package: @stdlib/string/longest-common-prefix + +'use strict'; + +// MODULES // + +var isArrayLikeObject = require( '@stdlib/assert/is-array-like-object' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var format = require( '@stdlib/string/format' ); + + +// MAIN // + +/** +* Returns the longest common prefix. +* +* ## Notes +* +* - The algorithmic complexity is `O(M*N)` where `M` is the number of strings and `N` is the length of the first string. +* +* @private +* @param {(string|StringArray)} arg - a string or list of strings +* @param {string} [...str] - strings +* @throws {TypeError} must provide strings +* @returns {string} longest common prefix +* +* @example +* var prefix = longestCommonPrefix( 'beep', 'bebop' ); +* // returns 'be' +* +* @example +* var prefix = longestCommonPrefix( [ 'beep', 'bebop' ] ); +* // returns 'be' +*/ +function longestCommonPrefix() { + var prefix; + var list; + var str; + var ch; + var M; + var N; + var i; + var j; + + if ( arguments.length === 1 && isArrayLikeObject( arguments[ 0 ] ) ) { + list = arguments[ 0 ]; + } else { + list = []; + for ( i = 0; i < arguments.length; i++ ) { + list.push( arguments[ i ] ); + } + } + M = list.length; + if ( M === 0 ) { + return ''; + } + prefix = list[ 0 ]; + if ( !isString( prefix ) ) { + throw new TypeError( format( 'invalid argument. Must provide a string. Value: `%s`.', prefix ) ); + } + if ( M === 1 ) { + return prefix; + } + N = prefix.length; + for ( i = 0; i < N; i++ ) { + ch = prefix[ i ]; + for ( j = 1; j < M; j++ ) { + str = list[ j ]; + if ( !isString( str ) ) { + throw new TypeError( format( 'invalid argument. Must provide a string. Value: `%s`.', str ) ); + } + if ( i >= str.length || str[ i ] !== ch ) { + return prefix.substring( 0, i ); + } + } + } + return prefix; +} + + +// EXPORTS // + +module.exports = longestCommonPrefix; diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/main.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/main.js new file mode 100644 index 000000000000..a0ddb615d5bb --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/main.js @@ -0,0 +1,1686 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* eslint-disable no-restricted-syntax, max-lines, no-invalid-this, no-underscore-dangle */ + +'use strict'; + +// MODULES // + +var vm = require( 'vm' ); +var EventEmitter = require( 'events' ).EventEmitter; +var logger = require( 'debug' ); +var inherit = require( '@stdlib/utils/inherit' ); +var isConfigurableProperty = require( '@stdlib/assert/is-configurable-property' ); +var isReadableProperty = require( '@stdlib/assert/is-readable-property' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var objectKeys = require( '@stdlib/utils/keys' ); +var properties = require( '@stdlib/utils/properties' ); +var typeOf = require( '@stdlib/utils/type-of' ); +var append = require( '@stdlib/utils/append' ); +var setNonEnumerable = require( '@stdlib/utils/define-nonenumerable-property' ); +var setNonEnumerableReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); +var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' ); +var setReadOnly = require( '@stdlib/utils/define-read-only-property' ); +var propertyDescriptor = require( '@stdlib/utils/property-descriptor' ); +var defineProperty = require( '@stdlib/utils/define-property' ); +var isFunction = require( '@stdlib/assert/is-function' ); +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var isPlainObject = require( '@stdlib/assert/is-plain-object' ); +var isArrayLike = require( '@stdlib/assert/is-array-like-object' ); +var isRegExp = require( '@stdlib/assert/is-regexp' ); +var format = require( '@stdlib/string/format' ); +var fifo = require( '@stdlib/dstructs/fifo' ); +var nextTick = require( '@stdlib/utils/next-tick' ); +var indexOf = require( './index_of.js' ); +var findUniqueEntry = require( './find_unique_entry.js' ); +var validate = require( './validate.js' ); +var defaults = require( './defaults.js' ); +var setAliases = require( './set_aliases.js' ); +var setAliasesGlobal = require( './set_aliases_global.js' ); +var setCommands = require( './set_commands.js' ); +var setCommandsGlobal = require( './set_commands_global.js' ); +var createEvalContext = require( './create_evaluation_context.js' ); +var completerFactory = require( './completer.js' ); +var tokenizerFactory = require( './tokenizer.js' ); +var processCommand = require( './process_command.js' ); +var compileCommand = require( './compile_command.js' ); +var processInput = require( './process_input.js' ); +var updateRegExpCache = require( './update_regexp_cache.js' ); +var restoreRegExpMatches = require( './restore_regexp_matches.js' ); +var isMultilineInput = require( './is_multiline_input.js' ); +var contains = require( './contains.js' ); +var filter = require( './filter.js' ); +var setdiff = require( './setdiff.js' ); +var propertyComparator = require( './property_comparator.js' ); +var ALIAS_OVERRIDES = require( './alias_overrides.js' ); + + +// VARIABLES // + +var debug = logger( 'repl' ); +var RE_WHITESPACE = /^\s*$/; + + +// MAIN // + +/** +* REPL constructor. +* +* @constructor +* @param {Options} options - constructor options +* @param {WritableStream} [options.output=process.stdout] - output stream +* @param {WritableStream} [options.error=process.stderr] - error stream +* @param {boolean} [options.sandbox=true] - boolean indicating whether to run a REPL in a sandboxed context +* @param {PositiveInteger} [options.timeout=4294967295] - number of milliseconds to execute a command before terminating execution +* @param {string} [options.save] - file path specifying where to save REPL command history +* @param {string} [options.log] - file path specifying where to save REPL commands and printed output +* @param {string} [options.quiet=false] - boolean indicating whether log information, confirmation messages, and other possible REPL diagnostics should be silenced +* @throws {Error} must provide valid options +* @returns {REPL} REPL instance +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Execute a command: +* repl.emit( 'input', '2 + 3' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +function REPL( options ) { + var opts; + var self; + var err; + + if ( !( this instanceof REPL ) ) { + if ( arguments.length ) { + return new REPL( options ); + } + return new REPL(); + } + self = this; + + opts = defaults(); + if ( arguments.length ) { + err = validate( opts, options ); + if ( err ) { + throw err; + } + } + + debug( 'Options: %s', JSON.stringify({ + 'output': '', + 'error': '', + 'sandbox': opts.sandbox, + 'timeout': opts.timeout, + 'isTTY': opts.isTTY, + 'padding': opts.padding, + 'save': opts.save, + 'log': opts.log, + 'quiet': opts.quiet + })); + + // Call the parent constructor: + EventEmitter.call( this ); + + // Cache references to the output and error streams: + setNonEnumerableReadOnly( this, '_output', opts.output ); + setNonEnumerableReadOnly( this, '_error', opts.error ); + + // Cache options: + setNonEnumerableReadOnly( this, '_timeout', opts.timeout ); + setNonEnumerableReadOnly( this, '_sandbox', opts.sandbox ); + setNonEnumerable( this, '_quiet', opts.quiet ); // allow this to be internally toggled + + // Initialize an internal command queue: + setNonEnumerableReadOnly( this, '_queue', fifo() ); + + // Initialize a executed command counter: + setNonEnumerable( this, '_count', -1 ); + + // Initialize an internal buffer for saving regular expression matches between command evaluations: + setNonEnumerableReadOnly( this, '_regexp', [ '', '', '', '', '', '', '', '', '', '' ] ); + + // Initialize a strided internal cache of context globals: + setNonEnumerableReadOnly( this, '_contextVars', [] ); + + // For non-sandboxed REPLs, initialize an internal buffer for storing a (unique) sorted list of "built-in" REPL global variables/properties which need to be deleted upon closing a REPL in order to allow garbage collection and prevent memory leaks: + setNonEnumerableReadOnly( this, '_globalVars', ( this._sandbox ) ? null : [] ); + + // Initialize a strided internal cache of resolved global variables/properties in order to allow, e.g., help text look-up based on object reference, not just alias name (note: members alternate between `''` and ``): + setNonEnumerableReadOnly( this, '_aliases', [] ); + + // Initialize an internal buffer for storing a (unique) sorted list of workspace global variables/properties which were *initially* introduced during a REPL session (note: this overlaps with `_globalVars`, but more accurately represents a snapshot of the `global` state *before* a user begins entering commands, which is useful when wanting determine what variables/identifiers a user has introduced during a REPL session): + setNonEnumerableReadOnly( this, '_workspace', [] ); + + // Initialize a strided internal buffer for caching "base" workspace variables: + setNonEnumerableReadOnly( this, '_workspaces', {} ); + setReadOnly( this._workspaces, 'base', [] ); + + // Define the current workspace: + setNonEnumerable( this, '_currentWorkspace', 'base' ); + + // Initialize an internal flag indicating whether the REPL has been closed: + setNonEnumerable( this, '_closed', false ); + + // Initialize an internal flag indicating whether the REPL is currently busy with asynchronous processing: + setNonEnumerable( this, '_busy', false ); + + // Initialize an internal variable for caching the result of the last successfully evaluated command: + setNonEnumerable( this, '_ans', void 0 ); + + // Initialize an internal variable for setting a command callback: + setNonEnumerable( this, '_done', void 0 ); + + // Create a REPL execution context: + setNonEnumerable( this, '_context', this.createContext() ); + + // Create a new completer: + setNonEnumerableReadOnly( this, '_completer', completerFactory( this ) ); + + // Create a new tokenizer: + setNonEnumerableReadOnly( this, '_tokenizer', tokenizerFactory( this._context ) ); + + // Add listener for "command" events: + this.on( 'command', onCommand ); + this.on( 'input', onInput ); + this.on( 'interrupt', onInterrupt ); + + // TODO: check whether to synchronously initialize a REPL history file + + // TODO: check whether to synchronously initialize a REPL log file + + this._count += 1; + return this; + + /** + * Callback invoked upon encountering a command input. + * + * @private + * @param {string} input - input command + */ + function onInput( input ) { + debug( 'Received an input: %s', input ); + if ( self._closed === false ) { + processInput( self, input ); + } + } + + /** + * Callback invoked upon receiving an interrupt. + * + * @private + * @returns {void} + */ + function onInterrupt() { + debug( 'Received an interrupt.' ); + + // If the REPL is currently busy executing a command, stop waiting for it to finish: + if ( self._busy ) { + self._done( new Error( 'unexpected error. Command execution terminated.' ) ); + return; + } + + // Reset the command queue: + self._queue.clear(); + } + + /** + * Callback invoked upon executing a command. + * + * @private + * @param {string} cmd - command + * @param {boolean} success - boolean indicating whether the command successfully executed + * @param {*} res - result + * @param {boolean} silent - boolean indicating whether the command output should be silenced + */ + function onCommand() { + self._count += 1; + debug( 'Command count: %d', self._count ); + + // TODO: if successful and if necessary, (asynchronously?) write the command to a history file (question: do we only want to write successful commands to the history file? maybe we need to option for limiting to successful commands?) + + // TODO: if necessary, (asynchronously?) write the command and result to a log file (JSON serialization?) + } +} + +/* +* Inherit from the `EventEmitter` prototype. +*/ +inherit( REPL, EventEmitter ); + +/** +* Name of the current workspace. +* +* @name currentWorkspace +* @memberof REPL.prototype +* @type {string} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Get current workspace name: +* var ws = repl.currentWorkspace; +* +* // Close the REPL: +* repl.close(); +*/ +setReadOnlyAccessor( REPL.prototype, 'currentWorkspace', function get() { + return this._currentWorkspace; +}); + +/** +* Boolean indicating whether log information, confirmation messages, and other possible REPL diagnostics should be silenced. +* +* @name quiet +* @memberof REPL.prototype +* @type {boolean} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Check if the REPL is quiet: +* var out = repl.quiet; +* +* // Close the REPL: +* repl.close(); +*/ +setReadOnlyAccessor( REPL.prototype, 'quiet', function get() { + return this._quiet; +}); + +/** +* Boolean indicating whether the REPL is closed. +* +* @name closed +* @memberof REPL.prototype +* @type {boolean} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Check if the REPL is closed: +* var out = repl.closed; +* +* // Close the REPL: +* repl.close(); +* +* // Check if the REPL was closed: +* out = repl.closed; +*/ +setReadOnlyAccessor( REPL.prototype, 'closed', function get() { + return this._closed; +}); + +/** +* Command count. +* +* @name count +* @memberof REPL.prototype +* @type {number} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Get command count: +* var cnt = repl.count; +* +* // Close the REPL: +* repl.close(); +*/ +setReadOnlyAccessor( REPL.prototype, 'count', function get() { + return this._count; +}); + +/** +* Result of the last successfully evaluated command. +* +* @name ans +* @memberof REPL.prototype +* @type {*} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Execute a command: +* repl.emit( 'input', '2 + 3' ); +* +* // Get the cached result: +* var res = repl.ans; +* +* // Close the REPL: +* repl.close(); +*/ +setReadOnlyAccessor( REPL.prototype, 'ans', function get() { + return this._ans; +}); + +/** +* Checks if the given input is a possible multi-line command. +* +* @name isMultilineInput +* @memberof REPL.prototype +* @type {Function} +* @param {string} input - input command +* @returns {boolean} boolean indicating whether the given input is a possible multi-line command +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Check if an input is a possible multi-line command: +* var input = 'for( var i = 0; i < 10; i++ ) {'; +* var out = repl.isMultilineInput( input ); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'isMultilineInput', function check( input ) { + if ( !isString( input ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', input ) ); + } + return isMultilineInput( input ); +}); + +/** +* Processes a "raw" input command. +* +* @name processCommand +* @memberof REPL.prototype +* @type {Function} +* @param {string} code - unevaluated command +* @returns {(string|Error)} processed command or an error +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Process raw command: +* var code = 'var y = 10;'; +* var out = repl.processCommand( code ); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'processCommand', function process( code ) { + if ( !isString( code ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', code ) ); + } + return processCommand( code ); +}); + +/** +* Compiles a command. +* +* @name compileCommand +* @memberof REPL.prototype +* @type {Function} +* @param {string} cmd - command string +* @returns {(Object|Error)} compiled command or an error +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Process raw command: +* var code = 'var y = 10;'; +* var cmd = repl.processCommand( code ); +* +* // Compile processed command: +* var out = repl.compileCommand( cmd ); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'compileCommand', function compile( cmd ) { + if ( !isString( cmd ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', cmd ) ); + } + return compileCommand( cmd ); +}); + +/** +* Runs a compiled command. +* +* ## Note +* +* - This runs the command outside of the current REPL session's flow meaning it doesn't affect the REPL's command history or count. +* +* @name runCommand +* @memberof REPL.prototype +* @type {Function} +* @param {Object} exe - compiled executable +* @param {Object} opts - run options +* @returns {*} command result +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Process and compile a raw command: +* var cmd = '1 + 1'; +* var code = repl.processCommand( cmd ); +* var exe = repl.compileCommand( code ); +* +* // Run the compiled command: +* var out = repl.runCommand( exe, {} ); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'runCommand', function run( exe, opts ) { + if ( this._sandbox ) { + return exe.compiled.runInContext( this._context, opts ); + } + return exe.compiled.runInThisContext( opts ); +}); + +/** +* Generates completions for a given line. +* +* @name completer +* @memberof REPL.prototype +* @type {Function} +* @param {string} line - current line +* @param {Function} clbk - completion callback +* @returns {void} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Generate completions for a line: +* var line = 'var x = M'; +* repl.completer( line, clbk ); +* +* function clbk( error, completions ) { +* if ( error ) { +* throw error; +* } +* console.log( completions ); +* } +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'completer', function completer( line, clbk ) { + if ( !isString( line ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', line ) ); + } + if ( !isFunction(clbk) ) { + throw new TypeError( format( 'invalid argument. Second argument must be a function. Value: `%s`.', clbk ) ); + } + this._completer( line, clbk ); +}); + +/** +* Tokenizes the input line based on ECMAScript specification. +* +* @name tokenizer +* @memberof REPL.prototype +* @type {Function} +* @param {string} line - input line +* @returns {Array} array of tokens +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Tokenize an input line: +* var line = 'var x = 5;'; +* var out = repl.tokenizer( line ); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'tokenizer', function tokenizer( line ) { + if ( !isString( line ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', line ) ); + } + return this._tokenizer( line ); +}); + +/** +* Resolves the value of a context variable for a given alias name. +* +* @name resolveContextVarByName +* @memberof REPL.prototype +* @type {Function} +* @param {string} name - variable name +* @returns {*} resolved value +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Create a new REPL context: +* var ctx = repl.createContext({ +* 'a': 5, +* 'b': 10 +* }); +* +* // Resolve a context variable by name: +* var name = 'a'; +* var out = repl.resolveContextVarByName( 'a' ); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'resolveContextVarByName', function resolve( name ) { + var i; + + if ( !isString( name ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); + } + indexOf( this._contextVars.length, this._contextVars, 2, 0, name ); + if ( i < 0 ) { + return void 0; + } + return this._contextVars[ i+1 ]; +}); + +/** +* Resolves the name of the context variable for a given reference. +* +* @name resolveContextVarByRef +* @memberof REPL.prototype +* @type {Function} +* @param {*} ref - variable reference +* @returns {(string|undefined)} variable name +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Create a new REPL context: +* var obj = {}; +* var ctx = repl.createContext({ +* 'a': obj +* }); +* +* // Resolve a context variable by reference: +* var out = repl.resolveContextVarByRef( obj ); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'resolveContextVarByRef', function resolve( ref ) { + var i; + + // Address the fact that the `global` object is proxied (see https://github.com/nodejs/node/issues/855) + if ( + ref !== null && + typeof ref === 'object' && + hasOwnProp( ref, 'global' ) && + ref.global === ref + ) { + i = indexOf( this._contextVars.length, this._contextVars, 2, 1, this._context.global ); // eslint-disable-line max-len + } else { + i = indexOf( this._contextVars.length, this._contextVars, 2, 1, ref ); + } + if ( i < 0 ) { + return void 0; + } + return this._contextVars[ i-1 ]; +}); + +/** +* Resolves the name of an alias for a given reference. +* +* @name resolveAliasByRef +* @memberof REPL.prototype +* @type {Function} +* @param {*} ref - alias reference +* @returns {(string|undefined)} variable name +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Create a new REPL context: +* var ctx = repl.createContext(); +* +* // Resolve alias by reference to the actual alias in context: +* var alias = repl.resolveAliasByRef({}); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'resolveAliasByRef', function resolve( ref ) { + var i = indexOf( this._aliases.length/2, this._aliases, 2, 1, ref ); + if ( i < 0 ) { + return void 0; + } + return this._aliases[ i-1 ]; +}); + +/** +* Resolves the name of an alias for a given property reference. +* +* @name resolveAliasByProp +* @memberof REPL.prototype +* @type {Function} +* @param {*} ref - property reference +* @returns {(string|undefined)} variable name +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Create a new REPL context: +* var ctx = repl.createContext(); +* +* // Resolve alias by reference to the actual alias in context: +* var alias = repl.resolveAliasByRef({}); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'resolveAliasByProp', function resolve( ref ) { + var entry; + + entry = findUniqueEntry( this._aliases.length/2, this._aliases, 2, 1, ref ); + if ( entry === null ) { + return void 0; + } + return this._aliases[ entry[2]-1 ]+'.'+entry[ 1 ]; +}); + +/** +* Creates a REPL context. +* +* @name createContext +* @memberof REPL.prototype +* @type {Function} +* @param {Object} [context] - context object +* @returns {Object} REPL context +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // Return a new REPL context: +* var ctx = repl.createContext({}); +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'createContext', function createContext( context ) { + if ( arguments.length ) { + if ( !isPlainObject( context ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a plain object. Value: `%s`.', context ) ); + } + } else { + context = {}; + } + debug( 'Creating REPL execution context...' ); + + // Create an evaluation context: + context = createEvalContext( context, this._contextVars, this._output, this._error, this._sandbox ); // eslint-disable-line max-len + + // Add project APIs... + if ( this._sandbox ) { + setAliases( this._aliases, context, ALIAS_OVERRIDES ); + } else { + setAliasesGlobal( this._globalVars, this._aliases, context, ALIAS_OVERRIDES ); // eslint-disable-line max-len + } + + // NOTE: the context should not be augmented **after** this point, except as done by the user when declaring variables and functions! + + // Sort the list of global variables: + if ( this._sandbox === false ) { + this._globalVars.sort( propertyComparator ); + } + // Capture a snapshot of the current global workspace: + append( this._workspace, properties( context ).sort( propertyComparator ) ); + + return context; +}); + +/** +* Resets a REPL's context. +* +* @name resetContext +* @memberof REPL.prototype +* @type {Function} +* @returns {REPL} REPL instance +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Reset the REPL context: +* repl.resetContext(); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'resetContext', function resetContext() { + var tmp; + var key; + var o; + var i; + var j; + + debug( 'Resetting REPL execution context...' ); + + // Before creating a new execution context in a non-sandboxed environment, remove current workspace variables in order to allow garbage collection and avoid memory leaks (e.g., variables/functions declared during a REPL session which might remain bound to the environment `global` after clearing a REPL): + if ( this._sandbox === false ) { + // WARNING: in a non-sandboxed environment, if a global variable is externally introduced during a REPL session (i.e., introduced via a mechanism outside of the REPL environment), we will delete that global variable, which means the following logic may introduce unintended side-effects for this particular edge case (e.g., application code may expect the presence of the subsequently deleted global variable). While not ideal, (a) user applications should not be introducing globals to begin with and (b) the probability of a user running a REPL session, a user clearing that REPL session, AND a global variable being introduced between starting a REPL and clearing the REPL should be negligible. + tmp = this.varsWorkspace( this.currentWorkspace ); + for ( i = 0; i < tmp.length; i++ ) { + if ( isConfigurableProperty( this._context, tmp[ i ] ) ) { + delete this._context[ tmp[ i ] ]; + } + } + + // Remove REPL globals: + for ( i = 0; i < this._globalVars.length; i++ ) { + o = this._context; + key = this._globalVars[ i ].split( '.' ); // Note: this addresses nested key paths (e.g., `a.b.c`) + for ( j = 0; j < key.length-1; j++ ) { + if ( !hasOwnProp( o, key[ j ] ) ) { + o = null; + break; + } + o = o[ key[ j ] ]; + } + if ( o && isConfigurableProperty( o, key[ j ] ) ) { + delete o[ key[ j ] ]; + } + } + } + // Reset internal buffers for storing context data: + if ( this._sandbox === false ) { + this._globalVars.length = 0; + } + this._aliases.length = 0; + this._workspace.length = 0; + this._contextVars.length = 0; + + // Create a new execution context... + this._context = this.createContext(); + this.emit( 'reset', this._context ); // note: emitting the context allows REPL wrappers to extend the newly created context + + return this; +}); + +/** +* Sets commands on a context object. +* +* @name setCommands +* @memberof REPL.prototype +* @type {Function} +* @param {Object} context - context object +* @param {ArrayArray} commands - commands +* @returns {Object} context object +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Initialize empty context: +* var ctx = {}; +* +* // Define custom commands: +* function helloWorld() { +* console.log( 'Hello World!' ); +* } +* var cmds = [ [ 'helloWorld', helloWorld, false ] ]; +* +* // Set custom commands on context: +* repl.setCommands( ctx, cmds ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'setCommands', function set( context, commands ) { + if ( this._sandbox ) { + return setCommands( context, commands ); + } + return setCommandsGlobal( this._globalVars, context, commands ); +}); + +/** +* Creates a new workspace. +* +* @name createWorkspace +* @memberof REPL.prototype +* @type {Function} +* @param {string} name - workspace name +* @throws {TypeError} must provide a unique workspace name +* @returns {void} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Create new workspace: +* repl.createWorkspace( 'myWorkspace' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'createWorkspace', function createWorkspace( name ) { + if ( hasOwnProp( this._workspaces, name ) ) { + throw new TypeError( format( 'invalid argument. Workspace already exists. Value: `%s`.', name ) ); + } + this._workspaces[ name ] = []; + debug( 'Created new workspace: %s.', name ); +}); + +/** +* Switches to a specified workspace. +* +* @name switchWorkspace +* @memberof REPL.prototype +* @type {Function} +* @param {string} name - workspace name +* @returns {void} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Create new workspace: +* repl.createWorkspace( 'myWorkspace' ); +* +* // Switch to newly created workspace: +* repl.switchWorkspace( 'myWorkspace' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'switchWorkspace', function workspace( name ) { + var vars; + var curr; + var desc; + var ws; + var i; + + if ( !isString( name ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); + } + if ( !hasOwnProp( this._workspaces, name ) ) { + throw new TypeError( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', name ) ); + } + curr = this._currentWorkspace; + if ( name === curr ) { + return; + } + // Cache and delete the current workspace variables... + vars = this.varsWorkspace( curr ); + ws = this._workspaces[ curr ]; + ws.length = 0; // reset + for ( i = 0; i < vars.length; i++ ) { + desc = propertyDescriptor( this._context, vars[ i ] ); + ws.push( vars[ i ], desc ); + + // WARNING: in non-sandboxed environments, we run the risk of deleting global variables which were not introduced by the REPL environment... + if ( desc.configurable ) { + delete this._context[ vars[ i ] ]; + } + } + // Reset the REPL evaluation context (Why? Because we cannot simply delete variables as seen within the REPL environment. E.g., variables declared with `var` in the global scope are non-configurable, and, thus, cannot be deleted (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete). Hence, while we can delete a property/variable here, this deletion does not get propagated to within the REPL environment; i.e., a user can still access the deleted property as a variable within the REPL environment.): + this.resetContext(); + + // Load the workspace's variables... + ws = this._workspaces[ name ]; + for ( i = 0; i < ws.length; i += 2 ) { + desc = propertyDescriptor( this._context, ws[ i ] ); + + // If the variable does not already exist in the current evaluation context, define a new variable... + if ( desc === null ) { + defineProperty( this._context, ws[ i ], ws[ i+1 ] ); + } + // If configurable, we can simply overwrite the existing property descriptor... + else if ( desc.configurable ) { + defineProperty( this._context, ws[ i ], ws[ i+1 ] ); + } + // Otherwise, use direct assignment if the variable is writable... + else if ( hasOwnProp( desc, 'value' ) || hasOwnProp( desc, 'set' ) ) { + this._context[ ws[ i ] ] = ws[ i+1 ]; + } + // Cannot assign to the variable as the variable is read-only... + else { + debug( 'Cannot load \'%s\' from \'%s\' workspace due to the presence of a non-configurable read-only variable of the same name.', ws[ i ], name ); + } + } + ws.length = 0; // free up memory and prevent holding on to old references + debug( 'Switched to %s workspace.', name ); + + // Update the current workspace variable: + this._currentWorkspace = name; // bookkeeping +}); + +/** +* Loads variables from a specified workspace into the current workspace. +* +* @name loadWorkspace +* @memberof REPL.prototype +* @type {Function} +* @param {string} name - workspace name +* @param {Options} [options] - function options +* @param {(RegExp|ArrayLikeObject)} [options.include] - name inclusion filter +* @param {(RegExp|ArrayLikeObject)} [options.exclude] - name exclusion filter +* @param {boolean} [options.override=true] - boolean indicating whether to override existing workspace variables +* @returns {number} number of variables loaded +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Create new workspace: +* repl.createWorkspace( 'myWorkspace' ); +* +* // Load variables from a workspace: +* var count = repl.loadWorkspace( 'myWorkspace', {} ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'loadWorkspace', function loadWorkspace( name, options ) { + var isArrInc; + var isArrExc; + var opts; + var cnt; + var ws; + var v; + var i; + if ( !isString( name ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); + } + opts = { + 'override': true + }; + if ( arguments.length > 1 ) { + if ( !isPlainObject( options ) ) { + throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', name ) ); + } + if ( hasOwnProp( options, 'include' ) ) { + isArrInc = isArrayLike( options.include ); + if ( isArrInc === false && !isRegExp( options.include ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'include', options.include ) ); + } + opts.include = options.include; + } + if ( hasOwnProp( options, 'exclude' ) ) { + isArrExc = isArrayLike( options.exclude ); + if ( isArrExc === false && !isRegExp( options.exclude ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'exclude', options.exclude ) ); + } + opts.exclude = options.exclude; + } + if ( hasOwnProp( options, 'override' ) ) { + if ( !isBoolean( options.override ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'override', options.override ) ); + } + opts.override = options.override; + } + } + if ( name === this._currentWorkspace ) { + return; + } + if ( !hasOwnProp( this._workspaces, name ) ) { + throw new TypeError( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', name ) ); + } + ws = this._workspaces[ name ]; + + // Note: the internal branches are not the most performant implementation, but the implementation is straightforward and presumably "good enough"... + cnt = 0; + for ( i = 0; i < ws.length; i += 2 ) { + v = ws[ i ]; + if ( opts.include ) { + if ( isArrInc && !contains( opts.include, v ) ) { + continue; + } + if ( !opts.include.test( v ) ) { + continue; + } + } + if ( opts.exclude ) { + if ( isArrExc && contains( opts.exclude, v ) ) { + continue; + } + if ( opts.exclude.test( v ) ) { + continue; + } + } + if ( hasOwnProp( this._context, v ) && opts.override === false ) { + continue; + } + // If we've made it this far, the variable should have passed all filters... + cnt += 1; + defineProperty( this._context, v, ws[ i+1] ); + } + return cnt; +}); + +/** +* Returns list of all workspaces. +* +* @name workspaces +* @memberof REPL.prototype +* @type {Function} +* @returns {Array} workspace names +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // List all workspaces: +* var list = repl.workspaces(); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'workspaces', function workspaces() { + return objectKeys( this._workspaces ); +}); + +/** +* Returns a list of variable names in a specified workspace. +* +* @name varsWorkspace +* @memberof REPL.prototype +* @type {Function} +* @param {string} name - workspace name +* @param {Options} [options] - function options +* @param {RegExp} [options.include] - name inclusion filter +* @param {RegExp} [options.exclude] - name exclusion filter +* @param {ArrayLikeObject} [options.types] - type inclusion filter(s) +* @param {boolean} [options.details] - boolean indicating whether to include additional variable details, such as variable type, contents, etc +* @throws {TypeError} must provide a recognized workspace name +* @returns {Array} workspace variable names +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Get list of variables in current workspace: +* var list = repl.varsWorkspace( repl.currentWorkspace ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'varsWorkspace', function varsWorkspace( name, options ) { + var list; + var type; + var out; + var tmp; + var FLG; + var i; + var v; + var j; + + if ( !isString( name ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); + } + if ( arguments.length > 1 ) { + if ( !isPlainObject( options ) ) { + throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + } else { + options = {}; + } + if ( hasOwnProp( options, 'include' ) && !isRegExp( options.include ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a regular expression. Option: `%s`.', 'include', options.include ) ); + } + if ( hasOwnProp( options, 'exclude' ) && !isRegExp( options.exclude ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a regular expression. Option: `%s`.', 'exclude', options.include ) ); + } + if ( hasOwnProp( options, 'types' ) && !isArrayLike( options.types ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be an array-like object. Option: `%s`.', 'types', options.types ) ); + } + if ( hasOwnProp( options, 'details' ) && !isBoolean( options.details ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'details', options.details ) ); + } + if ( name === this._currentWorkspace ) { + tmp = properties( this._context ).sort( propertyComparator ); + tmp = setdiff( this._workspace, tmp ); + list = []; + for ( i = 0; i < tmp.length; i++ ) { + if ( isReadableProperty( this._context, tmp[ i ] ) ) { + list.push( tmp[ i ], this._context[ tmp[ i ] ] ); + } else { + // The variable can be set, but not retrieved (i.e., is write-only), so value inspection is not possible without triggering an error... + list.push( tmp[ i ], void 0 ); + } + } + } else { + if ( !hasOwnProp( this._workspaces, name ) ) { + throw new Error( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', name ) ); + } + list = this._workspaces[ name ].slice(); + for ( i = 1; i < list.length; i += 2 ) { + if ( typeof list[ i ].get === 'function' ) { + // WARNING: the `this` context is not defined, as the variable is not actually bound to a global instance! + list[ i ] = list[ i ].get.call( null ); + } else if ( typeof list[ i ].set === 'function' ) { + // The variable can be set, but not retrieved (i.e., is write-only), so value inspection is not possible without triggering an error... + list[ i ] = void 0; + } else { + list[ i ] = list[ i ].value; + } + } + } + out = []; + for ( i = 0; i < list.length; i += 2 ) { + v = list[ i ]; + FLG = false; + type = ''; + if ( options.include && !options.include.test( v ) ) { + continue; + } + if ( options.exclude && options.exclude.test( v ) ) { + continue; + } + if ( options.types ) { + type = typeOf( list[ i+1 ] ); + for ( j = 0; j < options.types.length; j++ ) { + if ( type === options.types[ j ] ) { + FLG = true; + break; + } + } + if ( FLG === false ) { + continue; + } + } + // If we've made it this far, the variable should have passed all filters... + out.push( v ); + if ( options.details ) { + j = out.length - 1; + out[ j ] = { + 'name': out[ j ], + 'type': type || typeOf( list[ i+1 ] ), + 'data': String( list[ i+1 ] ) // WARNING: for large datasets, this could be expensive!!! TODO: may want to consider alternative strategies for serialization based on a value's type. + }; + v = out[ j ].data; + if ( v.length > 20 ) { + out[ j ].data = v.slice( 0, 9 ) + '...' + v.slice( v.length-8 ); + } + } + } + return out; +}); + +/** +* Evaluates an expression in a specified workspace. +* +* @name evalin +* @memberof REPL.prototype +* @type {Function} +* @param {string} workspace - workspace name +* @param {string} expression - expression to evaluate +* @returns {void} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Evaluate in base workspace: +* repl.evalin( 'base', 'var x = 5;' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'evalin', function evalin( workspace, expression ) { + var script; + var opts; + var FLG; + var ws; + if ( !isString( workspace ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', workspace ) ); + } + if ( !isString( expression ) ) { + throw new TypeError( format( 'invalid argument. Second argument must be a string. Value: `%s`.', workspace ) ); + } + if ( RE_WHITESPACE.test( expression ) ) { + debug( 'Expression only consists of whitespace. Nothing to evaluate.' ); + return; + } + // Cache the name of the current workspace: + ws = this._currentWorkspace; + + // Temporarily silence logging: + FLG = this._quiet; + this._quiet = true; + + try { + // Switch to the target workspace: + this.switchWorkspace( workspace ); + } catch ( error ) { + this._quiet = FLG; + throw error; + } + // Try evaluating the expression... + opts = { + 'filename': '', + 'lineOffset': 0 + }; + try { + // FIXME: this needs to follow the same logic as `process_line`, such as code wrapping, asynchronous execution, and handling top-level `await`!!! + script = new vm.Script( expression, opts ); + } catch ( error ) { + this.switchWorkspace( ws ); + this._quiet = FLG; + throw error; + } + // Set the (non-standard) properties on the `RegExp` expression object to the cached matches: + restoreRegExpMatches( this._regexp ); + + opts = { + 'timeout': this._timeout, + 'displayErrors': false, + 'breakOnSigint': true // Note: only applies for Node.js versions >=6.3.0 + }; + + // FIXME: we need to follow similar logic as `drain.js`, such as SIGINT handling!!! + script.runInContext( this._context, opts ); + updateRegExpCache( this._regexp ); + + // Return to the previous workspace: + this.switchWorkspace( ws ); + + // Re-enable logging (if enabled): + this._quiet = FLG; +}); + +/** +* Renames a workspace. +* +* @name renameWorkspace +* @memberof REPL.prototype +* @type {Function} +* @param {string} oldName - name of workspace to rename +* @param {string} newName - new workspace name +* @throws {TypeError} old name must be a recognized workspace name +* @throws {TypeError} new name must be a unique workspace name +* @throws {Error} new name must be different than the old name +* @returns {void} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Create new workspace: +* repl.createWorkspace( 'myWorkspace' ); +* +* // Rename workspace: +* repl.renameWorkspace( 'myWorkspace', 'yourWorkspace' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'renameWorkspace', function renameWorkspace( oldName, newName ) { + if ( !isString( oldName ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', oldName ) ); + } + if ( !isString( newName ) ) { + throw new TypeError( format( 'invalid argument. Second argument must be a string. Value: `%s`.', newName ) ); + } + if ( !hasOwnProp( this._workspaces, oldName ) ) { + throw new TypeError( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', oldName ) ); + } + if ( oldName === newName ) { + throw new Error( format( 'invalid arguments. New name must be different than the old name. Value: `%s`.', oldName ) ); + } + if ( hasOwnProp( this._workspaces, newName ) ) { + throw new TypeError( format( 'invalid argument. Workspace name already exists. Value: `%s`.', newName ) ); + } + if ( oldName === this._currentWorkspace ) { + if ( oldName === 'base' ) { + this._workspaces[ 'base' ].length = 0; + debug( 'Created \'%s\' workspace and cleared \'base\' workspace. Current workspace: \'%s\'.', newName, newName ); + } else { + delete this._workspaces[ oldName ]; + debug( 'Renamed \'%s\' workspace to \'%s\'. Current workspace: \'%s\'.', oldName, newName, newName ); + } + this._workspaces[ newName ] = []; // "registers" the workspace + this._currentWorkspace = newName; // bookkeeping + return; + } + if ( oldName === 'base' ) { + this._workspaces[ newName ] = this._workspaces[ 'base' ].slice(); + this._workspaces[ 'base' ].length = 0; + debug( 'Created \'%s\' workspace and cleared \'base\' workspace.', newName ); + return; + } + this._workspaces[ newName ] = this._workspaces[ oldName ]; + delete this._workspaces[ oldName ]; + debug( 'Renamed \'%s\' workspace to \'%s\'.', oldName, newName ); +}); + +/** +* Deletes a workspace. +* +* @name deleteWorkspace +* @memberof REPL.prototype +* @type {Function} +* @param {string} name - workspace name +* @throws {TypeError} must provide a recognized workspace name other than 'base' +* @returns {void} +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Create new workspace: +* repl.createWorkspace( 'yourWorkspace' ); +* +* // Delete workspace: +* repl.deleteWorkspace( 'yourWorkspace' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'deleteWorkspace', function deleteWorkspace( name ) { + if ( !isString( name ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); + } + if ( !hasOwnProp( this._workspaces, name ) ) { + throw new TypeError( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', name ) ); + } + if ( name === 'base' ) { + throw new TypeError( 'invalid operation. Cannot delete the `base` workspace.' ); + } + if ( name === this._currentWorkspace ) { + this.switchWorkspace( 'base' ); + } + delete this._workspaces[ name ]; +}); + +/** +* Deletes user-defined variables in a specified workspace. +* +* @name clearWorkspace +* @memberof REPL.prototype +* @type {Function} +* @param {string} name - workspace name +* @param {Options} [options] - function options +* @param {(RegExp|ArrayLikeObject)} [options.include] - name inclusion filter +* @param {(RegExp|ArrayLikeObject)} [options.exclude] - name exclusion filter +* @throws {TypeError} must provide a recognized workspace name +* @throws {TypeError} must provide a valid options object +* @returns {number} number of deleted variables +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Clear user workspace: +* var d = repl.clearWorkspace( 'base' ); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'clearWorkspace', function clearWorkspace( name, options ) { + var isArrInc; + var isArrExc; + var list; + var desc; + var tmp; + var i; + var d; // FIXME: Idt this variable is used correctly + + if ( !isString( name ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); + } + if ( arguments.length > 1 ) { + if ( !isPlainObject( options ) ) { + throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + } else { + options = {}; + } + if ( hasOwnProp( options, 'include' ) ) { + isArrInc = isArrayLike( options.include ); + if ( isArrInc === false && !isRegExp( options.include ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'include', options.include ) ); + } + } + if ( hasOwnProp( options, 'exclude' ) ) { + isArrExc = isArrayLike( options.exclude ); + if ( isArrExc === false && !isRegExp( options.exclude ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'exclude', options.include ) ); + } + } + if ( name === this._currentWorkspace ) { + // Get the current variable list: + tmp = this.varsWorkspace( name, {} ); + if ( tmp.length === 0 ) { + // No user-defined variables to delete... + return; + } + // Cache the variable names and their respective property descriptors: + list = []; + for ( i = 0; i < tmp.length; i++ ) { + list.push( tmp[ i ], propertyDescriptor( this._context, tmp[i] ) ); + } + d = list.length / 2; + + // Filter the list of variables: + list = filter( list, options.include, isArrInc, options.exclude, isArrExc ); // eslint-disable-line max-len + + // Reset the REPL evaluation context (Why? Because we cannot simply delete variables as seen within the REPL environment. E.g., variables declared with `var` in the global scope are non-configurable, and, thus, cannot be deleted (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete). While we can delete a property/variable from the REPL context object here, this deletion does not get propagated to within the REPL environment; i.e., a user can still access the deleted property as a variable within the REPL environment. Hence, we need to adopt a cache, reset, and reassign approach, as done here.): + this.resetContext(); // Note: in sandboxed environments, we assume a fresh context object is created! + + // Reassign the variables which were not deleted: + for ( i = 0; i < list.length; i += 2 ) { + desc = list[ i+1 ]; + if ( desc.configurable || this._sandbox ) { + // If configurable, in non-sandboxed environments, we simply overwrite the existing descriptor; in sandboxed environments, we always need to redefine the variable with the appropriate property descriptor; if non-configurable, in non-sandboxed environments, we do not need to reassign/redefine, as the variable could not be deleted from the context object and thus already exists and cannot be reconfigured: + defineProperty( this._context, list[ i ], desc ); + } + } + d -= list.length / 2; + return d; + } + if ( !hasOwnProp( this._workspaces, name ) ) { + throw new TypeError( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', name ) ); + } + list = this._workspaces[ name ]; + + // Case: clear all user-defined variables... + if ( options.include === void 0 && options.exclude === void 0 ) { + list.length = 0; + return d; + } + // Case: include/exclude filters: + list = filter( list, options.include, isArrInc, options.exclude, isArrExc ); + d -= list.length / 2; + return d; +}); + +/** +* Resets a REPL. +* +* @name reset +* @memberof REPL.prototype +* @type {Function} +* @throws {Error} cannot reset a closed REPL +* @returns {REPL} REPL instance +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Reset the REPL: +* repl.reset(); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'reset', function onReset() { + if ( this._closed ) { + throw new Error( 'invalid operation. Cannot reset a REPL which has already closed.' ); + } + debug( 'Resetting REPL...' ); + + // Reset the command queue: + this._queue.clear(); + + // Reset the execution context: + this.resetContext(); + + return this; +}); + +/** +* Closes a REPL. +* +* @name close +* @memberof REPL.prototype +* @type {Function} +* @returns {REPL} REPL instance +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'close', function close() { + var self; + if ( this._closed ) { + debug( 'Attempted to close an already closed REPL.' ); + return this; + } + self = this; + this._closed = true; + + // Clear the command queue: + this._queue.clear(); + + // TODO: ensure REPL history is saved (flushed) to file before closing the REPL (see https://github.com/nodejs/node/blob/b21e7c7bcf23a2715951e4cd96180e4dbf1dcd4d/lib/repl.js#L805) + + // TODO: ensure REPL log is saved (flushed) to file before closing the REPL + + nextTick( onTick ); + + return this; + + /** + * Callback invoked upon the next tick of the event loop. + * + * @private + */ + function onTick() { + var tmp; + var key; + var o; + var i; + var j; + + // If this is a non-sandboxed REPL, remove global variables/properties which were introduced during context creation and by a user during a REPL session... + if ( self._sandbox === false ) { + // WARNING: in a non-sandboxed environment, if a global variable is externally introduced during a REPL session (i.e., introduced via a mechanism outside of the REPL environment), we will delete that global variable, which means the following logic may introduce unintended side-effects for this particular edge case (e.g., application code may expect the presence of the subsequently deleted global variable). While not ideal, (a) user applications should not be introducing globals to begin with and (b) the probability of a user running a REPL session, a user closing that REPL session, AND a global variable being introduced between starting a REPL and closing the REPL should be negligible. + tmp = self._context.vars(); // current workspace variables + for ( i = 0; i < tmp.length; i++ ) { + if ( isConfigurableProperty( self._context, tmp[ i ] ) ) { + delete self._context[ tmp[ i ] ]; + } + } + + // Remove REPL globals: + for ( i = 0; i < self._globalVars.length; i++ ) { + o = self._context; + key = self._globalVars[ i ].split( '.' ); // Note: this addresses nested key paths (e.g., `a.b.c`) + for ( j = 0; j < key.length-1; j++ ) { + if ( !hasOwnProp( o, key[ j ] ) ) { + o = null; + break; + } + o = o[ key[ j ] ]; + } + if ( o && isConfigurableProperty( o, key[ j ] ) ) { + delete o[ key[ j ] ]; + } + } + } + } +}); + + +// EXPORTS // + +module.exports = REPL; diff --git a/lib/node_modules/@stdlib/repl/lib/process_command.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/process_command.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/process_command.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/process_command.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/process_input.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/process_input.js new file mode 100644 index 000000000000..47767349dab2 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/process_input.js @@ -0,0 +1,89 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* eslint-disable no-underscore-dangle */ + +'use strict'; + +// MODULES // + +var logger = require( 'debug' ); +var drain = require( './drain.js' ); + + +// VARIABLES // + +var debug = logger( 'repl:process-command' ); +var RE_WHITESPACE = /^\s*$/; +var RE_SINGLE_LINE_COMMENT = /^\s*\/\//; +var RE_MULTI_LINE_COMMENT = /^\s*\/\*.*\*\/$/; + + +// MAIN // + +/** +* Processes input command. +* +* @private +* @param {REPL} repl - REPL instance +* @param {string} input - input command +* @returns {void} +*/ +function processInput( repl, input ) { + var code; + var tmp; + + if ( RE_WHITESPACE.test( input ) ) { + return; + } + if ( RE_SINGLE_LINE_COMMENT.test( input ) || RE_MULTI_LINE_COMMENT.test( input ) ) { // eslint-disable-line max-len + debug( 'Detected single-line comment.' ); + tmp = input; + } else { + // Check if the command has valid syntax... + debug( 'Processing command...' ); + tmp = repl.processCommand( input ); + if ( tmp instanceof Error ) { + repl.emit( 'command', input, false, tmp, false ); // command failed + return; + } + } + debug( 'Successfully processed command.' ); + + // Attempt to compile the command: + debug( 'Attempting to compile command...' ); + code = repl.compileCommand( tmp ); + if ( code instanceof Error ) { + debug( 'Error: %s', code.message ); + repl.emit( 'command', input, false, code, false ); // command failed + return; + } + debug( 'Successfully compiled command.' ); + code.raw = input; + + // Add the command to the command queue: + repl._queue.push( code ); + + // Request to run the command: + drain( repl ); +} + + +// EXPORTS // + +module.exports = processInput; diff --git a/lib/node_modules/@stdlib/repl/lib/process_top_level_await.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/process_top_level_await.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/process_top_level_await.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/process_top_level_await.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/property_comparator.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/property_comparator.js new file mode 100644 index 000000000000..856e1a3c1367 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/property_comparator.js @@ -0,0 +1,63 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Comparator function for sorting property names and symbols in lexicography order. +* +* ## Notes +* +* - Symbols are sorted **after** names. +* +* @private +* @param {(string|symbol)} a - property +* @param {(string|symbol)} b - property +* @returns {integer} comparison result +*/ +function comparator( a, b ) { + var ta = typeof a; + var tb = typeof b; + + // Strings are sorted before symbols: + if ( ta === 'string' && tb === 'symbol' ) { + return -1; + } + if ( ta === 'symbol' && tb === 'string' ) { + return 1; + } + // Convert symbols to strings: + a = String( a ); + b = String( b ); + + // Sort in lexicographic order: + if ( a < b ) { + return -1; + } + if ( a === b ) { + return 0; + } + return 1; +} + + +// EXPORTS // + +module.exports = comparator; diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_fs_aliases.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_fs_aliases.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/regexp_fs_aliases.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_fs_aliases.js diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_index.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_index.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/regexp_index.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_index.js diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_path.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_path.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/regexp_path.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_path.js diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_relative_require_path.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_relative_require_path.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/regexp_relative_require_path.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_relative_require_path.js diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_require.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_require.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/regexp_require.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_require.js diff --git a/lib/node_modules/@stdlib/repl/lib/settings_alias_args.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_reserved_syntax_characters.js similarity index 59% rename from lib/node_modules/@stdlib/repl/lib/settings_alias_args.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_reserved_syntax_characters.js index ead6beda6e6e..c72e86e13e6a 100644 --- a/lib/node_modules/@stdlib/repl/lib/settings_alias_args.js +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_reserved_syntax_characters.js @@ -18,31 +18,25 @@ 'use strict'; -// MODULES // - -var SETTINGS_ALIASES = require( './settings_aliases.js' ); - - // MAIN // /** -* Returns a list of argument completion flags for a specified settings API. +* Returns a regular expression for matching reserved JavaScript syntax characters. * * @private -* @param {string} alias - alias -* @returns {(Array|null)} argument completion flags +* @returns {RegExp} regular expression +* +* @example +* var RE_SYNTAX_CHARS = createRegExp(); +* +* var bool = RE_SYNTAX_CHARS.test( '()' ); +* // returns true */ -function argFlags( alias ) { - var i; - for ( i = 0; i < SETTINGS_ALIASES.length; i++ ) { - if ( SETTINGS_ALIASES[ i ][ 0 ] === alias ) { - return SETTINGS_ALIASES[ i ].slice( 1 ); - } - } - return null; +function createRegExp() { + return /[`~!@#%^&*()\-=+[\]{}\\/|;:'",<>? ]/; } // EXPORTS // -module.exports = argFlags; +module.exports = createRegExp; diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_workspace.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_workspace.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/regexp_workspace.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/regexp_workspace.js diff --git a/lib/node_modules/@stdlib/repl/lib/reserved_keywords.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/reserved_keywords.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/reserved_keywords.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/reserved_keywords.js diff --git a/lib/node_modules/@stdlib/repl/lib/reserved_keywords_common.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/reserved_keywords_common.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/reserved_keywords_common.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/reserved_keywords_common.js diff --git a/lib/node_modules/@stdlib/repl/lib/reserved_keywords_empty_block_statement.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/reserved_keywords_empty_block_statement.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/reserved_keywords_empty_block_statement.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/reserved_keywords_empty_block_statement.js diff --git a/lib/node_modules/@stdlib/repl/lib/resolve_globals.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/resolve_globals.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/resolve_globals.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/resolve_globals.js diff --git a/lib/node_modules/@stdlib/repl/lib/resolve_local_scope.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/resolve_local_scope.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/resolve_local_scope.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/resolve_local_scope.js diff --git a/lib/node_modules/@stdlib/repl/lib/resolve_local_scopes.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/resolve_local_scopes.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/resolve_local_scopes.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/resolve_local_scopes.js diff --git a/lib/node_modules/@stdlib/repl/lib/restore_regexp_matches.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/restore_regexp_matches.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/restore_regexp_matches.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/restore_regexp_matches.js diff --git a/lib/node_modules/@stdlib/repl/lib/set_aliases.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/set_aliases.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/set_aliases.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/set_aliases.js diff --git a/lib/node_modules/@stdlib/repl/lib/set_aliases_global.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/set_aliases_global.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/set_aliases_global.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/set_aliases_global.js diff --git a/lib/node_modules/@stdlib/repl/lib/set_commands.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/set_commands.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/set_commands.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/set_commands.js diff --git a/lib/node_modules/@stdlib/repl/lib/set_commands_global.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/set_commands_global.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/set_commands_global.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/set_commands_global.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/setdiff.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/setdiff.js new file mode 100644 index 000000000000..a646ba1dad93 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/setdiff.js @@ -0,0 +1,193 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// VARIABLES // + +var TYPE_SORT_ORDER = { + 'number': 0, + 'string': 1, + 'symbol': 2 +}; + + +// MAIN // + +/** +* Returns the set difference between two similarly **sorted** lists. +* +* ## Notes +* +* - The contents of the provided arrays are assumed to be either numbers, strings, or symbols. +* +* - The lists are **expected** to be sorted not only, e.g., lexicographically, but also according to type in the **following** order: `numbers`, `strings`, and then `symbols`. +* +* ```text +* A = [ 1, 2, 3, '1', '2', '3', Symbol('1'), Symbol('2'), Symbol('3') ] +* B = [ 1, 2, '1', '3', Symbol('2'), Symbol('3') ] +* // => [ 3, '2', Symbol('1') ] +* ``` +* +* @private +* @param {Array} A - first sorted list +* @param {Array} B - second sorted list +* @returns {Array} set difference +* +* @example +* var out = setdiff( [ 1, 2, 3 ], [ 2, 4, 5 ] ); +* // returns [ 1, 3, 4, 5 ] +* +* @example +* var out = setdiff( [ 1 ], [ 2, 4, 5 ] ); +* // returns [ 1, 2, 4, 5 ] +* +* @example +* var out = setdiff( [ 1, 2, 3 ], [ 2 ] ); +* // returns [ 1, 3 ] +* +* @example +* var out = setdiff( [ 1, 2, 3 ], [] ); +* // returns [ 1, 2, 3 ] +* +* @example +* var out = setdiff( [], [ 2, 4, 5 ] ); +* // returns [ 2, 4, 5 ] +* +* @example +* var out = setdiff( [ 1, 2, 3 ], [ 1, 2, 3 ] ); +* // returns [] +* +* @example +* var out = setdiff( [], [] ); +* // returns [] +* +* @example +* var out = setdiff( [ 1 ], [ 1 ] ); +* // returns [] +* +* @example +* var out = setdiff( [ 1, 2, 2, 3, 3 ], [ 2, 4, 5, 5 ] ); +* // returns [ 1, 2, 3, 3, 4, 5, 5 ] +* +* @example +* var out = setdiff( [ 1, 2, 3 ], [ 4, 5 ] ); +* // returns [ 1, 2, 3, 4, 5 ] +* +* @example +* var out = setdiff( [ 1, 2 ], [ 3, 4, 5 ] ); +* // returns [ 1, 2, 3, 4, 5 ] +* +* @example +* var out = setdiff( [ 1, 2, 3, 7 ], [ 0, 1, 2, 4, 5 ] ); +* // returns [ 0, 3, 4, 5, 7 ] +* +* @example +* var out = setdiff( [ 1, 2, 3, 7, 9 ], [ -2, -1, 0, 1, 2, 4, 5 ] ); +* // returns [ -2, -1, 0, 3, 4, 5, 7, 9 ] +*/ +function setdiff( A, B ) { + var out; + var la; + var lb; + var ta; + var tb; + var a; + var b; + var i; + var j; + var k; + + la = A.length; + lb = B.length; + if ( la === 0 ) { + return B.slice(); + } + if ( lb === 0 ) { + return A.slice(); + } + out = []; + i = 0; + j = 0; + while ( i < la && j < lb ) { + a = A[ i ]; + b = B[ j ]; + if ( a === b ) { // addresses numbers, strings, and symbols alike + i += 1; + j += 1; + continue; + } + ta = typeof a; + tb = typeof b; + if ( ta !== tb ) { + // Note: we assume we have found a "type" border! + ta = TYPE_SORT_ORDER[ ta ]; + tb = TYPE_SORT_ORDER[ tb ]; + if ( ta < tb ) { + out.push( a ); + i += 1; + } else { // tb < ta + out.push( b ); + j += 1; + } + } + // Note: the types for `a` and `b` are the *same*! + else if ( ta === 'symbol' ) { + // Note: symbols don't have a "natural" sort order, so we need to do things in a more computationally intensive way via linear scans... + while ( i < la ) { + for ( k = j+1; k < lb; k++ ) { // `j+1` because we already know the symbols are not equal + if ( a === B[ k ] ) { + break; + } + } + // If we searched through all the symbols in `B` and failed to find a match, we found a unique symbol... + if ( k === lb ) { + out.push( a ); + } else { + // We can leverage the fact that symbols in `A` and `B` should be similarly sorted by recognizing that, if we found a match, this means that the symbols in `B` preceding the match should be unique... + for ( ; j < k; j++ ) { + out.push( B[ j ] ); + } + } + i += 1; + } + } else if ( a < b ) { + out.push( a ); + i += 1; + } else { // b < a + out.push( b ); + j += 1; + } + } + if ( i < la ) { + for ( ; i < la; i++ ) { + out.push( A[ i ] ); + } + } + if ( j < lb ) { + for ( ; j < lb; j++ ) { + out.push( B[ j ] ); + } + } + return out; +} + + +// EXPORTS // + +module.exports = setdiff; diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/tokenizer.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/tokenizer.js new file mode 100644 index 000000000000..3d5b5a68ea84 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/tokenizer.js @@ -0,0 +1,408 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* eslint-disable max-lines-per-function, id-length */ + +'use strict'; + +// MODULES // + +var parse = require( 'acorn-loose' ).parse; +var walk = require( 'acorn-walk' ); +var hasProp = require( '@stdlib/assert/has-property' ); +var linkedList = require( '@stdlib/dstructs/linked-list' ); +var contains = require( '@stdlib/array/base/assert/contains' ); +var resolveLocalScopes = require( './resolve_local_scopes.js' ); +var resolveLocalScope = require( './resolve_local_scope.js' ); + + +// VARIABLES // + +var isUnrecognizedKeyword = contains.factory( [ 'async', 'let' ] ); +var isControlKeyword = contains.factory( [ 'if', 'else', 'switch', 'case', 'catch', 'finally', 'try', 'return', 'break', 'continue' ] ); +var isUnrecognizedControlKeyword = contains.factory( [ 'await' ] ); +var isSpecialIdentifier = contains.factory( [ 'this', 'super' ] ); +var isReservedLiteral = contains.factory( [ 'null', 'true', 'false' ] ); +var isUnrecognizedReservedLiteral = contains.factory( [ 'undefined' ] ); +var isStringTokenType = contains.factory( [ 'string', 'template' ] ); +var isLiteralType = contains.factory( [ 'string', 'boolean', 'number' ] ); +var isReservedName = contains.factory( [ 'undefined', 'async', 'await', 'let' ] ); +var RE_PUNCTUATION = /(\{|\}|\[|\]|\(|\)|,|;|:|\.|\?|\?\.|=>|\.\.\.|`|\${)/; + + +// MAIN // + +/** +* Returns a callback for tokenization. +* +* @private +* @name tokenizer +* @type {Function} +* @param {Object} context - REPL context +* @returns {Function} tokenizer callback +*/ +function tokenizer( context ) { + return tokenize; + + /** + * Tokenizes the input line based on ECMAScript specification. + * + * @private + * @name tokenize + * @type {Function} + * @param {string} line - input line + * @returns {Array} array of tokens + */ + function tokenize( line ) { + var declarations; + var VISITORS; + var tokens = []; + var ast; + var i; + + // Parse the given line into tokens & comments... + try { + ast = parse( line, { + 'ecmaVersion': 'latest', + 'onToken': onToken, + 'onComment': onComment + }); + } catch ( error ) { // eslint-disable-line no-unused-vars + return tokens; + } + + // Resolve variable declarations from the given line as tokens... + declarations = resolveLocalScopes( ast ); + for ( i = 0; i < declarations.length; i++ ) { + // If declaration cannot be resolved as an identifier, push it as a `name` token: + if ( !resolveIdentifier( declarations[ i ] ) ) { + tokens.push({ + 'value': declarations[ i ].name, + 'type': 'name', + 'start': declarations[ i ].start, + 'end': declarations[ i ].end + }); + } + } + + // Resolve identifiers from the given line as tokens... + VISITORS = { + 'Identifier': resolveIdentifier, + 'MemberExpression': resolveMemberExpression + }; + walk.simple( ast, VISITORS ); + + return tokens; + + /** + * Callback invoked upon encountering a `Token` when parsing. + * + * @private + * @param {Object} token - token object + */ + function onToken( token ) { + // Ignore placeholders & EOF tokens: + if ( token.start >= token.end ) { + return; + } + if ( token.type.isLoop || isControlKeyword( token.type.keyword ) || ( token.type.label === 'name' && isUnrecognizedControlKeyword( token.value ) ) ) { + // Control flow keywords - `for`, `while`, `do`, `if`, `else` etc: + token.type = 'control'; + tokens.push( token ); + return; + } + if ( isSpecialIdentifier( token.type.keyword ) ) { + // Special identifiers - `this`, `super`: + token.type = 'specialIdentifier'; + tokens.push( token ); + return; + } + if ( isReservedLiteral( token.type.keyword ) ) { + // Built-in literals - `true`, `false`, `null`, `undefined`: + token.type = 'literal'; + tokens.push( token ); + return; + } + if ( token.type.keyword || ( token.type.label === 'name' && isUnrecognizedKeyword( token.value ) ) ) { + // Keywords - `function`, `import`, `var`, `const`, `let` etc.: + token.type = 'keyword'; + tokens.push( token ); + return; + } + if ( isStringTokenType( token.type.label ) ) { + // Strings and template string literals: + token.type = 'string'; + tokens.push( token ); + return; + } + if ( token.type.label === 'regexp' ) { + // Regex expressions: + token.type = 'regexp'; + tokens.push( token ); + return; + } + if ( token.type.label === 'num' ) { + // Numeric literals: + token.type = 'number'; + tokens.push( token ); + return; + } + if ( token.type.binop || token.type.prefix || token.type.postfix || token.type.isAssign ) { // eslint-disable-line max-len + // Operator symbols - `+`, `=`, `++` etc: + token.type = 'operator'; + tokens.push( token ); + return; + } + if ( RE_PUNCTUATION.test( token.type.label ) ) { + // Punctuation symbols - `,`, `(`, `;` etc: + token.value = token.type.label; + token.type = 'punctuation'; + tokens.push( token ); + } + } + + /** + * Callback invoked upon encountering a `Comment` when parsing. + * + * @private + * @param {boolean} block - boolean indicating whether a comment is a block comment + * @param {string} text - comment value + * @param {number} start - start index + * @param {number} end - end index + */ + function onComment( block, text, start, end ) { + if ( block ) { + // TODO: add support for highlighting multi-line comments. + return; + } + tokens.push({ + 'type': 'comment', + 'start': start, + 'end': end + }); + } + + /** + * Resolves an `Identifier` node. + * + * @private + * @param {Object} node - AST node + * @returns {boolean} boolean indicating whether the `Identifier` was resolved + */ + function resolveIdentifier( node ) { + var identifier; + + // Ignore placeholder nodes: + if ( node.start >= node.end ) { + return true; + } + // Ignore node if it is an unrecognized `keyword`: + if ( isUnrecognizedKeyword( node.name ) || isUnrecognizedControlKeyword( node.name ) ) { // eslint-disable-line max-len + return true; + } + // If node is an unrecognized `literal`, push it as a token: + if ( isUnrecognizedReservedLiteral( node.name ) ) { + tokens.push({ + 'value': node.name, + 'type': 'literal', + 'start': node.start, + 'end': node.end + }); + return true; + } + // If identifier is defined in the local scope, assume and treat it like a `variable` and push it as a token... + if ( contains( resolveLocalScope( ast, node ), node.name ) ) { + tokens.push({ + 'value': node.name, + 'type': 'variable', + 'start': node.start, + 'end': node.end + }); + return true; + } + // If identifier is in global context, push it as a token... + identifier = context[ node.name ]; + if ( identifier ) { + if ( isLiteralType( typeof identifier ) ) { + tokens.push({ + 'value': node.name, + 'type': 'variable', + 'start': node.start, + 'end': node.end + }); + } else { + tokens.push({ + 'value': node.name, + 'type': typeof identifier, + 'start': node.start, + 'end': node.end + }); + } + return true; + } + return false; + } + + /** + * Resolves a `MemberExpression` node. + * + * @private + * @param {Object} node - AST node + * @param {boolean} compute - boolean indicating whether to compute the `MemberExpression` + * @returns {(void|*)} computed value of the `MemberExpression` if compute is true + */ + function resolveMemberExpression( node, compute ) { + var properties = linkedList(); + var property; + var computed; + var locals; + var obj; + + // Ignore placeholder nodes: + if ( node.start >= node.end ) { + return; + } + + // Resolve members of the `MemberExpression`: + resolveMembers( node ); + + // Check if the object identifier is valid... + property = properties.first(); + if ( !property ) { + return; + } + // Ignore if the object identifier is a reserved name: + if ( isReservedName( property.value.name ) ) { + return; + } + // If object identifier exists in the local scope, don't resolve from global scope... + locals = resolveLocalScope( ast, property.value ); + if ( contains( locals, property.value.name ) ) { + return; + } + // Enter object's namespace: + obj = context; + properties = properties.iterator(); + obj = obj[ properties.next().value.name ]; + if ( !obj ) { + // Object not defined in context: + return; + } + // Fetch properties from context: + property = properties.next(); + while ( !property.done ) { + // Ignore placeholder nodes: + if ( property.value.start >= property.value.end ) { + return; + } + // Case: 'bar' in `foo['bar']` - property already pushed as a string token. Ignore... + if ( property.value.type === 'Literal' ) { + try { + if ( !hasProp( obj, property.value.value ) ) { + // Property not found in context: + break; + } + obj = obj[ property.value.value ]; + } catch ( error ) { // eslint-disable-line no-unused-vars + break; + } + property = properties.next(); + continue; + } + // Case: `foo.bar` - resolve property and push it as a token... + if ( property.value.type === 'Identifier' ) { + try { + if ( !hasProp( obj, property.value.name ) ) { + // Property not found in context: + break; + } + obj = obj[ property.value.name ]; + } catch ( error ) { // eslint-disable-line no-unused-vars + break; + } + if ( !compute ) { + // Push token if property exists in context: + if ( isLiteralType( typeof obj ) ) { + tokens.push({ + 'value': property.value.name, + 'type': 'variable', + 'start': property.value.start, + 'end': property.value.end + }); + } else { + tokens.push({ + 'value': property.value.name, + 'type': typeof obj, + 'start': property.value.start, + 'end': property.value.end + }); + } + } + property = properties.next(); + continue; + } + // Case: `foo[a.b].bar` - recursively compute the internal `MemberExpression`... + if ( property.value.type === 'MemberExpression' ) { + computed = resolveMemberExpression( property.value, true ); + if ( !isLiteralType( typeof computed ) ) { + // Couldn't compute the internal `MemberExpression` into a definite name: + break; + } + try { + if ( !hasProp( obj, computed ) ) { + // Property not found in context: + break; + } + obj = obj[ computed ]; + } catch ( error ) { // eslint-disable-line no-unused-vars + break; + } + property = properties.next(); + continue; + } + break; + } + if ( compute ) { + return obj; + } + + /** + * Resolves members of the `MemberExpression` node. + * + * @private + * @param {Object} node - node to be traversed + */ + function resolveMembers( node ) { + if ( node.object.type === 'Identifier' ) { + // Reached a resolvable MemberExpression (a.b in a.b.c.d), save property(b) & object(a) and exit: + properties.unshift( node.property ); + properties.unshift( node.object ); + } else if ( node.object.type === 'MemberExpression' ) { + // Found node with another MemberExpression as object, save property and traverse it: + properties.unshift( node.property ); + resolveMembers( node.object ); + } + } + } + } +} + + +// EXPORTS // + +module.exports = tokenizer; diff --git a/lib/node_modules/@stdlib/repl/lib/update_regexp_cache.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/update_regexp_cache.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/update_regexp_cache.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/update_regexp_cache.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/lib/validate.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/validate.js new file mode 100644 index 000000000000..eb2322769182 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/lib/validate.js @@ -0,0 +1,111 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var isPlainObject = require( '@stdlib/assert/is-plain-object' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var isWritableStreamLike = require( '@stdlib/assert/is-node-writable-stream-like' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; +var isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ).isPrimitive; +var format = require( '@stdlib/string/format' ); + + +// MAIN // + +/** +* Validates function options. +* +* @private +* @param {Object} opts - destination object +* @param {Options} options - function options +* @param {WritableStream} [options.output] - output stream +* @param {WritableStream} [options.error] - error stream +* @param {boolean} [options.sandbox] - boolean indicating whether to run a REPL in a sandboxed context +* @param {PositiveInteger} [options.timeout] - number of milliseconds to execute a command before terminating execution +* @param {string} [options.save] - file path specifying where to save REPL command history +* @param {string} [options.log] - file path specifying where to save REPL commands and printed output +* @param {string} [options.quiet] - boolean indicating whether log information, confirmation messages, and other possible REPL diagnostics should be silenced +* @returns {(Error|null)} error or null +* +* @example +* var options = { +* 'sandbox': true +* }; +* var opts = {}; +* var err = validate( opts, options ); +* if ( err ) { +* throw err; +* } +*/ +function validate( opts, options ) { + if ( !isPlainObject( options ) ) { + return new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + if ( hasOwnProp( options, 'output' ) ) { + opts.output = options.output; + if ( !isWritableStreamLike( options.output ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a writable stream. Option: `%s`.', 'output', options.output ) ); + } + } + if ( hasOwnProp( options, 'error' ) ) { + opts.output = options.error; + if ( !isWritableStreamLike( options.error ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a writable stream. Option: `%s`.', 'error', options.error ) ); + } + } + if ( hasOwnProp( options, 'save' ) ) { + opts.save = options.save; + if ( !isString( options.save ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'save', options.save ) ); + } + } + if ( hasOwnProp( options, 'log' ) ) { + opts.log = options.log; + if ( !isString( options.log ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'log', options.log ) ); + } + } + if ( hasOwnProp( options, 'timeout' ) ) { + opts.timeout = options.timeout; + if ( !isPositiveInteger( options.timeout ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a positive integer. Option: `%s`.', 'timeout', options.timeout ) ); + } + } + if ( hasOwnProp( options, 'sandbox' ) ) { + opts.sandbox = options.sandbox; + if ( !isBoolean( options.sandbox ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'sandbox', options.sandbox ) ); + } + } + if ( hasOwnProp( options, 'quiet' ) ) { + opts.quiet = options.quiet; + if ( !isBoolean( options.quiet ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'quiet', options.quiet ) ); + } + } + return null; +} + + +// EXPORTS // + +module.exports = validate; diff --git a/lib/node_modules/@stdlib/repl/lib/workspace_alias_args.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/workspace_alias_args.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/workspace_alias_args.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/workspace_alias_args.js diff --git a/lib/node_modules/@stdlib/repl/lib/workspace_aliases.js b/lib/node_modules/@stdlib/repl/base/ctor/lib/workspace_aliases.js similarity index 100% rename from lib/node_modules/@stdlib/repl/lib/workspace_aliases.js rename to lib/node_modules/@stdlib/repl/base/ctor/lib/workspace_aliases.js diff --git a/lib/node_modules/@stdlib/repl/base/ctor/package.json b/lib/node_modules/@stdlib/repl/base/ctor/package.json new file mode 100644 index 000000000000..c38d7f25c47f --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/package.json @@ -0,0 +1,66 @@ +{ + "name": "@stdlib/repl/base/ctor", + "version": "0.0.0", + "description": "REPL environment.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "browser": { + "process": "process/" + }, + "directories": { + "benchmark": "./benchmark", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "repl", + "read-eval-print-loop", + "eval", + "evaluate", + "interact", + "interactive" + ], + "__stdlib__": { + "envs": { + "browser": false + } + } +} diff --git a/lib/node_modules/@stdlib/repl/base/ctor/test/test.js b/lib/node_modules/@stdlib/repl/base/ctor/test/test.js new file mode 100644 index 000000000000..f302074f6ef2 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/ctor/test/test.js @@ -0,0 +1,35 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var repl = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof repl, 'function', 'main export is a function' ); + t.end(); +}); + +// TODO: tests diff --git a/lib/node_modules/@stdlib/repl/base/examples/index.js b/lib/node_modules/@stdlib/repl/base/examples/index.js new file mode 100644 index 000000000000..f5349d26ce9b --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/examples/index.js @@ -0,0 +1,24 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var objectKeys = require( '@stdlib/utils/keys' ); +var ns = require( './../lib' ); + +console.log( objectKeys( ns ) ); diff --git a/lib/node_modules/@stdlib/repl/base/lib/index.js b/lib/node_modules/@stdlib/repl/base/lib/index.js new file mode 100644 index 000000000000..2cb987b48dd3 --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/lib/index.js @@ -0,0 +1,51 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/* +* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name. +*/ + +// MODULES // + +var setReadOnly = require( '@stdlib/utils/define-read-only-property' ); + + +// MAIN // + +/** +* Top-level namespace. +* +* @namespace ns +*/ +var ns = {}; + +/** +* @name REPL +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/repl/base/ctor} +*/ +setReadOnly( ns, 'REPL', require( '@stdlib/repl/base/ctor' ) ); + + +// EXPORTS // + +module.exports = ns; diff --git a/lib/node_modules/@stdlib/repl/base/package.json b/lib/node_modules/@stdlib/repl/base/package.json new file mode 100644 index 000000000000..7dcd583dd6ca --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/package.json @@ -0,0 +1,57 @@ +{ + "name": "@stdlib/repl/base", + "version": "0.0.0", + "description": "Base (i.e., lower-level) REPL functionality.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "repl", + "read-eval-print-loop", + "eval", + "evaluate", + "interact", + "interactive" + ] +} diff --git a/lib/node_modules/@stdlib/repl/base/test/test.js b/lib/node_modules/@stdlib/repl/base/test/test.js new file mode 100644 index 000000000000..ff0bea34c42b --- /dev/null +++ b/lib/node_modules/@stdlib/repl/base/test/test.js @@ -0,0 +1,40 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var objectKeys = require( '@stdlib/utils/keys' ); +var ns = require( './../lib' ); + + +// TESTS // + +tape( 'main export is an object', function test( t ) { + t.ok( true, __filename ); + t.equal( typeof ns, 'object', 'main export is an object' ); + t.end(); +}); + +tape( 'the exported object contains key-value pairs', function test( t ) { + var keys = objectKeys( ns ); + t.equal( keys.length > 0, true, 'has keys' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/repl/bin/cli b/lib/node_modules/@stdlib/repl/bin/cli index 2a0199695efc..ca58c9c807ff 100755 --- a/lib/node_modules/@stdlib/repl/bin/cli +++ b/lib/node_modules/@stdlib/repl/bin/cli @@ -37,7 +37,7 @@ var REPL = require( './../lib' ); */ function main() { var flags; - var repl; // eslint-disable-line no-unused-vars + var repl; var opts; var cli; @@ -86,7 +86,7 @@ function main() { } // Create a new REPL instance: - repl = new REPL( opts ); + repl = new REPL( opts ); // eslint-disable-line no-unused-vars } main(); diff --git a/lib/node_modules/@stdlib/repl/lib/commands/alias2pkg.js b/lib/node_modules/@stdlib/repl/lib/commands/alias2pkg.js index 31214a58df9e..a4709750053f 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/alias2pkg.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/alias2pkg.js @@ -24,7 +24,6 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var alias2pkg = require( '@stdlib/namespace/alias2pkg' ); -var indexOf = require( './../index_of.js' ); var alias2string = require( './../alias_to_string.js' ); @@ -48,29 +47,24 @@ function command( repl ) { * @returns {(string|void)} package name */ function onCommand( alias ) { - var aliases; var out; - var N; - var i; - - aliases = repl._aliases; - N = aliases.length; + var o; if ( isString( alias ) ) { out = alias2pkg( alias ); } // If provided an `alias` which is not a string or we failed to resolve a package name based on the provided string value, we try to resolve a string alias (and subsequently a corresponding package name) by searching the list of cached references of global variables/properties... if ( !out ) { - i = indexOf( N/2, aliases, 2, 1, alias ); - if ( i >= 0 ) { - out = alias2pkg( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias ); + if ( o !== void 0 ) { + out = alias2pkg( o ); } } // If we failed to resolve a package name and the provided value is an object, try finding a provided value's constructor (e.g., if provided a `Uint32Array`, try finding the package name for `Uint32Array`)... if ( !out && typeof alias === 'object' && alias !== null && alias.constructor ) { - i = indexOf( N/2, aliases, 2, 1, alias.constructor ); - if ( i >= 0 ) { - out = alias2pkg( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias.constructor ); + if ( o !== void 0 ) { + out = alias2pkg( o ); } } if ( out ) { diff --git a/lib/node_modules/@stdlib/repl/lib/commands/alias2related.js b/lib/node_modules/@stdlib/repl/lib/commands/alias2related.js index 5050935ac41d..c2e881698b2b 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/alias2related.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/alias2related.js @@ -24,7 +24,6 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var alias2related = require( '@stdlib/namespace/alias2related' ); -var indexOf = require( './../index_of.js' ); var alias2string = require( './../alias_to_string.js' ); @@ -49,13 +48,9 @@ function command( repl, cmds ) { * @returns {(StringArray|void)} related packages as a newline-delimited list */ function onCommand( alias ) { - var aliases; var out; - var N; var i; - - aliases = repl._aliases; - N = aliases.length; + var o; if ( isString( alias ) ) { out = alias2related( alias ); @@ -70,16 +65,16 @@ function command( repl, cmds ) { } // If provided an `alias` which is not a string or we failed to resolve related aliases based on the provided string value, we try to resolve a string alias (and subsequently related aliases) by searching the list of cached references of global variables/properties... if ( !out ) { - i = indexOf( N/2, aliases, 2, 1, alias ); - if ( i >= 0 ) { - out = alias2related( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias ); + if ( o !== void 0 ) { + out = alias2related( o ); } } // If we failed to resolve related aliases and the provided value is an object, try finding a provided value's constructor (e.g., if provided a `Uint32Array`, try finding related aliases for `Uint32Array`)... if ( !out && typeof alias === 'object' && alias !== null && alias.constructor ) { - i = indexOf( N/2, aliases, 2, 1, alias.constructor ); - if ( i >= 0 ) { - out = alias2related( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias.constructor ); + if ( o !== void 0 ) { + out = alias2related( o ); } } if ( out === void 0 || out === null ) { diff --git a/lib/node_modules/@stdlib/repl/lib/commands/ans.js b/lib/node_modules/@stdlib/repl/lib/commands/ans.js index 494cd9c67fc3..fb4c6ae989fc 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/ans.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/ans.js @@ -16,8 +16,6 @@ * limitations under the License. */ -/* eslint-disable no-underscore-dangle */ - 'use strict'; // MAIN // @@ -39,7 +37,7 @@ function command( repl ) { * @returns {*} result */ function onCommand() { - return repl._ans; + return repl.ans; } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/clear_vars.js b/lib/node_modules/@stdlib/repl/lib/commands/clear_vars.js index 144caac56065..441172a6c060 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/clear_vars.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/clear_vars.js @@ -16,8 +16,6 @@ * limitations under the License. */ -/* eslint-disable no-underscore-dangle */ - 'use strict'; // MAIN // @@ -47,7 +45,7 @@ function command( repl ) { } else { opts = {}; } - repl._context.clearWorkspace( repl._currentWorkspace, opts ); + repl.clearWorkspace( repl.currentWorkspace, opts ); } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/clear_workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/clear_workspace.js index c3187313bf80..20ae1fd4b8c3 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/clear_workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/clear_workspace.js @@ -25,13 +25,7 @@ var logger = require( 'debug' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var isPlainObject = require( '@stdlib/assert/is-plain-object' ); -var isArrayLike = require( '@stdlib/assert/is-array-like-object' ); -var isRegExp = require( '@stdlib/assert/is-regexp' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var propertyDescriptor = require( '@stdlib/utils/property-descriptor' ); -var defineProperty = require( '@stdlib/utils/define-property' ); var format = require( '@stdlib/string/format' ); -var contains = require( './../contains.js' ); var log = require( './../log.js' ); @@ -40,71 +34,6 @@ var log = require( './../log.js' ); var debug = logger( 'repl:command:clear_workspace' ); -// FUNCTIONS // - -/** -* Filters a variable list based on include and exclude filters. -* -* @private -* @param {Array} list - variable list to filter -* @param {(RegExp|ArrayLikeObject|void)} include - name inclusion filter -* @param {boolean} isArrInc - boolean indicating whether the inclusion filter is an array -* @param {(RegExp|ArrayLikeObject|void)} exclude - name exclusion filter -* @param {boolean} isArrExc - boolean indicating whether the exclusion filter is an array -* @returns {Array} input list -*/ -function filter( list, include, isArrInc, exclude, isArrExc ) { - var FLG; - var v; - var i; - var j; - - // Perform list "compression" without using temporary data structures... - j = 0; - for ( i = 0; i < list.length; i += 2 ) { - // Note: we can only delete "configurable" variables... - if ( list[ i+1 ].configurable === false ) { - // Variable is non-configurable and, hence, cannot be deleted... - continue; - } - v = list[ i ]; - FLG = false; - - // Note: exclude/include order matters!!! - if ( exclude ) { - if ( isArrExc ) { - if ( contains( exclude, v ) ) { - // The variable is in the explicit exclude list: - FLG = true; - } - } else if ( exclude.test( v ) ) { - // The variable passes the exclusion test: - FLG = true; - } - } - // Only apply inclusion filters if the variable has not been already excluded from deletion... - if ( FLG === false && include ) { - if ( isArrInc ) { - if ( !contains( include, v ) ) { - // The variable is *not* in the include list: - FLG = true; - } - } else if ( !include.test( v ) ) { - // The variable does *not* pass the include test: - FLG = true; - } - } - if ( FLG ) { - list[ j ] = list[ i ]; - list[ j+1 ] = list[ i+1 ]; - j += 2; - } - } - list.length = j; - return list; -} - - // MAIN // /** @@ -128,26 +57,20 @@ function command( repl ) { * @returns {void} */ function onCommand( name, options ) { - var isArrInc; - var isArrExc; var opts; - var list; - var desc; var err; - var tmp; var n; var d; - var i; if ( arguments.length === 0 ) { - n = repl._currentWorkspace; + n = repl.currentWorkspace; opts = {}; } else if ( arguments.length === 1 ) { if ( isString( name ) ) { n = name; opts = {}; } else if ( isPlainObject( name ) ) { - n = repl._currentWorkspace; + n = repl.currentWorkspace; opts = name; } else { err = new TypeError( format( 'invalid argument. Must provide either an options object or a workspace name. Value: `%s`.', name ) ); @@ -156,94 +79,17 @@ function command( repl ) { return; } } else { - if ( !isString( name ) ) { - err = new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } n = name; - if ( !isPlainObject( options ) ) { - err = new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', name ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } opts = options; } - if ( hasOwnProp( opts, 'include' ) ) { - isArrInc = isArrayLike( opts.include ); - if ( isArrInc === false && !isRegExp( opts.include ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'include', opts.include ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - } - if ( hasOwnProp( opts, 'exclude' ) ) { - isArrExc = isArrayLike( opts.exclude ); - if ( isArrExc === false && !isRegExp( opts.exclude ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'exclude', opts.include ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - } - if ( n === repl._currentWorkspace ) { - // Get the current variable list: - tmp = repl._context.varsWorkspace( n, {} ); - if ( tmp.length === 0 ) { - // No user-defined variables to delete... - log( repl, 'No user-defined variables to delete.' ); - debug( 'No user-defined variables to delete.' ); - return; - } - // Cache the variable names and their respective property descriptors: - list = []; - for ( i = 0; i < tmp.length; i++ ) { - list.push( tmp[ i ], propertyDescriptor( repl._context, tmp[i] ) ); // eslint-disable-line max-len - } - d = list.length / 2; - - // Filter the list of variables: - list = filter( list, opts.include, isArrInc, opts.exclude, isArrExc ); // eslint-disable-line max-len - - // Reset the REPL evaluation context (Why? Because we cannot simply delete variables as seen within the REPL environment. E.g., variables declared with `var` in the global scope are non-configurable, and, thus, cannot be deleted (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete). While we can delete a property/variable from the REPL context object here, this deletion does not get propagated to within the REPL environment; i.e., a user can still access the deleted property as a variable within the REPL environment. Hence, we need to adopt a cache, reset, and reassign approach, as done here.): - repl.resetContext(); // Note: in sandboxed environments, we assume a fresh context object is created! - - // Reassign the variables which were not deleted: - for ( i = 0; i < list.length; i += 2 ) { - desc = list[ i+1 ]; - if ( desc.configurable || repl._sandbox ) { - // If configurable, in non-sandboxed environments, we simply overwrite the existing descriptor; in sandboxed environments, we always need to redefine the variable with the appropriate property descriptor; if non-configurable, in non-sandboxed environments, we do not need to reassign/redefine, as the variable could not be deleted from the context object and thus already exists and cannot be reconfigured: - defineProperty( repl._context, list[ i ], desc ); - } - } - d -= list.length / 2; + try { + d = repl.clearWorkspace( n, opts ); log( repl, 'Deleted '+d+' variable(s).' ); debug( 'Deleted %d variable(s).', d ); - return; - } - if ( !hasOwnProp( repl._workspaces, n ) ) { - err = new Error( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', n ) ); + } catch ( err ) { debug( 'Error: %s', err.message ); repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - list = repl._workspaces[ n ]; - - // Case: clear all user-defined variables... - if ( opts.include === void 0 && opts.exclude === void 0 ) { - list.length = 0; - log( repl, 'Deleted '+d+' variable(s).' ); - debug( 'Deleted %d variable(s).', d ); - return; } - // Case: include/exclude filters: - list = filter( list, opts.include, isArrInc, opts.exclude, isArrExc ); - d -= list.length / 2; - log( repl, 'Deleted '+d+' variable(s).' ); - debug( 'Deleted %d variable(s).', d ); } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/current_workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/current_workspace.js index c10c16800875..92bf636bf4e2 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/current_workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/current_workspace.js @@ -16,8 +16,6 @@ * limitations under the License. */ -/* eslint-disable no-underscore-dangle */ - 'use strict'; // MAIN // @@ -39,7 +37,7 @@ function command( repl ) { * @returns {string} result */ function onCommand() { - return repl._currentWorkspace; + return repl.currentWorkspace; } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/delete_workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/delete_workspace.js index 279a852c0d7f..dbb1cdc03719 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/delete_workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/delete_workspace.js @@ -23,9 +23,6 @@ // MODULES // var logger = require( 'debug' ); -var isString = require( '@stdlib/assert/is-string' ).isPrimitive; -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var format = require( '@stdlib/string/format' ); var log = require( './../log.js' ); @@ -54,37 +51,20 @@ function command( repl ) { * @returns {void} */ function onCommand( name ) { - var err; var ws; if ( arguments.length ) { - if ( !isString( name ) ) { - err = new TypeError( format( 'invalid argument. Must provide a string. Value: `%s`.', name ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( !hasOwnProp( repl._workspaces, name ) ) { - err = new Error( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', name ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } ws = name; } else { - ws = repl._currentWorkspace; + ws = repl.currentWorkspace; } - if ( ws === 'base' ) { - err = new Error( 'invalid operation. Cannot delete the `base` workspace.' ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; + try { + repl.deleteWorkspace( ws ); + log( repl, 'Deleted \''+ws+'\' workspace.' ); + debug( 'Deleted \'%s\' workspace.', ws ); + } catch ( error ) { + debug( 'Error: %s', error.message ); + repl._ostream.write( 'Error: '+error.message+'\n' ); } - if ( ws === repl._currentWorkspace ) { - repl._context.workspace( 'base' ); - } - delete repl._workspaces[ ws ]; - log( repl, 'Deleted \''+ws+'\' workspace.' ); - debug( 'Deleted \'%s\' workspace.', ws ); } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/evalin.js b/lib/node_modules/@stdlib/repl/lib/commands/evalin.js index 2f17af820bad..4f33d8f31980 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/evalin.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/evalin.js @@ -22,19 +22,12 @@ // MODULES // -var vm = require( 'vm' ); var logger = require( 'debug' ); -var isString = require( '@stdlib/assert/is-string' ).isPrimitive; -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var format = require( '@stdlib/string/format' ); -var updateRegExpCache = require( './../update_regexp_cache.js' ); -var restoreRegExpMatches = require( './../restore_regexp_matches.js' ); // VARIABLES // var debug = logger( 'repl:command:evalin' ); -var RE_WHITESPACE = /^\s*$/; // MAIN // @@ -58,82 +51,13 @@ function command( repl ) { * @returns {void} */ function onCommand( workspace, expression ) { - var script; - var opts; - var err; - var FLG; - var ws; - if ( !isString( workspace ) ) { - err = new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', workspace ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( !isString( expression ) ) { - err = new TypeError( format( 'invalid argument. Second argument must be a string. Value: `%s`.', workspace ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( !hasOwnProp( repl._workspaces, workspace ) ) { - err = new Error( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', workspace ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( RE_WHITESPACE.test( expression ) ) { - debug( 'Expression only consists of whitespace. Nothing to evaluate.' ); - return; - } - // Cache the name of the current workspace: - ws = repl._currentWorkspace; - - // Temporarily silence logging: - FLG = repl._quiet; - repl._quiet = true; - - // Switch to the target workspace: - repl._context.workspace( workspace ); - - // Try evaluating the expression... - opts = { - 'filename': '', - 'lineOffset': 0 - }; - try { - // FIXME: this needs to follow the same logic as `process_line`, such as code wrapping, asynchronous execution, and handling top-level `await`!!! - script = new vm.Script( expression, opts ); - } catch ( error ) { - debug( 'Error: %s', error.message ); - repl._ostream.write( 'Error: '+error.message+'\n' ); - repl._context.workspace( ws ); - repl._quiet = FLG; - return; - } - // Set the (non-standard) properties on the `RegExp` expression object to the cached matches: - restoreRegExpMatches( repl._regexp ); - - opts = { - 'timeout': repl._timeout, - 'displayErrors': false, - 'breakOnSigint': true // Note: only applies for Node.js versions >=6.3.0 - }; - - // FIXME: we need to follow similar logic as `drain.js`, such as SIGINT handling!!! try { - script.runInContext( repl._context, opts ); + repl.evalin( workspace, expression ); repl._ostream.write( 'Successfully evaluated expression.\n' ); - } catch ( error ) { - debug( 'Error: %s', error.message ); - repl._ostream.write( 'Error: '+error.message+'\n' ); + } catch ( err ) { + debug( 'Error: %s', err.message ); + repl._ostream.write( 'Error: '+err.message+'\n' ); } - updateRegExpCache( repl._regexp ); - - // Return to the previous workspace: - repl._context.workspace( ws ); - - // Re-enable logging (if enabled): - repl._quiet = FLG; } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/example.js b/lib/node_modules/@stdlib/repl/lib/commands/example.js index 28307dfac132..2e20c3d837c7 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/example.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/example.js @@ -24,12 +24,9 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var isFunction = require( '@stdlib/assert/is-function' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var alias2example = require( '@stdlib/repl/code-blocks' ); var RE_EOL = require( '@stdlib/regexp/eol' ).REGEXP; var nextTick = require( '@stdlib/utils/next-tick' ); -var indexOf = require( './../index_of.js' ); -var findUniqueEntry = require( './../find_unique_entry.js' ); var alias2string = require( './../alias_to_string.js' ); var DOCS = require( './../repl_docs.js' ); @@ -55,16 +52,11 @@ function command( repl, cmds ) { * @returns {void} */ function onCommand( alias ) { - var aliases; - var entry; var lines; var out; var len; - var N; var i; - - aliases = repl._aliases; - N = aliases.length; + var o; if ( isString( alias ) ) { // Command docs supersede project namespace docs... @@ -74,8 +66,8 @@ function command( repl, cmds ) { } } if ( !out ) { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 0, alias ); // eslint-disable-line max-len - if ( i >= 0 ) { + o = repl.resolveContextVarByName( alias ); + if ( o !== void 0 ) { out = DOCS.example[ alias ]; } } @@ -94,43 +86,33 @@ function command( repl, cmds ) { } // Check if we were provided a reference to a global context variable... if ( !out ) { - // Address the fact that the `global` object is proxied (see https://github.com/nodejs/node/issues/855) - if ( - alias !== null && - typeof alias === 'object' && - hasOwnProp( alias, 'global' ) && - alias.global === alias - ) { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 1, repl._context.global ); // eslint-disable-line max-len - } else { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 1, alias ); // eslint-disable-line max-len - } - if ( i >= 0 ) { - out = DOCS.example[ repl._contextVars[ i-1 ] ]; + o = repl.resolveContextVarByRef( alias ); + if ( o !== void 0 ) { + out = DOCS.example[ o ]; } } // If provided an `alias` which is not a string or we failed to resolve an associated example based on the provided value, we try to resolve a string alias (and subsequently a corresponding example) by searching the list of cached references of global variables/properties... if ( !out ) { - i = indexOf( N/2, aliases, 2, 1, alias ); - if ( i >= 0 ) { - out = alias2example( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias ); + if ( o !== void 0 ) { + out = alias2example( o ); } } // TODO: add support for searching user documentation // If we failed to resolve an associated example and the provided value is an object, try finding a provided value's constructor (e.g., if provided a `Uint32Array`, try finding examples for `Uint32Array`)... if ( !out && typeof alias === 'object' && alias !== null && alias.constructor ) { - i = indexOf( N/2, aliases, 2, 1, alias.constructor ); - if ( i >= 0 ) { - out = alias2example( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias.constructor ); + if ( o !== void 0 ) { + out = alias2example( o ); } } // If we failed to resolve an associated example and the provided value is a function, try finding method examples... if ( !out && isFunction( alias ) ) { // Note: the following is an **expensive** look-up!! - entry = findUniqueEntry( N/2, aliases, 2, 1, alias ); - if ( entry ) { - out = alias2example( aliases[ entry[2]-1 ]+'.'+entry[ 1 ] ); + o = repl.resolveAliasByProp( alias ); + if ( o !== void 0 ) { + out = alias2example( o ); } } if ( out ) { @@ -162,7 +144,7 @@ function command( repl, cmds ) { lines.push( out[ i ] ); // If line is part of a multi-line input, wait for the next line... - if ( repl._multilineHandler.isMultilineInput( lines.join( '\n' ) ) ) { + if ( repl.isMultilineInput( lines.join( '\n' ) ) ) { return next(); } for ( j = 0; j < lines.length; j++ ) { diff --git a/lib/node_modules/@stdlib/repl/lib/commands/help.js b/lib/node_modules/@stdlib/repl/lib/commands/help.js index cf849a33b582..1cf9be9dfca6 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/help.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/help.js @@ -24,10 +24,8 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var isFunction = require( '@stdlib/assert/is-function' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var alias2help = require( '@stdlib/repl/help' ); var indexOf = require( './../index_of.js' ); -var findUniqueEntry = require( './../find_unique_entry.js' ); var alias2string = require( './../alias_to_string.js' ); var HELP_TEXT = require( './../help_text.js' ); var DOCS = require( './../repl_docs.js' ); @@ -54,17 +52,14 @@ function command( repl, cmds ) { * @returns {void} */ function onCommand( alias ) { - var aliases; - var entry; var out; - var N; var i; + var o; + if ( arguments.length === 0 ) { repl._ostream.write( HELP_TEXT ); return; } - aliases = repl._aliases; - N = aliases.length; if ( isString( alias ) ) { // Command docs supersede project namespace docs... @@ -74,8 +69,8 @@ function command( repl, cmds ) { } } if ( !out ) { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 0, alias ); // eslint-disable-line max-len - if ( i >= 0 ) { + o = repl.resolveContextVarByName( alias ); + if ( o !== void 0 ) { out = DOCS.help[ alias ]; } } @@ -100,26 +95,16 @@ function command( repl, cmds ) { } // Check if we were provided a reference to a global context variable... if ( !out ) { - // Address the fact that the `global` object is proxied (see https://github.com/nodejs/node/issues/855) - if ( - alias !== null && - typeof alias === 'object' && - hasOwnProp( alias, 'global' ) && - alias.global === alias - ) { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 1, repl._context.global ); // eslint-disable-line max-len - } else { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 1, alias ); // eslint-disable-line max-len - } - if ( i >= 0 ) { - out = DOCS.help[ repl._contextVars[ i-1 ] ]; + o = repl.resolveContextVarByRef( alias ); + if ( o !== void 0 ) { + out = DOCS.help[ o ]; } } // If provided an `alias` which is not a string or we failed to resolve a help text based on the provided string value, we try to resolve a string alias (and subsequently a corresponding help text) by searching the list of cached references of global variables/properties... if ( !out ) { - i = indexOf( N/2, aliases, 2, 1, alias ); - if ( i >= 0 ) { - out = alias2help( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias ); + if ( o !== void 0 ) { + out = alias2help( o ); } } // Try searching user-defined documentation for a matching object reference... @@ -131,17 +116,17 @@ function command( repl, cmds ) { } // If we failed to resolve help text and the provided value is an object, try finding a provided value's constructor (e.g., if provided a `Uint32Array`, try finding the documentation for `Uint32Array`)... if ( !out && typeof alias === 'object' && alias !== null && alias.constructor ) { - i = indexOf( N/2, aliases, 2, 1, alias.constructor ); - if ( i >= 0 ) { - out = alias2help( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias.constructor ); + if ( o !== void 0 ) { + out = alias2help( o ); } } // If we failed to resolve help text and the provided value is a function, try finding method documentation (note: we cannot perform a full inherited property search as prototype methods can be shared among multiple constructors, and, based on a reference alone, we cannot determine the appropriate document context; e.g., typed array methods all belong to an ancestor constructor `TypedArray` and we cannot tell, for example, whether a reference to `forEach` should return the documentation for `Uint32Array.prototype.forEach` or `Int32Array.prototype.forEach` or any of the other typed array constructors)... if ( !out && isFunction( alias ) ) { // Note: the following is an **expensive** look-up!! Why unique? In order to avoid document conflicts/"race conditions" between two or more context variables having own properties pointing to the same function reference (e.g., PRNGs having a `PRNG` property whose value is shared among multiple PRNGs; which `PRNG` property documentation do we return?). - entry = findUniqueEntry( N/2, aliases, 2, 1, alias ); - if ( entry ) { - out = alias2help( aliases[ entry[2]-1 ]+'.'+entry[ 1 ] ); + o = repl.resolveAliasByProp( alias ); + if ( o !== void 0 ) { + out = alias2help( o ); } } if ( out ) { diff --git a/lib/node_modules/@stdlib/repl/lib/commands/info.js b/lib/node_modules/@stdlib/repl/lib/commands/info.js index 73ba181bc982..768254f9484d 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/info.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/info.js @@ -24,10 +24,7 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var isFunction = require( '@stdlib/assert/is-function' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var alias2info = require( '@stdlib/repl/info' ); -var indexOf = require( './../index_of.js' ); -var findUniqueEntry = require( './../find_unique_entry.js' ); var alias2string = require( './../alias_to_string.js' ); var DOCS = require( './../repl_docs.js' ); @@ -53,14 +50,9 @@ function command( repl, cmds ) { * @returns {void} */ function onCommand( alias ) { - var aliases; - var entry; var out; - var N; var i; - - aliases = repl._aliases; - N = aliases.length; + var o; if ( isString( alias ) ) { // Command docs supersede project namespace docs... @@ -70,8 +62,8 @@ function command( repl, cmds ) { } } if ( !out ) { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 0, alias ); // eslint-disable-line max-len - if ( i >= 0 ) { + o = repl.resolveContextVarByName( alias ); + if ( o !== void 0 ) { out = DOCS.info[ alias ]; } } @@ -90,43 +82,33 @@ function command( repl, cmds ) { } // Check if we were provided a reference to a global context variable... if ( !out ) { - // Address the fact that the `global` object is proxied (see https://github.com/nodejs/node/issues/855) - if ( - alias !== null && - typeof alias === 'object' && - hasOwnProp( alias, 'global' ) && - alias.global === alias - ) { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 1, repl._context.global ); // eslint-disable-line max-len - } else { - i = indexOf( repl._contextVars.length, repl._contextVars, 2, 1, alias ); // eslint-disable-line max-len - } - if ( i >= 0 ) { - out = DOCS.info[ repl._contextVars[ i-1 ] ]; + o = repl.resolveContextVarByRef( alias ); + if ( o !== void 0 ) { + out = DOCS.info[ o ]; } } // If provided an `alias` which is not a string or we failed to resolve an abbreviated help text based on the provided string value, we try to resolve a string alias (and subsequently a corresponding abbreviated help text) by searching the list of cached references of global variables/properties... if ( !out ) { - i = indexOf( N/2, aliases, 2, 1, alias ); - if ( i >= 0 ) { - out = alias2info( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias ); + if ( o !== void 0 ) { + out = alias2info( o ); } } // TODO: add support for user-defined documentation // If we failed to resolve abbreviated help text and the provided value is an object, try finding a provided value's constructor (e.g., if provided a `Uint32Array`, try finding the documentation for `Uint32Array`)... if ( !out && typeof alias === 'object' && alias !== null && alias.constructor ) { - i = indexOf( N/2, aliases, 2, 1, alias.constructor ); - if ( i >= 0 ) { - out = alias2info( aliases[ i-1 ] ); + o = repl.resolveAliasByRef( alias.constructor ); + if ( o !== void 0 ) { + out = alias2info( o ); } } // If we failed to resolve abbreviated help text and the provided value is a function, try finding method abbreviated documentation... if ( !out && isFunction( alias ) ) { // Note: the following is an **expensive** look-up!! - entry = findUniqueEntry( N/2, aliases, 2, 1, alias ); - if ( entry ) { - out = alias2info( aliases[ entry[2]-1 ]+'.'+entry[ 1 ] ); + o = repl.resolveAliasByProp( alias ); + if ( o !== void 0 ) { + out = alias2info( o ); } } if ( out ) { diff --git a/lib/node_modules/@stdlib/repl/lib/commands/is_workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/is_workspace.js index b24993ea323b..57158e924245 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/is_workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/is_workspace.js @@ -25,8 +25,7 @@ var logger = require( 'debug' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var isRegExp = require( '@stdlib/assert/is-regexp' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var objectKeys = require( '@stdlib/utils/keys' ); +var contains = require( '@stdlib/array/base/assert/contains' ); var format = require( '@stdlib/string/format' ); @@ -55,8 +54,8 @@ function command( repl ) { * @returns {(boolean|void)} boolean indicating whether a workspace exists */ function onCommand( name ) { + var workspaces; var isStr; - var keys; var err; var i; @@ -67,12 +66,12 @@ function command( repl ) { repl._ostream.write( 'Error: '+err.message+'\n' ); return; } + workspaces = repl.workspaces(); if ( isStr ) { - return hasOwnProp( repl._workspaces, name ); + return contains( workspaces, name ); } - keys = objectKeys( repl._workspaces ); - for ( i = 0; i < keys.length; i++ ) { - if ( name.test( keys[ i ] ) ) { + for ( i = 0; i < workspaces.length; i++ ) { + if ( name.test( workspaces[ i ] ) ) { return true; } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/load_workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/load_workspace.js index d47965d7df48..acea75630997 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/load_workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/load_workspace.js @@ -23,15 +23,8 @@ // MODULES // var logger = require( 'debug' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; -var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; -var isPlainObject = require( '@stdlib/assert/is-plain-object' ); -var isArrayLike = require( '@stdlib/assert/is-array-like-object' ); -var isRegExp = require( '@stdlib/assert/is-regexp' ); -var defineProperty = require( '@stdlib/utils/define-property' ); var format = require( '@stdlib/string/format' ); -var contains = require( './../contains.js' ); var log = require( './../log.js' ); @@ -64,102 +57,32 @@ function command( repl ) { * @returns {void} */ function onCommand( name, options ) { - var isArrInc; - var isArrExc; var opts; var err; var cnt; - var ws; - var v; - var i; if ( !isString( name ) ) { err = new TypeError( format( 'invalid argument. First argument must be a string. Value: `%s`.', name ) ); debug( 'Error: %s', err.message ); repl._ostream.write( 'Error: '+err.message+'\n' ); return; } - opts = { - 'override': true - }; + opts = {}; if ( arguments.length > 1 ) { - if ( !isPlainObject( options ) ) { - err = new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', name ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( hasOwnProp( options, 'include' ) ) { - isArrInc = isArrayLike( options.include ); - if ( isArrInc === false && !isRegExp( options.include ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'include', options.include ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - opts.include = options.include; - } - if ( hasOwnProp( options, 'exclude' ) ) { - isArrExc = isArrayLike( options.exclude ); - if ( isArrExc === false && !isRegExp( options.exclude ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a regular expression or an array-like object. Option: `%s`.', 'exclude', options.exclude ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - opts.exclude = options.exclude; - } - if ( hasOwnProp( options, 'override' ) ) { - if ( !isBoolean( options.override ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'override', options.override ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - opts.override = options.override; - } + opts = options; } - if ( name === repl._currentWorkspace ) { + if ( name === repl.currentWorkspace ) { log( repl, 'Already in \''+name+'\' workspace.' ); debug( 'Already in \'%s\' workspace.', name ); return; } - if ( !hasOwnProp( repl._workspaces, name ) ) { - err = new Error( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', name ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - ws = repl._workspaces[ name ]; - - // Note: the internal branches are not the most performant implementation, but the implementation is straightforward and presumably "good enough"... - cnt = 0; - for ( i = 0; i < ws.length; i += 2 ) { - v = ws[ i ]; - if ( opts.include ) { - if ( isArrInc && !contains( opts.include, v ) ) { - continue; - } - if ( !opts.include.test( v ) ) { - continue; - } - } - if ( opts.exclude ) { - if ( isArrExc && contains( opts.exclude, v ) ) { - continue; - } - if ( opts.exclude.test( v ) ) { - continue; - } - } - if ( hasOwnProp( repl._context, v ) && opts.override === false ) { - continue; - } - // If we've made it this far, the variable should have passed all filters... - cnt += 1; - defineProperty( repl._context, v, ws[ i+1] ); + try { + cnt = repl.loadWorkspace( name, opts ); + log( repl, cnt.toString()+' variable(s) loaded from \''+name+'\' workspace.' ); + debug( '%d variable(s) loaded from \'%s\' workspace.', cnt, name ); + } catch ( error ) { + debug( 'Error: %s', error.message ); + repl._ostream.write( 'Error: '+error.message+'\n' ); } - log( repl, cnt.toString()+' variable(s) loaded from \''+name+'\' workspace.' ); - debug( '%d variable(s) loaded from \'%s\' workspace.', cnt, name ); } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/presentation_start.js b/lib/node_modules/@stdlib/repl/lib/commands/presentation_start.js index 949a23831efd..b4c9965f9eaa 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/presentation_start.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/presentation_start.js @@ -27,6 +27,7 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; var isPlainObject = require( '@stdlib/assert/is-plain-object' ); var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var contains = require( '@stdlib/array/base/assert/contains' ); var propertyDescriptor = require( '@stdlib/utils/property-descriptor' ); var properties = require( '@stdlib/utils/properties' ); var Presentation = require( '@stdlib/repl/presentation' ); // eslint-disable-line stdlib/no-redeclare @@ -63,7 +64,6 @@ function command( repl ) { */ function onCommand( text, options ) { var opts; - var FLG; var err; var ctx; var ws; @@ -135,15 +135,12 @@ function command( repl ) { ctx = repl._context; // Cache the current workspace name: - cs = repl._currentWorkspace; + cs = repl.currentWorkspace; // If the destination workspace already exists, we need to delete that workspace in order to allow presentation commands to be properly bound... - if ( ws !== 'base' && repl._context.isWorkspace( ws ) ) { + if ( ws !== 'base' && contains( repl.workspaces(), ws ) ) { debug( 'Deleting workspace: %s', ws ); - FLG = repl._quiet; - repl._quiet = true; // temporarily silence logging - repl._context.deleteWorkspace( ws ); - repl._quiet = FLG; + repl.deleteWorkspace( ws ); } // Create a new presentation... debug( 'Creating presentation...' ); diff --git a/lib/node_modules/@stdlib/repl/lib/commands/presentation_stop.js b/lib/node_modules/@stdlib/repl/lib/commands/presentation_stop.js index 3d2ce4937473..ad20a05c3aca 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/presentation_stop.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/presentation_stop.js @@ -57,7 +57,6 @@ function command( repl ) { function onCommand( id ) { var cache; var keys; - var FLG; var err; var key; var ws; @@ -74,7 +73,7 @@ function command( repl ) { } key = id; } else { - ws = repl._currentWorkspace; + ws = repl.currentWorkspace; keys = objectKeys( cache ); for ( i = 0; i < keys.length; i++ ) { if ( cache[ keys[ i ] ].w === ws ) { @@ -101,10 +100,7 @@ function command( repl ) { // Delete the presentation workspace... if ( o.w !== 'base' ) { debug( 'Deleting workspace: %s', o.w ); - FLG = repl._quiet; - repl._quiet = true; // temporarily silence logging - repl._context.deleteWorkspace( o.w ); - repl._quiet = FLG; + repl.deleteWorkspace( o.w ); } // Ensure that we no longer watch presentation files (if enabled): o.p.unwatch(); diff --git a/lib/node_modules/@stdlib/repl/lib/commands/rename_workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/rename_workspace.js index c1c699026127..37ecbc5a1ca2 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/rename_workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/rename_workspace.js @@ -24,7 +24,6 @@ var logger = require( 'debug' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var format = require( '@stdlib/string/format' ); var log = require( './../log.js' ); @@ -68,45 +67,26 @@ function command( repl ) { repl._ostream.write( 'Error: '+err.message+'\n' ); return; } - if ( !hasOwnProp( repl._workspaces, oldName ) ) { - err = new Error( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', oldName ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( oldName === newName ) { - log( repl, 'Workspace is already named \''+newName+'\'.' ); - return; + try { + repl.renameWorkspace( oldName, newName ); + } catch ( error ) { + debug( 'Error: %s', error.message ); + repl._ostream.write( 'Error: '+error.message+'\n' ); } - if ( hasOwnProp( repl._workspaces, newName ) ) { - err = new Error( format( 'invalid argument. Workspace name already exists. Value: `%s`.', newName ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( oldName === repl._currentWorkspace ) { + if ( oldName === repl.currentWorkspace ) { if ( oldName === 'base' ) { - repl._workspaces[ 'base' ].length = 0; log( repl, 'Created \''+newName+'\' workspace and cleared \'base\' workspace. Current workspace: \''+newName+'\'.' ); debug( 'Created \'%s\' workspace and cleared \'base\' workspace. Current workspace: \'%s\'.', newName, newName ); } else { - delete repl._workspaces[ oldName ]; log( repl, 'Renamed \''+oldName+'\' workspace to \''+newName+'\'. Current workspace: \''+newName+'\'.' ); debug( 'Renamed \'%s\' workspace to \'%s\'. Current workspace: \'%s\'.', oldName, newName, newName ); } - repl._workspaces[ newName ] = []; // "registers" the workspace - repl._currentWorkspace = newName; // bookkeeping - return; } if ( oldName === 'base' ) { - repl._workspaces[ newName ] = repl._workspaces[ 'base' ].slice(); - repl._workspaces[ 'base' ].length = 0; log( repl, 'Created \''+newName+'\' workspace and cleared \'base\' workspace.' ); debug( 'Created \'%s\' workspace and cleared \'base\' workspace.', newName ); return; } - repl._workspaces[ newName ] = repl._workspaces[ oldName ]; - delete repl._workspaces[ oldName ]; log( repl, 'Renamed \''+oldName+'\' workspace to \''+newName+'\'.' ); debug( 'Renamed \'%s\' workspace to \'%s\'.', oldName, newName ); } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/vars.js b/lib/node_modules/@stdlib/repl/lib/commands/vars.js index c16437c1baa8..0e7cabc2105b 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/vars.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/vars.js @@ -16,8 +16,6 @@ * limitations under the License. */ -/* eslint-disable no-underscore-dangle */ - 'use strict'; // MAIN // @@ -50,7 +48,7 @@ function command( repl ) { } else { opts = {}; } - return repl._context.varsWorkspace( repl._currentWorkspace, opts ); + return repl.varsWorkspace( repl.currentWorkspace, opts ); } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/vars_workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/vars_workspace.js index f806033ca051..e6e516ae3c22 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/vars_workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/vars_workspace.js @@ -24,17 +24,8 @@ var logger = require( 'debug' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; -var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; var isPlainObject = require( '@stdlib/assert/is-plain-object' ); -var isArrayLike = require( '@stdlib/assert/is-array-like-object' ); -var isRegExp = require( '@stdlib/assert/is-regexp' ); -var isReadableProperty = require( '@stdlib/assert/is-readable-property' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var properties = require( '@stdlib/utils/properties' ); -var typeOf = require( '@stdlib/utils/type-of' ); var format = require( '@stdlib/string/format' ); -var setdiff = require( './../setdiff.js' ); -var propertyComparator = require( './../property_comparator.js' ); // VARIABLES // @@ -68,21 +59,13 @@ function command( repl ) { */ function onCommand( name, options ) { var opts; - var list; - var type; var err; - var tmp; - var out; - var FLG; - var v; var n; - var i; - var j; if ( arguments.length === 0 ) { - return setdiff( repl._workspace, properties( repl._context ).sort( propertyComparator ) ); // eslint-disable-line max-len - } - if ( arguments.length === 1 ) { + n = repl.currentWorkspace; + opts = {}; + } else if ( arguments.length === 1 ) { if ( isString( name ) ) { n = name; opts = {}; @@ -110,101 +93,12 @@ function command( repl ) { } opts = options; } - if ( hasOwnProp( opts, 'include' ) && !isRegExp( opts.include ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a regular expression. Option: `%s`.', 'include', opts.include ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( hasOwnProp( opts, 'exclude' ) && !isRegExp( opts.exclude ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a regular expression. Option: `%s`.', 'exclude', opts.include ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( hasOwnProp( opts, 'types' ) && !isArrayLike( opts.types ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be an array-like object. Option: `%s`.', 'types', opts.types ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( hasOwnProp( opts, 'details' ) && !isBoolean( opts.details ) ) { - err = new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'details', opts.details ) ); + try { + return repl.varsWorkspace( n, opts ); + } catch ( err ) { debug( 'Error: %s', err.message ); repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - if ( n === void 0 || n === repl._currentWorkspace ) { - tmp = properties( repl._context ).sort( propertyComparator ); - tmp = setdiff( repl._workspace, tmp ); - list = []; - for ( i = 0; i < tmp.length; i++ ) { - if ( isReadableProperty( repl._context, tmp[ i ] ) ) { - list.push( tmp[ i ], repl._context[ tmp[ i ] ] ); - } else { - // The variable can be set, but not retrieved (i.e., is write-only), so value inspection is not possible without triggering an error... - list.push( tmp[ i ], void 0 ); - } - } - } else { - if ( !hasOwnProp( repl._workspaces, n ) ) { - err = new Error( format( 'invalid argument. Unrecognized workspace name. Value: `%s`.', n ) ); - debug( 'Error: %s', err.message ); - repl._ostream.write( 'Error: '+err.message+'\n' ); - return; - } - list = repl._workspaces[ n ].slice(); - for ( i = 1; i < list.length; i += 2 ) { - if ( typeof list[ i ].get === 'function' ) { - // WARNING: the `this` context is not defined, as the variable is not actually bound to a global instance! - list[ i ] = list[ i ].get.call( null ); - } else if ( typeof list[ i ].set === 'function' ) { - // The variable can be set, but not retrieved (i.e., is write-only), so value inspection is not possible without triggering an error... - list[ i ] = void 0; - } else { - list[ i ] = list[ i ].value; - } - } - } - out = []; - for ( i = 0; i < list.length; i += 2 ) { - v = list[ i ]; - FLG = false; - type = ''; - if ( opts.include && !opts.include.test( v ) ) { - continue; - } - if ( opts.exclude && opts.exclude.test( v ) ) { - continue; - } - if ( opts.types ) { - type = typeOf( list[ i+1 ] ); - for ( j = 0; j < opts.types.length; j++ ) { - if ( type === opts.types[ j ] ) { - FLG = true; - break; - } - } - if ( FLG === false ) { - continue; - } - } - // If we've made it this far, the variable should have passed all filters... - out.push( v ); - if ( opts.details ) { - j = out.length - 1; - out[ j ] = { - 'name': out[ j ], - 'type': type || typeOf( list[ i+1 ] ), - 'data': String( list[ i+1 ] ) // WARNING: for large datasets, this could be expensive!!! TODO: may want to consider alternative strategies for serialization based on a value's type. - }; - v = out[ j ].data; - if ( v.length > 20 ) { - out[ j ].data = v.slice( 0, 9 ) + '...' + v.slice( v.length-8 ); - } - } } - return out; } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/workspace.js b/lib/node_modules/@stdlib/repl/lib/commands/workspace.js index f2964a97a9c1..d49d7ac52249 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/workspace.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/workspace.js @@ -24,9 +24,6 @@ var logger = require( 'debug' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var propertyDescriptor = require( '@stdlib/utils/property-descriptor' ); -var defineProperty = require( '@stdlib/utils/define-property' ); var format = require( '@stdlib/string/format' ); var log = require( './../log.js' ); @@ -56,77 +53,29 @@ function command( repl ) { * @returns {void} */ function onCommand( name ) { - var vars; - var curr; - var desc; var err; - var ws; - var i; if ( !isString( name ) ) { err = new TypeError( format( 'invalid argument. Must provide a string. Value: `%s`.', name ) ); debug( 'Error: %s', err.message ); repl._ostream.write( 'Error: '+err.message+'\n' ); return; } - curr = repl._currentWorkspace; - if ( name === curr ) { + if ( name === repl.currentWorkspace ) { log( repl, 'Already in \''+name+'\' workspace.' ); debug( 'Already in \'%s\' workspace.', name ); return; } - // Cache and delete the current workspace variables... - vars = repl._context.varsWorkspace( curr ); - ws = repl._workspaces[ curr ]; - ws.length = 0; // reset - for ( i = 0; i < vars.length; i++ ) { - desc = propertyDescriptor( repl._context, vars[ i ] ); - ws.push( vars[ i ], desc ); - - // WARNING: in non-sandboxed environments, we run the risk of deleting global variables which were not introduced by the REPL environment... - if ( desc.configurable ) { - delete repl._context[ vars[ i ] ]; - } - } - // Reset the REPL evaluation context (Why? Because we cannot simply delete variables as seen within the REPL environment. E.g., variables declared with `var` in the global scope are non-configurable, and, thus, cannot be deleted (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete). Hence, while we can delete a property/variable here, this deletion does not get propagated to within the REPL environment; i.e., a user can still access the deleted property as a variable within the REPL environment.): - repl.resetContext(); - - // If the destination workspace already exists, load the workspace's variables... - if ( hasOwnProp( repl._workspaces, name ) ) { - ws = repl._workspaces[ name ]; - for ( i = 0; i < ws.length; i += 2 ) { - desc = propertyDescriptor( repl._context, ws[ i ] ); - - // If the variable does not already exist in the current evaluation context, define a new variable... - if ( desc === null ) { - defineProperty( repl._context, ws[ i ], ws[ i+1 ] ); - } - // If configurable, we can simply overwrite the existing property descriptor... - else if ( desc.configurable ) { - defineProperty( repl._context, ws[ i ], ws[ i+1 ] ); - } - // Otherwise, use direct assignment if the variable is writable... - else if ( hasOwnProp( desc, 'value' ) || hasOwnProp( desc, 'set' ) ) { - repl._context[ ws[ i ] ] = ws[ i+1 ]; - } - // Cannot assign to the variable as the variable is read-only... - else { - log( repl, 'Cannot load \''+ws[ i ]+'\' from \''+name+'\' workspace due to the presence of a non-configurable read-only variable of the same name.' ); - debug( 'Cannot load \'%s\' from \'%s\' workspace due to the presence of a non-configurable read-only variable of the same name.', ws[ i ], name ); - } - } - ws.length = 0; // free up memory and prevent holding on to old references + try { + repl.switchWorkspace( name ); log( repl, 'Switched to \''+name+'\' workspace.' ); debug( 'Switched to %s workspace.', name ); - } - // Otherwise, create a new workspace... - else { - repl._workspaces[ name ] = []; + } catch ( error ) { // eslint-disable-line no-unused-vars + // Workspace doesn't exist, create a new one: + repl.createWorkspace( name ); + repl.switchWorkspace( name ); log( repl, 'Created and switched to \''+name+'\' workspace.' ); debug( 'Created and switched to %s workspace.', name ); } - - // Update the current workspace variable: - repl._currentWorkspace = name; // bookkeeping } } diff --git a/lib/node_modules/@stdlib/repl/lib/commands/workspaces.js b/lib/node_modules/@stdlib/repl/lib/commands/workspaces.js index d4e39c858b5f..b51a44d4be6c 100644 --- a/lib/node_modules/@stdlib/repl/lib/commands/workspaces.js +++ b/lib/node_modules/@stdlib/repl/lib/commands/workspaces.js @@ -27,7 +27,6 @@ var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; var isPlainObject = require( '@stdlib/assert/is-plain-object' ); var isRegExp = require( '@stdlib/assert/is-regexp' ); var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var objectKeys = require( '@stdlib/utils/keys' ); var format = require( '@stdlib/string/format' ); @@ -65,7 +64,7 @@ function command( repl ) { var w; var i; if ( arguments.length === 0 ) { - return objectKeys( repl._workspaces ); + return repl.workspaces(); } if ( !isPlainObject( options ) ) { err = new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', name ) ); @@ -91,7 +90,7 @@ function command( repl ) { repl._ostream.write( 'Error: '+err.message+'\n' ); return; } - tmp = objectKeys( repl._workspaces ); + tmp = repl.workspaces(); out = []; for ( i = 0; i < tmp.length; i++ ) { w = tmp[ i ]; @@ -106,7 +105,7 @@ function command( repl ) { if ( options.details ) { out[ out.length-1 ] = { 'name': w, - 'variables': repl._context.varsWorkspace( w, { + 'variables': repl.varsWorkspace( w, { 'details': true }) }; diff --git a/lib/node_modules/@stdlib/repl/lib/complete_settings.js b/lib/node_modules/@stdlib/repl/lib/complete_settings.js deleted file mode 100644 index 93672a1f4da7..000000000000 --- a/lib/node_modules/@stdlib/repl/lib/complete_settings.js +++ /dev/null @@ -1,91 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2024 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -// MODULES // - -var logger = require( 'debug' ); -var parse = require( 'acorn-loose' ).parse; -var startsWith = require( '@stdlib/string/starts-with' ); -var settingsAliasArgs = require( './settings_alias_args.js' ); -var SETTINGS_NAMES = require( './settings_names.js' ); - - -// VARIABLES // - -var debug = logger( 'repl:completer:settings' ); -var AOPTS = { - 'ecmaVersion': 'latest' -}; - - -// MAIN // - -/** -* Completes a settings API expression. -* -* @private -* @param {Array} out - output array for storing completions -* @param {REPL} repl - REPL instance -* @param {string} expression - expression to complete -* @param {string} alias - settings API alias -* @param {string} value - value to complete -* @returns {string} value filter -*/ -function complete( out, repl, expression, alias, value ) { - var args; - var ast; - var arg; - var v; - var i; - - // Get the list of argument types for the desired API: - debug( 'Settings API: %s', alias ); - args = settingsAliasArgs( alias ); - - // Parse the expression into an AST: - debug( 'Expression: %s', expression ); - ast = parse( expression, AOPTS ); - - // Check whether the argument which triggered TAB completion has a corresponding argument type which is completable: - debug( 'Checking if argument is completable...' ); - arg = args[ ast.body[ 0 ].expression.arguments.length-1 ]; - if ( !arg ) { - debug( 'Argument which triggered TAB completion is not completable.' ); - return ''; - } - debug( 'Argument is completable.' ); - - debug( 'Searching for completion candidates...' ); - for ( i = 0; i < SETTINGS_NAMES.length; i++ ) { - v = SETTINGS_NAMES[ i ]; - if ( startsWith( v, value ) ) { - debug( 'Found a completion: %s', v ); - out.push( v ); - } else { - debug( '%s does not match filter %s. Skipping...', v, value ); - } - } - return value; -} - - -// EXPORTS // - -module.exports = complete; diff --git a/lib/node_modules/@stdlib/repl/lib/complete_tutorial.js b/lib/node_modules/@stdlib/repl/lib/complete_tutorial.js deleted file mode 100644 index d66e1be6ca39..000000000000 --- a/lib/node_modules/@stdlib/repl/lib/complete_tutorial.js +++ /dev/null @@ -1,93 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2019 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -// MODULES // - -var logger = require( 'debug' ); -var parse = require( 'acorn-loose' ).parse; -var startsWith = require( '@stdlib/string/starts-with' ); -var objectKeys = require( '@stdlib/utils/keys' ); -var tutorialAliasArgs = require( './tutorial_alias_args.js' ); -var TUTORIALS = require( './repl_docs.js' ).tutorial; - - -// VARIABLES // - -var debug = logger( 'repl:completer:tutorial' ); -var TUTS = objectKeys( TUTORIALS ); -var AOPTS = { - 'ecmaVersion': 'latest' -}; - - -// MAIN // - -/** -* Completes a tutorial API expression. -* -* @private -* @param {Array} out - output array for storing completions -* @param {REPL} repl - REPL instance -* @param {string} expression - expression to complete -* @param {string} alias - tutorial API alias -* @param {string} value - value to complete -* @returns {string} value filter -*/ -function complete( out, repl, expression, alias, value ) { - var args; - var ast; - var arg; - var t; - var i; - - // Get the list of argument types for the desired API: - debug( 'Tutorial API: %s', alias ); - args = tutorialAliasArgs( alias ); - - // Parse the expression into an AST: - debug( 'Expression: %s', expression ); - ast = parse( expression, AOPTS ); - - // Check whether the argument which triggered TAB completion has a corresponding argument type which is completable: - debug( 'Checking if argument is completable...' ); - arg = args[ ast.body[ 0 ].expression.arguments.length-1 ]; - if ( !arg ) { - debug( 'Argument which triggered TAB completion is not completable.' ); - return ''; - } - debug( 'Argument is completable.' ); - - debug( 'Searching for completion candidates...' ); - for ( i = 0; i < TUTS.length; i++ ) { - t = TUTS[ i ]; - if ( startsWith( t, value ) ) { - debug( 'Found a completion: %s', t ); - out.push( t ); - } else { - debug( '%s does not match filter %s. Skipping...', t, value ); - } - } - return value; -} - - -// EXPORTS // - -module.exports = complete; diff --git a/lib/node_modules/@stdlib/repl/lib/completer_engine.js b/lib/node_modules/@stdlib/repl/lib/completer_engine.js index a1ff5db541fe..d2f58a5f7ad8 100644 --- a/lib/node_modules/@stdlib/repl/lib/completer_engine.js +++ b/lib/node_modules/@stdlib/repl/lib/completer_engine.js @@ -69,14 +69,13 @@ function stripANSI( str ) { * @private * @constructor * @param {REPL} repl - REPL instance -* @param {Function} completer - function for generating possible completions * @param {WritableStream} ostream - writable stream * @param {Function} ttyWrite - function to trigger the default behavior of the keypress * @returns {CompleterEngine} completer engine instance */ -function CompleterEngine( repl, completer, ostream, ttyWrite ) { +function CompleterEngine( repl, ostream, ttyWrite ) { if ( !( this instanceof CompleterEngine ) ) { - return new CompleterEngine( repl, completer, ostream, ttyWrite ); + return new CompleterEngine( repl, ostream, ttyWrite ); } debug( 'Creating a completer engine...' ); @@ -89,9 +88,6 @@ function CompleterEngine( repl, completer, ostream, ttyWrite ) { // Cache a reference to the output writable stream: this._ostream = ostream; - // Cache a reference to the provided completer; - this._completer = completer; - // Cache a reference to the private readline interface `ttyWrite` to allow calling the method when wanting default behavior: this._ttyWrite = ttyWrite; @@ -682,7 +678,7 @@ setNonEnumerableReadOnly( CompleterEngine.prototype, 'beforeKeypress', function // Pause the input stream before generating completions as the completer may be asynchronous: this._rli.pause(); - this._completer( this._inputLine, this._onCompletions ); + this._repl.completer( this._inputLine, this._onCompletions ); }); /** @@ -733,7 +729,7 @@ setNonEnumerableReadOnly( CompleterEngine.prototype, 'onKeypress', function onKe // Pause the input stream before generating completions as the completer may be asynchronous... this._rli.pause(); - this._completer( this._inputLine, this._onCompletions ); + this._repl.completer( this._inputLine, this._onCompletions ); }); /** diff --git a/lib/node_modules/@stdlib/repl/lib/completer_preview.js b/lib/node_modules/@stdlib/repl/lib/completer_preview.js index 2eae0a89ac4e..e3d3f1fdd7bb 100644 --- a/lib/node_modules/@stdlib/repl/lib/completer_preview.js +++ b/lib/node_modules/@stdlib/repl/lib/completer_preview.js @@ -41,30 +41,30 @@ var debug = logger( 'repl:completer:preview' ); * * @private * @constructor +* @param {REPL} repl - REPL instance * @param {Object} rli - readline instance -* @param {Function} completer - function for generating possible completions * @param {WritableStream} ostream - writable stream * @param {boolean} enabled - boolean indicating whether the completer should be initially enabled * @returns {PreviewCompleter} completer instance */ -function PreviewCompleter( rli, completer, ostream, enabled ) { +function PreviewCompleter( repl, rli, ostream, enabled ) { if ( !(this instanceof PreviewCompleter) ) { - return new PreviewCompleter( rli, completer, ostream, enabled ); + return new PreviewCompleter( repl, rli, ostream, enabled ); } debug( 'Creating a preview completer...' ); // Initialize a flag indicating whether the preview completer is enabled: this._enabled = enabled; + // Cache a reference to the provided REPL instance: + this._repl = repl; + // Cache a reference to the provided readline interface: this._rli = rli; // Cache a reference to the output writable stream: this._ostream = ostream; - // Cache a reference to the provided completer: - this._completer = completer; - // Create a callback for processing potential completion previews: this._onCompletions = this._completionCallback(); @@ -232,7 +232,7 @@ setNonEnumerableReadOnly( PreviewCompleter.prototype, 'onKeypress', function onK return; } try { - this._completer( this._rli.line, this._onCompletions ); + this._repl.completer( this._rli.line, this._onCompletions ); } catch ( err ) { debug( 'Error: %s', err.message ); } diff --git a/lib/node_modules/@stdlib/repl/lib/display_prompt.js b/lib/node_modules/@stdlib/repl/lib/display_prompt.js index 344cede3bbf7..69bbb323d6e6 100644 --- a/lib/node_modules/@stdlib/repl/lib/display_prompt.js +++ b/lib/node_modules/@stdlib/repl/lib/display_prompt.js @@ -47,7 +47,7 @@ function displayPrompt( repl, preserveCursor ) { } len = repl._cmd.length; if ( len === 0 ) { - if ( repl._padding && repl._count >= 0 ) { + if ( repl._padding && repl.count >= 0 ) { repl._ostream.write( repeat( '\n', repl._padding ) ); } repl._rli.setPrompt( repl._prompt() ); diff --git a/lib/node_modules/@stdlib/repl/lib/eager_evaluator.js b/lib/node_modules/@stdlib/repl/lib/eager_evaluator.js index c8cd708df713..fdc84445387d 100644 --- a/lib/node_modules/@stdlib/repl/lib/eager_evaluator.js +++ b/lib/node_modules/@stdlib/repl/lib/eager_evaluator.js @@ -30,8 +30,6 @@ var replace = require( '@stdlib/string/replace' ); var setNonEnumerableReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); var copy = require( '@stdlib/array/base/copy' ); var max = require( '@stdlib/math/base/special/max' ); -var processCommand = require( './process_command.js' ); -var compileCommand = require( './compile_command.js' ); var ANSI_COLORS = require( './ansi_colors.js' ); @@ -301,23 +299,19 @@ setNonEnumerableReadOnly( EagerEvaluator.prototype, 'onKeypress', function onKey return; } debug( 'Processing command...' ); - tmp = processCommand( code ); + tmp = this._repl.processCommand( code ); if ( tmp instanceof Error ) { debug( 'Error encountered when processing command: %s', tmp.message ); return; } debug( 'Compiling command...' ); - executable = compileCommand( tmp ); + executable = this._repl.compileCommand( tmp ); if ( executable instanceof Error ) { debug( 'Error encountered when compiling command: %s', executable.message ); return; } try { - if ( this._repl._sandbox ) { - res = executable.compiled.runInContext( this._repl._context, ROPTS ); - } else { - res = executable.compiled.runInThisContext( ROPTS ); - } + res = this._repl.runCommand( executable, ROPTS ); } catch ( err ) { debug( 'Encountered an error when executing the command: %s', err.message ); return; @@ -329,7 +323,7 @@ setNonEnumerableReadOnly( EagerEvaluator.prototype, 'onKeypress', function onKey res = res.slice( 0, index ) + '...'; } cursorPosition = this._rli.cursor; - pre = replace( this._repl._outputPrompt, '%d', ( this._repl._count+1 ).toString() ); + pre = replace( this._repl._outputPrompt, '%d', ( this._repl.count+1 ).toString() ); this._repl._ostream.write( '\n' + ANSI_GRAY + pre + res + ANSI_RESET ); readline.moveCursor( this._repl._ostream, 0, -1 ); readline.cursorTo( this._repl._ostream, cursorPosition + this._repl.promptLength() ); diff --git a/lib/node_modules/@stdlib/repl/lib/log.js b/lib/node_modules/@stdlib/repl/lib/log.js index 1ae2f532f99b..21cbe25ce325 100644 --- a/lib/node_modules/@stdlib/repl/lib/log.js +++ b/lib/node_modules/@stdlib/repl/lib/log.js @@ -34,7 +34,7 @@ * @param {string} msg - message */ function log( repl, msg ) { - if ( repl._quiet === false ) { + if ( repl.quiet === false ) { repl._ostream.write( msg+'\n' ); } } diff --git a/lib/node_modules/@stdlib/repl/lib/main.js b/lib/node_modules/@stdlib/repl/lib/main.js index 8bb1b56fec8b..52e34b525d65 100644 --- a/lib/node_modules/@stdlib/repl/lib/main.js +++ b/lib/node_modules/@stdlib/repl/lib/main.js @@ -16,53 +16,43 @@ * limitations under the License. */ -/* eslint-disable no-restricted-syntax, no-invalid-this, no-underscore-dangle, max-lines, max-lines-per-function, max-statements */ +/* eslint-disable no-restricted-syntax, no-invalid-this, no-underscore-dangle, max-lines, max-lines-per-function */ 'use strict'; // MODULES // -var EventEmitter = require( 'events' ).EventEmitter; var readline = require( 'readline' ); -var proc = require( 'process' ); var resolve = require( 'path' ).resolve; +var proc = require( 'process' ); +var inspect = require( 'util' ).inspect; var logger = require( 'debug' ); var inherit = require( '@stdlib/utils/inherit' ); +var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' ); +var replace = require( '@stdlib/string/replace' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var isFunction = require( '@stdlib/assert/is-function' ); var isNumber = require( '@stdlib/assert/is-number' ).isPrimitive; var isPlainObject = require( '@stdlib/assert/is-plain-object' ); -var isFunction = require( '@stdlib/assert/is-function' ); -var isConfigurableProperty = require( '@stdlib/assert/is-configurable-property' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var objectKeys = require( '@stdlib/utils/keys' ); -var setNonEnumerable = require( '@stdlib/utils/define-nonenumerable-property' ); -var setNonEnumerableReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); -var setReadOnly = require( '@stdlib/utils/define-read-only-property' ); -var properties = require( '@stdlib/utils/properties' ); -var append = require( '@stdlib/utils/append' ); var format = require( '@stdlib/string/format' ); -var Boolean = require( '@stdlib/boolean/ctor' ); var cwd = require( '@stdlib/process/cwd' ); var readFileSync = require( '@stdlib/fs/read-file' ).sync; var RE_EOL = require( '@stdlib/regexp/eol' ).REGEXP; -var fifo = require( '@stdlib/dstructs/fifo' ); +var setNonEnumerable = require( '@stdlib/utils/define-nonenumerable-property' ); +var setNonEnumerableReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); var nextTick = require( '@stdlib/utils/next-tick' ); +var Boolean = require( '@stdlib/boolean/ctor' ); var assign = require( '@stdlib/object/assign' ); +var BaseREPL = require( '@stdlib/repl/base/ctor' ); var validate = require( './validate.js' ); var parseKey = require( './parse_key.js' ); var defaults = require( './defaults.js' ); var isSettingName = require( './is_setting_name.js' ); -var setAliases = require( './set_aliases.js' ); -var setAliasesGlobal = require( './set_aliases_global.js' ); -var setCommands = require( './set_commands.js' ); -var setCommandsGlobal = require( './set_commands_global.js' ); -var propertyComparator = require( './property_comparator.js' ); -var createEvalContext = require( './create_evaluation_context.js' ); var commands = require( './commands.js' ); var displayPrompt = require( './display_prompt.js' ); var inputPrompt = require( './input_prompt.js' ); var OutputStream = require( './output_stream.js' ); -var completerFactory = require( './completer.js' ); var MultilineHandler = require( './multiline_handler.js' ); var Keybindings = require( './keybindings.js' ); var EditorActions = require( './editor_actions.js' ); @@ -71,7 +61,6 @@ var PreviewCompleter = require( './completer_preview.js' ); var AutoCloser = require( './auto_close_pairs.js' ); var SyntaxHighlighter = require( './syntax_highlighter.js' ); var EagerEvaluator = require( './eager_evaluator.js' ); -var ALIAS_OVERRIDES = require( './alias_overrides.js' ); var SETTINGS = require( './settings.js' ); var SETTINGS_VALIDATORS = require( './settings_validators.js' ); @@ -111,8 +100,8 @@ var debug = logger( 'repl' ); * @param {boolean} [options.settings.completionPreviews] - boolean indicating whether to enable completion previews for auto-completion * @param {boolean} [options.settings.autoDisableBracketedPasteOnExit] - boolean indicating whether to automatically disable bracketed-paste upon exiting the REPL * @param {boolean} [options.settings.syntaxHighlighting] - boolean indicating whether to enable syntax highlighting -* @param {boolean} [options.settings.eagerEvaluation] - boolean indicating whether to enable eager evaluation * @param {string} [options.settings.theme] - initial color theme for syntax highlighting +* @param {boolean} [options.settings.eagerEvaluation] - boolean indicating whether to enable eager evaluation * @throws {Error} must provide valid options * @returns {REPL} REPL instance * @@ -182,15 +171,23 @@ function REPL( options ) { 'settings': opts.settings })); - // Call the parent constructor: - EventEmitter.call( this ); - // Create an internal output stream: ostream = new OutputStream( this, opts.settings.autoPage ); // Setup the output stream pipeline: ostream.pipe( opts.output ); + // Call the parent constructor: + BaseREPL.call( this, { + 'output': ostream, + 'error': ostream, + 'sandbox': opts.sandbox, + 'timeout': opts.timeout, + 'save': opts.save, + 'log': opts.log, + 'quiet': opts.quiet + }); + // Cache references to the input and output streams: setNonEnumerableReadOnly( this, '_istream', opts.input ); setNonEnumerableReadOnly( this, '_ostream', ostream ); @@ -200,11 +197,8 @@ function REPL( options ) { setNonEnumerableReadOnly( this, '_inputPrompt', opts.inputPrompt ); setNonEnumerableReadOnly( this, '_outputPrompt', opts.outputPrompt ); setNonEnumerableReadOnly( this, '_padding', opts.padding ); - setNonEnumerableReadOnly( this, '_timeout', opts.timeout ); setNonEnumerableReadOnly( this, '_isTTY', opts.isTTY ); - setNonEnumerableReadOnly( this, '_sandbox', opts.sandbox ); setNonEnumerableReadOnly( this, '_settings', opts.settings ); - setNonEnumerable( this, '_quiet', opts.quiet ); // allow this to be internally toggled // Initialize an internal data store: setNonEnumerableReadOnly( this, '_internal', {} ); @@ -212,68 +206,22 @@ function REPL( options ) { setNonEnumerableReadOnly( this._internal.presentation, 'cache', {} ); setNonEnumerable( this._internal.presentation, 'counter', 0 ); - // Initialize an internal command queue: - setNonEnumerableReadOnly( this, '_queue', fifo() ); - - // Initialize a strided internal buffer for storing the command history: - setNonEnumerableReadOnly( this, '_history', [] ); - // Initialize an internal buffer for storing the current command: setNonEnumerableReadOnly( this, '_cmd', [] ); - // Initialize a executed command counter: - setNonEnumerable( this, '_count', -1 ); - - // Initialize an internal buffer for saving regular expression matches between command evaluations: - setNonEnumerableReadOnly( this, '_regexp', [ '', '', '', '', '', '', '', '', '', '' ] ); - - // Initialize a strided internal cache of context globals: - setNonEnumerableReadOnly( this, '_contextVars', [] ); - - // For non-sandboxed REPLs, initialize an internal buffer for storing a (unique) sorted list of "built-in" REPL global variables/properties which need to be deleted upon closing a REPL in order to allow garbage collection and prevent memory leaks: - setNonEnumerableReadOnly( this, '_globalVars', ( this._sandbox ) ? null : [] ); - - // Initialize a strided internal cache of resolved global variables/properties in order to allow, e.g., help text look-up based on object reference, not just alias name (note: members alternate between `''` and ``): - setNonEnumerableReadOnly( this, '_aliases', [] ); + // Initialize a strided internal buffer for storing the command history: + setNonEnumerableReadOnly( this, '_history', [] ); // Initialize a strided internal buffer for storing user-defined documentation: setNonEnumerableReadOnly( this, '_userdocs', [] ); - // Initialize an internal buffer for storing a (unique) sorted list of workspace global variables/properties which were *initially* introduced during a REPL session (note: this overlaps with `_globalVars`, but more accurately represents a snapshot of the `global` state *before* a user begins entering commands, which is useful when wanting determine what variables/identifiers a user has introduced during a REPL session): - setNonEnumerableReadOnly( this, '_workspace', [] ); - - // Initialize a strided internal buffer for caching "base" workspace variables: - setNonEnumerableReadOnly( this, '_workspaces', {} ); - setReadOnly( this._workspaces, 'base', [] ); - - // Define the current workspace: - setNonEnumerable( this, '_currentWorkspace', 'base' ); - - // Initialize an internal flag indicating whether the REPL has been closed: - setNonEnumerable( this, '_closed', false ); - - // Initialize an internal flag indicating whether the REPL is currently busy with asynchronous processing: - setNonEnumerable( this, '_busy', false ); - // Initialize an internal flag indicating whether we've received a `SIGINT` signal: setNonEnumerable( this, '_SIGINT', false ); - // Initialize an internal variable for caching the result of the last successfully evaluated command: - setNonEnumerable( this, '_ans', void 0 ); - - // Initialize an internal variable for setting a command callback: - setNonEnumerable( this, '_done', void 0 ); - // Initialize internal variables for setting a keybinding: setNonEnumerable( this, '_isCapturingKeybinding', false ); setNonEnumerable( this, '_targetAction', '' ); - // Create a REPL execution context: - setNonEnumerable( this, '_context', this.createContext() ); - - // Create a new TAB completer: - setNonEnumerableReadOnly( this, '_completer', completerFactory( this ) ); - // Create an internal readline interface: debug( 'Creating readline interface...' ); setNonEnumerableReadOnly( this, '_rli', readline.createInterface({ @@ -293,13 +241,13 @@ function REPL( options ) { setNonEnumerableReadOnly( this, '_editorActions', new EditorActions( this, this._rli._ttyWrite ) ); // Create a new TAB completer engine: - setNonEnumerableReadOnly( this, '_completerEngine', new CompleterEngine( this, this._completer, this._wstream, this._rli._ttyWrite ) ); + setNonEnumerableReadOnly( this, '_completerEngine', new CompleterEngine( this, this._wstream, this._rli._ttyWrite ) ); // Create a new auto-closer: setNonEnumerableReadOnly( this, '_autoCloser', new AutoCloser( this._rli, this._settings.autoClosePairs, this._settings.autoDeletePairs, this._multilineHandler ) ); // Initialize a preview completer: - setNonEnumerableReadOnly( this, '_previewCompleter', new PreviewCompleter( this._rli, this._completer, this._ostream, this._settings.completionPreviews ) ); + setNonEnumerableReadOnly( this, '_previewCompleter', new PreviewCompleter( this, this._rli, this._ostream, this._settings.completionPreviews ) ); // Initialize a syntax-highlighter: setNonEnumerableReadOnly( this, '_syntaxHighlighter', new SyntaxHighlighter( this, this._ostream, this._settings.syntaxHighlighting ) ); @@ -354,7 +302,6 @@ function REPL( options ) { this.load( opts.load ); } else { displayPrompt( this, false ); - this._count += 1; } return this; @@ -433,7 +380,7 @@ function REPL( options ) { */ function onLine( line ) { self._SIGINT = false; // reset flag - if ( self._closed === false ) { + if ( self.closed === false ) { self._multilineHandler.processLine( line ); } } @@ -481,11 +428,9 @@ function REPL( options ) { debug( 'Received a SIGINT event.' ); - // If the REPL is currently busy executing a command, stop waiting for it to finish: - if ( self._busy ) { - self._done( new Error( 'unexpected error. Command execution terminated.' ) ); - return; - } + // Emit an interrupt: + self.emit( 'interrupt' ); + // Check whether the user has entered any characters: isEmpty = ( self._rli.line.length === 0 ); @@ -507,9 +452,6 @@ function REPL( options ) { } else { self._SIGINT = false; } - // Reset the command queue: - self._queue.clear(); - // Clear any command which has been buffered but not yet executed: self.clearCommand(); @@ -523,13 +465,31 @@ function REPL( options ) { * @private * @param {string} cmd - command * @param {boolean} success - boolean indicating whether the command successfully executed + * @param {*} res - result + * @param {boolean} silent - boolean indicating whether the command output should be silenced */ - function onCommand( cmd, success ) { - self._count += 1; - debug( 'Command count: %d', self._count ); + function onCommand( cmd, success, res, silent ) { + var pre; + var tmp; // Update the internal command history buffer: [..., , , , ...] - self._history.push( self._count, cmd, success ); + self._history.push( self.count, cmd, success ); + + if ( success === false ) { + self._ostream.write( 'Error: '+res.message+'\n' ); + } else if ( !silent && res !== void 0 ) { + pre = replace( self._outputPrompt, '%d', self.count.toString() ); + + if ( isndarrayLike( res ) ) { + tmp = res.toString(); // FIXME: this is a hack in order to avoid printing private ndarray properties in the REPL, as done by the built-in `util.inspect`. Ideally, we'd roll our own inspector which specifically accommodates stdlib's ndarray and other specialized classes. + } else { + tmp = res; + } + self._ostream.write( pre+inspect( tmp )+'\n' ); + } + if ( !self.closed ) { + displayPrompt( self, false ); + } // TODO: if successful and if necessary, (asynchronously?) write the command to a history file (question: do we only want to write successful commands to the history file? maybe we need to option for limiting to successful commands?) @@ -540,7 +500,7 @@ function REPL( options ) { /* * Inherit from the `EventEmitter` prototype. */ -inherit( REPL, EventEmitter ); +inherit( REPL, BaseREPL ); /** * Displays a command prompt. @@ -567,7 +527,7 @@ setNonEnumerableReadOnly( REPL.prototype, '_displayPrompt', function showPrompt( * @returns {string} command prompt */ setNonEnumerableReadOnly( REPL.prototype, '_prompt', function prompt() { - return inputPrompt( this._inputPrompt, this._count ); + return inputPrompt( this._inputPrompt, this.count ); }); /** @@ -729,178 +689,17 @@ setNonEnumerableReadOnly( REPL.prototype, 'createContext', function createContex var context; var cmds; - debug( 'Creating REPL execution context...' ); - - // Create an evaluation context: - context = createEvalContext( this._contextVars, this._ostream, this._sandbox ); // eslint-disable-line max-len - - // Add project APIs... - if ( this._sandbox ) { - setAliases( this._aliases, context, ALIAS_OVERRIDES ); - } else { - setAliasesGlobal( this._globalVars, this._aliases, context, ALIAS_OVERRIDES ); // eslint-disable-line max-len - } + // Initialize context object: + context = {}; // Get the list of REPL-specific commands: cmds = commands( this ); // Add commands requiring privileged access to internal instance variables... - if ( this._sandbox ) { - setCommands( context, cmds ); - } else { - setCommandsGlobal( this._globalVars, context, cmds ); - } - - // NOTE: the context should not be augmented **after** this point, except as done by the user when declaring variables and functions! - - // Sort the list of global variables: - if ( this._sandbox === false ) { - this._globalVars.sort( propertyComparator ); - } - // Capture a snapshot of the current global workspace: - append( this._workspace, properties( context ).sort( propertyComparator ) ); - - return context; -}); - -/** -* Resets a REPL's context. -* -* @name resetContext -* @memberof REPL.prototype -* @type {Function} -* @returns {REPL} REPL instance -* -* @example -* var debug = require( '@stdlib/streams/node/debug-sink' ); -* -* // Create a new REPL: -* var repl = new REPL({ -* 'output': debug() -* }); -* -* // ... -* -* // Reset the REPL context: -* repl.resetContext(); -* -* // ... -* -* // Close the REPL: -* repl.close(); -*/ -setNonEnumerableReadOnly( REPL.prototype, 'resetContext', function resetContext() { - var tmp; - var key; - var o; - var i; - var j; - - debug( 'Resetting REPL execution context...' ); - - // Before creating a new execution context in a non-sandboxed environment, remove current workspace variables in order to allow garbage collection and avoid memory leaks (e.g., variables/functions declared during a REPL session which might remain bound to the environment `global` after clearing a REPL): - if ( this._sandbox === false ) { - // WARNING: in a non-sandboxed environment, if a global variable is externally introduced during a REPL session (i.e., introduced via a mechanism outside of the REPL environment), we will delete that global variable, which means the following logic may introduce unintended side-effects for this particular edge case (e.g., application code may expect the presence of the subsequently deleted global variable). While not ideal, (a) user applications should not be introducing globals to begin with and (b) the probability of a user running a REPL session, a user clearing that REPL session, AND a global variable being introduced between starting a REPL and clearing the REPL should be negligible. - tmp = this._context.vars(); - for ( i = 0; i < tmp.length; i++ ) { - if ( isConfigurableProperty( this._context, tmp[ i ] ) ) { - delete this._context[ tmp[ i ] ]; - } - } - - // Remove REPL globals: - for ( i = 0; i < this._globalVars.length; i++ ) { - o = this._context; - key = this._globalVars[ i ].split( '.' ); // Note: this addresses nested key paths (e.g., `a.b.c`) - for ( j = 0; j < key.length-1; j++ ) { - if ( !hasOwnProp( o, key[ j ] ) ) { - o = null; - break; - } - o = o[ key[ j ] ]; - } - if ( o && isConfigurableProperty( o, key[ j ] ) ) { - delete o[ key[ j ] ]; - } - } - } - // Reset internal buffers for storing context data: - if ( this._sandbox === false ) { - this._globalVars.length = 0; - } - this._aliases.length = 0; - this._workspace.length = 0; - this._contextVars.length = 0; - - // Create a new execution context... - this._context = this.createContext(); - this.emit( 'reset', this._context ); // note: emitting the context allows REPL wrappers to extend the newly created context - - return this; -}); - -/** -* Clears a REPL's history. -* -* @name clearHistory -* @memberof REPL.prototype -* @type {Function} -* @returns {REPL} REPL instance -* -* @example -* var debug = require( '@stdlib/streams/node/debug-sink' ); -* -* // Create a new REPL: -* var repl = new REPL({ -* 'output': debug() -* }); -* -* // ... -* -* // Clear the REPL history: -* repl.clearHistory(); -* -* // ... -* -* // Close the REPL: -* repl.close(); -*/ -setNonEnumerableReadOnly( REPL.prototype, 'clearHistory', function clearHistory() { - debug( 'Resetting REPL history...' ); - this._history.length = 0; - return this; -}); + context = this.setCommands( context, cmds ); -/** -* Clears user-defined documentation. -* -* @name clearUserDocs -* @memberof REPL.prototype -* @type {Function} -* @returns {REPL} REPL instance -* -* @example -* var debug = require( '@stdlib/streams/node/debug-sink' ); -* -* // Create a new REPL: -* var repl = new REPL({ -* 'output': debug() -* }); -* -* // ... -* -* // Clear the user defined documentation: -* repl.clearUserDocs(); -* -* // ... -* -* // Close the REPL: -* repl.close(); -*/ -setNonEnumerableReadOnly( REPL.prototype, 'clearUserDocs', function clearUserDocs() { - debug( 'Resetting REPL user-defined documentation...' ); - this._userdocs.length = 0; - return this; + // Call the parent method: + return BaseREPL.prototype.createContext.call( this, context ); }); /** @@ -1209,7 +1008,7 @@ setNonEnumerableReadOnly( REPL.prototype, 'load', function load( fpath, clbk ) { var file; var len; var i; - if ( this._closed ) { + if ( this.closed ) { throw new Error( 'invalid operation. Cannot load a file into a REPL which has already closed.' ); } if ( !isString( fpath ) ) { @@ -1251,7 +1050,10 @@ setNonEnumerableReadOnly( REPL.prototype, 'load', function load( fpath, clbk ) { i += 1; if ( i < len ) { if ( file[ i ] ) { - self._rli.write( file[ i ]+'\n' ); + self._rli.write( file[ i ] ); + self._rli.write( '\n', { + 'name': 'return' + }); self.once( 'drain', next ); } else { nextTick( next ); @@ -1290,22 +1092,19 @@ setNonEnumerableReadOnly( REPL.prototype, 'load', function load( fpath, clbk ) { * repl.close(); */ setNonEnumerableReadOnly( REPL.prototype, 'reset', function onReset() { - if ( this._closed ) { + if ( this.closed ) { throw new Error( 'invalid operation. Cannot reset a REPL which has already closed.' ); } debug( 'Resetting REPL...' ); - // Reset the command queue: - this._queue.clear(); - - // Clear any command which has been buffered but not yet executed: - this.clearCommand(); + // Call the parent method: + BaseREPL.prototype.reset.call( this ); // Clear the command history: this.clearHistory(); - // Reset the execution context: - this.resetContext(); + // Clear any command which has been buffered but not yet executed: + this.clearCommand(); // Clear an output TTY stream of any previous commands and output: this.clear(); @@ -1316,6 +1115,62 @@ setNonEnumerableReadOnly( REPL.prototype, 'reset', function onReset() { return this; }); +/** +* Clears user-defined documentation. +* +* @name clearUserDocs +* @memberof REPL.prototype +* @type {Function} +* @returns {REPL} REPL instance +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Clear the user defined documentation: +* repl.clearUserDocs(); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'clearUserDocs', function clearUserDocs() { + debug( 'Resetting REPL user-defined documentation...' ); + this._userdocs.length = 0; + return this; +}); + +/** +* Clears a REPL's history. +* +* @name clearHistory +* @memberof REPL.prototype +* @type {Function} +* @returns {REPL} REPL instance +* +* @example +* // Create a new REPL: +* var repl = new REPL(); +* +* // ... +* +* // Clear the REPL history: +* repl.clearHistory(); +* +* // ... +* +* // Close the REPL: +* repl.close(); +*/ +setNonEnumerableReadOnly( REPL.prototype, 'clearHistory', function clearHistory() { + debug( 'Resetting REPL history...' ); + this._history.length = 0; + return this; +}); + /** * Clears the entire REPL screen and scrollback history. * @@ -1348,7 +1203,7 @@ setNonEnumerableReadOnly( REPL.prototype, 'reset', function onReset() { * repl.close(); */ setNonEnumerableReadOnly( REPL.prototype, 'clear', function onClear() { - if ( this._closed ) { + if ( this.closed ) { throw new Error( 'invalid operation. Cannot clear a REPL which has already closed.' ); } if ( this._isTTY ) { @@ -1399,7 +1254,7 @@ setNonEnumerableReadOnly( REPL.prototype, 'clear', function onClear() { * repl.close(); */ setNonEnumerableReadOnly( REPL.prototype, 'clearLine', function onClearLine() { - if ( this._closed ) { + if ( this.closed ) { throw new Error( 'invalid operation. Cannot clear the line of a REPL which has already closed.' ); } if ( this._isTTY ) { @@ -1436,7 +1291,7 @@ setNonEnumerableReadOnly( REPL.prototype, 'clearLine', function onClearLine() { * repl.close(); */ setNonEnumerableReadOnly( REPL.prototype, 'clearCommand', function onClearCommand() { - if ( this._closed ) { + if ( this.closed ) { throw new Error( 'invalid operation. Cannot clear the command buffer of a REPL which has already closed.' ); } // Clear any command which has been buffered but not yet executed: @@ -1467,67 +1322,17 @@ setNonEnumerableReadOnly( REPL.prototype, 'clearCommand', function onClearComman * repl.close(); */ setNonEnumerableReadOnly( REPL.prototype, 'close', function close() { - var self; - if ( this._closed ) { + if ( this.closed ) { debug( 'Attempted to close an already closed REPL.' ); return this; } - self = this; - this._closed = true; + debug( 'Closing readline interface...' ); + this._rli.close(); - // Clear the command queue: - this._queue.clear(); - - // TODO: ensure REPL history is saved (flushed) to file before closing the REPL (see https://github.com/nodejs/node/blob/b21e7c7bcf23a2715951e4cd96180e4dbf1dcd4d/lib/repl.js#L805) - - // TODO: ensure REPL log is saved (flushed) to file before closing the REPL - - nextTick( onTick ); + // Call the parent method: + BaseREPL.prototype.close.call( this ); return this; - - /** - * Callback invoked upon the next tick of the event loop. - * - * @private - */ - function onTick() { - var tmp; - var key; - var o; - var i; - var j; - - debug( 'Closing readline interface...' ); - self._rli.close(); - - // If this is a non-sandboxed REPL, remove global variables/properties which were introduced during context creation and by a user during a REPL session... - if ( self._sandbox === false ) { - // WARNING: in a non-sandboxed environment, if a global variable is externally introduced during a REPL session (i.e., introduced via a mechanism outside of the REPL environment), we will delete that global variable, which means the following logic may introduce unintended side-effects for this particular edge case (e.g., application code may expect the presence of the subsequently deleted global variable). While not ideal, (a) user applications should not be introducing globals to begin with and (b) the probability of a user running a REPL session, a user closing that REPL session, AND a global variable being introduced between starting a REPL and closing the REPL should be negligible. - tmp = self._context.vars(); // current workspace variables - for ( i = 0; i < tmp.length; i++ ) { - if ( isConfigurableProperty( self._context, tmp[ i ] ) ) { - delete self._context[ tmp[ i ] ]; - } - } - - // Remove REPL globals: - for ( i = 0; i < self._globalVars.length; i++ ) { - o = self._context; - key = self._globalVars[ i ].split( '.' ); // Note: this addresses nested key paths (e.g., `a.b.c`) - for ( j = 0; j < key.length-1; j++ ) { - if ( !hasOwnProp( o, key[ j ] ) ) { - o = null; - break; - } - o = o[ key[ j ] ]; - } - if ( o && isConfigurableProperty( o, key[ j ] ) ) { - delete o[ key[ j ] ]; - } - } - } - } }); /** @@ -1568,7 +1373,7 @@ setNonEnumerableReadOnly( REPL.prototype, 'settings', function settings() { var name; var f; - if ( this._closed ) { + if ( this.closed ) { throw new Error( 'invalid operation. Cannot access settings for a REPL which has already closed.' ); } nargs = arguments.length; diff --git a/lib/node_modules/@stdlib/repl/lib/multiline_handler.js b/lib/node_modules/@stdlib/repl/lib/multiline_handler.js index d78009de4959..5a1669f1303e 100644 --- a/lib/node_modules/@stdlib/repl/lib/multiline_handler.js +++ b/lib/node_modules/@stdlib/repl/lib/multiline_handler.js @@ -24,30 +24,17 @@ var readline = require( 'readline' ); var logger = require( 'debug' ); -var Parser = require( 'acorn' ).Parser; -var parseLoose = require( 'acorn-loose' ).parse; var setNonEnumerableReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); var startsWith = require( '@stdlib/string/starts-with' ); var copy = require( '@stdlib/array/base/copy' ); var min = require( '@stdlib/math/base/special/min' ); var max = require( '@stdlib/math/base/special/max' ); var displayPrompt = require( './display_prompt.js' ); -var drain = require( './drain.js' ); -var multilinePlugin = require( './acorn_detect_multiline_input.js' ); -var processCommand = require( './process_command.js' ); -var compileCommand = require( './compile_command.js' ); // VARIABLES // var debug = logger( 'repl:line' ); -var hasMultilineError = Parser.extend( multilinePlugin ).hasMultilineError; -var RE_WHITESPACE = /^\s*$/; -var RE_SINGLE_LINE_COMMENT = /^\s*\/\//; -var RE_MULTI_LINE_COMMENT = /^\s*\/\*.*\*\/$/; -var AOPTS = { - 'ecmaVersion': 'latest' -}; // MAIN // @@ -81,9 +68,6 @@ function MultilineHandler( repl, ttyWrite ) { // Cache a reference to the command array: this._cmd = repl._cmd; - // Cache a reference to the command queue: - this._queue = repl._queue; - // Initialize an internal object for command history: this._history = {}; this._history.list = repl._history; @@ -531,55 +515,6 @@ setNonEnumerableReadOnly( MultilineHandler.prototype, 'isPasting', function isPa return this._multiline.pasteMode; }); -/** -* Checks if the command is incomplete and a multi-line input. -* -* @name isMultilineInput -* @memberof MultilineHandler.prototype -* @type {Function} -* @param {string} cmd - command -* @returns {boolean} boolean indicating whether the command is a multi-line input -*/ -setNonEnumerableReadOnly( MultilineHandler.prototype, 'isMultilineInput', function isMultilineInput( cmd ) { - var node; - var tmp; - var ast; - - debug( 'Attempting to detect multi-line input...' ); - if ( RE_WHITESPACE.test( cmd ) ) { - debug( 'Multi-line input not detected.' ); - return false; - } - if ( RE_SINGLE_LINE_COMMENT.test( cmd ) || RE_MULTI_LINE_COMMENT.test( cmd ) ) { // eslint-disable-line max-len - debug( 'Multi-line input not detected.' ); - return false; - } - // Check if the command has valid syntax... - tmp = processCommand( cmd ); - if ( !( tmp instanceof Error ) ) { - debug( 'Multi-line input not detected.' ); - return false; - } - if ( hasMultilineError( cmd, AOPTS ) ) { - debug( 'Detected multi-line input. Triggering multi-line mode...' ); - return true; - } - // Still possible that a user is attempting to enter an object literal across multiple lines... - ast = parseLoose( cmd, AOPTS ); - - // Check for a trailing node which is being interpreted as a block statement, as this could be an object literal... - node = ast.body[ ast.body.length-1 ]; - if ( node.type === 'BlockStatement' && node.end === ast.end ) { - tmp = cmd.slice( node.start, node.end ); - if ( hasMultilineError( tmp, AOPTS ) ) { - debug( 'Detected multi-line input. Triggering multi-line mode...' ); - return true; - } - } - debug( 'Multi-line input not detected.' ); - return false; -}); - /** * Processes input line data. * @@ -590,9 +525,7 @@ setNonEnumerableReadOnly( MultilineHandler.prototype, 'isMultilineInput', functi * @returns {void} */ setNonEnumerableReadOnly( MultilineHandler.prototype, 'processLine', function processLine( line ) { - var code; var cmd; - var tmp; var dy; // Save line: @@ -622,34 +555,6 @@ setNonEnumerableReadOnly( MultilineHandler.prototype, 'processLine', function pr } this._multiline.active = false; // false until proven otherwise cmd = this._cmd.join( '\n' ); - if ( RE_WHITESPACE.test( cmd ) ) { - this.resetInput(); - displayPrompt( this._repl, false ); - return; - } - if ( RE_SINGLE_LINE_COMMENT.test( cmd ) || RE_MULTI_LINE_COMMENT.test( cmd ) ) { // eslint-disable-line max-len - debug( 'Detected single-line comment.' ); - tmp = cmd; - } else { - // Check if the command has valid syntax... - debug( 'Processing command...' ); - tmp = processCommand( cmd ); - if ( tmp instanceof Error ) { - // Move cursor to the output row: - dy = this._lines.length - this._lineIndex - 1; - readline.moveCursor( this._ostream, 0, dy ); - - // Reset the input buffers: - this.resetInput(); - - // Write error message and display next prompt: - this._ostream.write( 'Error: '+tmp.message+'\n' ); - this._repl.emit( 'command', cmd, false ); // command failed - displayPrompt( this._repl, false ); - return; - } - } - debug( 'Successfully processed command.' ); // Move cursor to the output row: dy = this._lines.length - this._lineIndex - 1; @@ -658,24 +563,8 @@ setNonEnumerableReadOnly( MultilineHandler.prototype, 'processLine', function pr // Reset the input buffers: this.resetInput(); - // Attempt to compile the command: - debug( 'Attempting to compile command...' ); - code = compileCommand( tmp ); - if ( code instanceof Error ) { - debug( 'Error: %s', code.message ); - this._ostream.write( 'Error: '+code.message+'\n' ); - this._repl.emit( 'command', cmd, false ); // command failed - displayPrompt( this._repl, false ); - return; - } - debug( 'Successfully compiled command.' ); - code.raw = cmd; - - // Add the command to the command queue: - this._queue.push( code ); - - // Request to run the command: - drain( this._repl ); + // Evaluate command: + this._repl.emit( 'input', cmd ); }); /** @@ -739,7 +628,7 @@ setNonEnumerableReadOnly( MultilineHandler.prototype, 'beforeKeypress', function this._lines[ this._lineIndex ] = this._rli.line; // If we are in paste mode or the command is incomplete, trigger multi-line mode... - if ( !this._multiline.pasteMode && !this.isMultilineInput( cmd.join( '\n' ) ) ) { + if ( !this._multiline.pasteMode && !this._repl.isMultilineInput( cmd.join( '\n' ) ) ) { this._ttyWrite.call( this._rli, data, key ); return; } diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_settings.js b/lib/node_modules/@stdlib/repl/lib/regexp_settings.js deleted file mode 100644 index 161d77940a1f..000000000000 --- a/lib/node_modules/@stdlib/repl/lib/regexp_settings.js +++ /dev/null @@ -1,106 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2024 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -// MODULES // - -var SETTINGS_ALIASES = require( './settings_aliases.js' ); - - -// MAIN // - -/** -* Returns a regular expression for matching settings APIs. -* -* ## Notes -* -* - Example output: -* -* ```text -* /\b(?:(settings)\s*\(\s*(.*,\s*)*(?:\[\s*(?:[^\]]*,\s*)*)?['"]([^'"]*))$/ -* ``` -* -* @private -* @returns {RegExp} regular expression -*/ -function createRegExp() { - var re; - var N; - var M; - var i; - - N = SETTINGS_ALIASES.length; - M = N - 1; - re = ''; - - // Match a word boundary: - re += '\\b'; - - // Create a capture group for detecting an alias with an incomplete invocation (e.g., `settings( 'foo`): - re += '(?:'; - - // Create a capture group for matching the alias... - re += '('; - for ( i = 0; i < N; i++ ) { - // Append the alias: - re += SETTINGS_ALIASES[ i ][ 0 ]; - - // Separate aliases with an OR separator: - if ( i < M ) { - re += '|'; - } - } - // Close the alias capture group: - re += ')'; - - // Match zero or more whitespace characters after the alias: - re += '\\s*'; - - // Match an opening parenthesis literal: - re += '\\('; - - // Match zero or more whitespace characters after the opening parenthesis: - re += '\\s*'; - - // Capture provided (comma-separated) arguments which precede the last argument: - re += '(.*,\\s*)*'; - - // Capture, but don't remember, an incomplete array argument (including all items except for the last) which occurs zero or one time: - re += '(?:\\[\\s*(?:[^\\]]*,\\s*)*)?'; - - // Match either a `'` or `"` literal: - re += '[\'"]'; - - // Capture the last (incomplete) argument (or array item): - re += '([^\'"]*)'; - - // Close the incomplete invocation capture group: - re += ')'; - - // Match the end of input (i.e., ensure that the match is an incomplete invocation): - re += '$'; - - // Return the regular expression: - return new RegExp( re ); -} - - -// EXPORTS // - -module.exports = createRegExp; diff --git a/lib/node_modules/@stdlib/repl/lib/regexp_tutorial.js b/lib/node_modules/@stdlib/repl/lib/regexp_tutorial.js deleted file mode 100644 index 280554a6fe25..000000000000 --- a/lib/node_modules/@stdlib/repl/lib/regexp_tutorial.js +++ /dev/null @@ -1,106 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2019 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -// MODULES // - -var TUTORIAL_ALIASES = require( './tutorial_aliases.js' ); - - -// MAIN // - -/** -* Returns a regular expression for matching tutorial APIs. -* -* ## Notes -* -* - Example output: -* -* ```text -* /\b(?:(tutorial)\s*\(\s*(.*,\s*)*(?:\[\s*(?:[^\]]*,\s*)*)?['"]([^'"]*))$/ -* ``` -* -* @private -* @returns {RegExp} regular expression -*/ -function createRegExp() { - var re; - var N; - var M; - var i; - - N = TUTORIAL_ALIASES.length; - M = N - 1; - re = ''; - - // Match a word boundary: - re += '\\b'; - - // Create a capture group for detecting an alias with an incomplete invocation (e.g., `tutorial( 'foo`): - re += '(?:'; - - // Create a capture group for matching the alias... - re += '('; - for ( i = 0; i < N; i++ ) { - // Append the alias: - re += TUTORIAL_ALIASES[ i ][ 0 ]; - - // Separate aliases with an OR separator: - if ( i < M ) { - re += '|'; - } - } - // Close the alias capture group: - re += ')'; - - // Match zero or more whitespace characters after the alias: - re += '\\s*'; - - // Match an opening parenthesis literal: - re += '\\('; - - // Match zero or more whitespace characters after the opening parenthesis: - re += '\\s*'; - - // Capture provided (comma-separated) arguments which precede the last argument: - re += '(.*,\\s*)*'; - - // Capture, but don't remember, an incomplete array argument (including all items except for the last) which occurs zero or one time: - re += '(?:\\[\\s*(?:[^\\]]*,\\s*)*)?'; - - // Match either a `'` or `"` literal: - re += '[\'"]'; - - // Capture the last (incomplete) argument (or array item): - re += '([^\'"]*)'; - - // Close the incomplete invocation capture group: - re += ')'; - - // Match the end of input (i.e., ensure that the match is an incomplete invocation): - re += '$'; - - // Return the regular expression: - return new RegExp( re ); -} - - -// EXPORTS // - -module.exports = createRegExp; diff --git a/lib/node_modules/@stdlib/repl/lib/settings.js b/lib/node_modules/@stdlib/repl/lib/settings.js index 429e21b3d1a5..91103b5891ee 100644 --- a/lib/node_modules/@stdlib/repl/lib/settings.js +++ b/lib/node_modules/@stdlib/repl/lib/settings.js @@ -56,13 +56,13 @@ var SETTINGS = { 'desc': 'Enable syntax highlighting.', 'type': 'boolean' }, - 'eagerEvaluation': { - 'desc': 'Enable eager evaluation.', - 'type': 'boolean' - }, 'theme': { 'desc': 'Set the syntax highlighting theme.', 'type': 'string' + }, + 'eagerEvaluation': { + 'desc': 'Enable eager evaluation.', + 'type': 'boolean' } }; diff --git a/lib/node_modules/@stdlib/repl/lib/settings_aliases.js b/lib/node_modules/@stdlib/repl/lib/settings_aliases.js deleted file mode 100644 index 7e27cf222120..000000000000 --- a/lib/node_modules/@stdlib/repl/lib/settings_aliases.js +++ /dev/null @@ -1,46 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2024 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -// MAIN // - -/* -* List of settings API aliases and corresponding argument completion compatibility. -* -* ## Notes -* -* - Each entry in the list has the following format: -* -* ``` -* [ , , ... ] -* ``` -* -* where `` is a settings API alias and `` is a `boolean` indicating whether an argument is compatible with settings name completion. -* -* - For the purposes of TAB completion, only those positional arguments which expect settings names need to be included. For example, if an API has three parameters and only the first argument expects a settings name, only that first argument needs to be included below; the remaining two arguments can be omitted, as those arguments are assumed to be incompatible with settings name completion. If an API has three parameters and only the second argument expects a settings name, only the first two arguments need to be included below, with the first argument documented as `null`; the remaining argument can be omitted. -*/ -var aliases = [ - // Note: keep in alphabetical order... - [ 'settings', true ] -]; - - -// EXPORTS // - -module.exports = aliases; diff --git a/lib/node_modules/@stdlib/repl/lib/syntax_highlighter.js b/lib/node_modules/@stdlib/repl/lib/syntax_highlighter.js index 0e09f00cb332..2855ef42eb3a 100644 --- a/lib/node_modules/@stdlib/repl/lib/syntax_highlighter.js +++ b/lib/node_modules/@stdlib/repl/lib/syntax_highlighter.js @@ -30,7 +30,6 @@ var isEmptyArray = require( '@stdlib/assert/is-empty-array' ); var objectKeys = require( '@stdlib/utils/keys' ); var omit = require( '@stdlib/utils/omit' ); var hasOwnProp = require( '@stdlib/assert/has-own-property' ); -var tokenizer = require( './tokenizer.js' ); var THEMES = require( './themes.js' ); var ANSI = require( './ansi_colors.js' ); @@ -329,7 +328,7 @@ setNonEnumerableReadOnly( SyntaxHighlighter.prototype, 'onKeypress', function on // Tokenize: debug( 'Line change detected. Tokenizing line: %s', this._rli.line ); this._line = this._rli.line; // update line buffer - tokens = tokenizer( this._line, this._repl._context ); + tokens = this._repl.tokenizer( this._line ); if ( isEmptyArray( tokens ) ) { debug( 'No tokens found. Skipping highlighting...' ); this._highlightedLine = this._line; diff --git a/lib/node_modules/@stdlib/repl/lib/themes.js b/lib/node_modules/@stdlib/repl/lib/themes.js index 63edd47db577..36a0bc4e47a4 100644 --- a/lib/node_modules/@stdlib/repl/lib/themes.js +++ b/lib/node_modules/@stdlib/repl/lib/themes.js @@ -41,7 +41,6 @@ var THEMES = { 'regexp': 'underline brightRed', // Identifiers: - 'command': 'bold magenta', 'function': 'bold yellow', 'object': 'cyan', 'variable': null, @@ -65,7 +64,6 @@ var THEMES = { 'regexp': 'bold red', // Identifiers: - 'command': 'brightGreen', 'function': 'bold magenta', 'object': 'cyan', 'variable': null, @@ -89,7 +87,6 @@ var THEMES = { 'regexp': 'underline red', // Identifiers: - 'command': 'brightMagenta', 'function': 'yellow', 'object': 'bold', 'variable': null, @@ -113,7 +110,6 @@ var THEMES = { 'regexp': 'underline red', // Identifiers: - 'command': 'underline brightBlue', 'function': 'bold yellow', 'object': 'italic cyan', 'variable': 'green', @@ -137,7 +133,6 @@ var THEMES = { 'regexp': 'bold underline', // Identifiers: - 'command': 'underline bold', 'function': 'italic bold', 'object': 'italic', 'variable': null, @@ -161,7 +156,6 @@ var THEMES = { 'regexp': 'red', // Identifiers: - 'command': 'bold magenta', 'function': 'brightBlue', 'object': 'brightRed', 'variable': 'brightBlue', @@ -185,7 +179,6 @@ var THEMES = { 'regexp': 'underline yellow', // Identifiers: - 'command': 'bold brightGreen', 'function': 'brightGreen', 'object': 'italic brightMagenta', 'variable': null, diff --git a/lib/node_modules/@stdlib/repl/lib/tokenizer.js b/lib/node_modules/@stdlib/repl/lib/tokenizer.js deleted file mode 100644 index fe0d9d8482b5..000000000000 --- a/lib/node_modules/@stdlib/repl/lib/tokenizer.js +++ /dev/null @@ -1,413 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2024 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -/* eslint-disable max-lines-per-function, id-length */ - -'use strict'; - -// MODULES // - -var parse = require( 'acorn-loose' ).parse; -var walk = require( 'acorn-walk' ); -var hasProp = require( '@stdlib/assert/has-property' ); -var linkedList = require( '@stdlib/dstructs/linked-list' ); -var contains = require( '@stdlib/array/base/assert/contains' ); -var resolveLocalScopes = require( './resolve_local_scopes.js' ); -var resolveLocalScope = require( './resolve_local_scope.js' ); -var commands = require( './commands.js' ); - - -// VARIABLES // - -var COMMANDS = commands(); -var isUnrecognizedKeyword = contains.factory( [ 'async', 'let' ] ); -var isControlKeyword = contains.factory( [ 'if', 'else', 'switch', 'case', 'catch', 'finally', 'try', 'return', 'break', 'continue' ] ); -var isUnrecognizedControlKeyword = contains.factory( [ 'await' ] ); -var isSpecialIdentifier = contains.factory( [ 'this', 'super' ] ); -var isReservedLiteral = contains.factory( [ 'null', 'true', 'false' ] ); -var isUnrecognizedReservedLiteral = contains.factory( [ 'undefined' ] ); -var isStringTokenType = contains.factory( [ 'string', 'template' ] ); -var isLiteralType = contains.factory( [ 'string', 'boolean', 'number' ] ); -var isReservedName = contains.factory( [ 'undefined', 'async', 'await', 'let' ] ); -var RE_PUNCTUATION = /(\{|\}|\[|\]|\(|\)|,|;|:|\.|\?|\?\.|=>|\.\.\.|`|\${)/; - - -// MAIN // - -/** -* Tokenizes the input line based on ECMAScript specification. -* -* @private -* @name tokenizer -* @type {Function} -* @param {string} line - input line -* @param {Object} context - REPL context -* @returns {Array} array of tokens -*/ -function tokenizer( line, context ) { - var declarations; - var VISITORS; - var tokens = []; - var ast; - var i; - - // Parse the given line into tokens & comments... - try { - ast = parse( line, { - 'ecmaVersion': 'latest', - 'onToken': onToken, - 'onComment': onComment - }); - } catch ( error ) { // eslint-disable-line no-unused-vars - return tokens; - } - - // Resolve variable declarations from the given line as tokens... - declarations = resolveLocalScopes( ast ); - for ( i = 0; i < declarations.length; i++ ) { - // If declaration cannot be resolved as an identifier, push it as a `name` token: - if ( !resolveIdentifier( declarations[ i ] ) ) { - tokens.push({ - 'value': declarations[ i ].name, - 'type': 'name', - 'start': declarations[ i ].start, - 'end': declarations[ i ].end - }); - } - } - - // Resolve identifiers from the given line as tokens... - VISITORS = { - 'Identifier': resolveIdentifier, - 'MemberExpression': resolveMemberExpression - }; - walk.simple( ast, VISITORS ); - - return tokens; - - /** - * Callback invoked upon encountering a `Token` when parsing. - * - * @private - * @param {Object} token - token object - */ - function onToken( token ) { - // Ignore placeholders & EOF tokens: - if ( token.start >= token.end ) { - return; - } - if ( token.type.isLoop || isControlKeyword( token.type.keyword ) || ( token.type.label === 'name' && isUnrecognizedControlKeyword( token.value ) ) ) { - // Control flow keywords - `for`, `while`, `do`, `if`, `else` etc: - token.type = 'control'; - tokens.push( token ); - return; - } - if ( isSpecialIdentifier( token.type.keyword ) ) { - // Special identifiers - `this`, `super`: - token.type = 'specialIdentifier'; - tokens.push( token ); - return; - } - if ( isReservedLiteral( token.type.keyword ) ) { - // Built-in literals - `true`, `false`, `null`, `undefined`: - token.type = 'literal'; - tokens.push( token ); - return; - } - if ( token.type.keyword || ( token.type.label === 'name' && isUnrecognizedKeyword( token.value ) ) ) { - // Keywords - `function`, `import`, `var`, `const`, `let` etc.: - token.type = 'keyword'; - tokens.push( token ); - return; - } - if ( isStringTokenType( token.type.label ) ) { - // Strings and template string literals: - token.type = 'string'; - tokens.push( token ); - return; - } - if ( token.type.label === 'regexp' ) { - // Regex expressions: - token.type = 'regexp'; - tokens.push( token ); - return; - } - if ( token.type.label === 'num' ) { - // Numeric literals: - token.type = 'number'; - tokens.push( token ); - return; - } - if ( token.type.binop || token.type.prefix || token.type.postfix || token.type.isAssign ) { // eslint-disable-line max-len - // Operator symbols - `+`, `=`, `++` etc: - token.type = 'operator'; - tokens.push( token ); - return; - } - if ( RE_PUNCTUATION.test( token.type.label ) ) { - // Punctuation symbols - `,`, `(`, `;` etc: - token.value = token.type.label; - token.type = 'punctuation'; - tokens.push( token ); - } - } - - /** - * Callback invoked upon encountering a `Comment` when parsing. - * - * @private - * @param {boolean} block - boolean indicating whether a comment is a block comment - * @param {string} text - comment value - * @param {number} start - start index - * @param {number} end - end index - */ - function onComment( block, text, start, end ) { - if ( block ) { - // TODO: add support for highlighting multi-line comments. - return; - } - tokens.push({ - 'type': 'comment', - 'start': start, - 'end': end - }); - } - - /** - * Resolves an `Identifier` node. - * - * @private - * @param {Object} node - AST node - * @returns {boolean} boolean indicating whether the `Identifier` was resolved - */ - function resolveIdentifier( node ) { - var identifier; - var command; - var i; - - // Ignore placeholder nodes: - if ( node.start >= node.end ) { - return true; - } - // Ignore node if it is an unrecognized `keyword`: - if ( isUnrecognizedKeyword( node.name ) || isUnrecognizedControlKeyword( node.name ) ) { // eslint-disable-line max-len - return true; - } - // If node is an unrecognized `literal`, push it as a token: - if ( isUnrecognizedReservedLiteral( node.name ) ) { - tokens.push({ - 'value': node.name, - 'type': 'literal', - 'start': node.start, - 'end': node.end - }); - return true; - } - // If identifier is defined in the local scope, assume and treat it like a `variable` and push it as a token... - if ( contains( resolveLocalScope( ast, node ), node.name ) ) { - tokens.push({ - 'value': node.name, - 'type': 'variable', - 'start': node.start, - 'end': node.end - }); - return true; - } - // If identifier is a REPL command, push it as a token... - for ( i = 0; i < COMMANDS.length; i++ ) { - command = COMMANDS[ i ]; - if ( node.name === command[ 0 ] ) { - tokens.push({ - 'value': node.name, - 'type': 'command', - 'start': node.start, - 'end': node.end - }); - return true; - } - } - // If identifier is in global context, push it as a token... - identifier = context[ node.name ]; - if ( identifier ) { - if ( isLiteralType( typeof identifier ) ) { - tokens.push({ - 'value': node.name, - 'type': 'variable', - 'start': node.start, - 'end': node.end - }); - } else { - tokens.push({ - 'value': node.name, - 'type': typeof identifier, - 'start': node.start, - 'end': node.end - }); - } - return true; - } - return false; - } - - /** - * Resolves a `MemberExpression` node. - * - * @private - * @param {Object} node - AST node - * @param {boolean} compute - boolean indicating whether to compute the `MemberExpression` - * @returns {(void|*)} computed value of the `MemberExpression` if compute is true - */ - function resolveMemberExpression( node, compute ) { - var properties = linkedList(); - var property; - var computed; - var locals; - var obj; - - // Ignore placeholder nodes: - if ( node.start >= node.end ) { - return; - } - - // Resolve members of the `MemberExpression`: - resolveMembers( node ); - - // Check if the object identifier is valid... - property = properties.first(); - if ( !property ) { - return; - } - // Ignore if the object identifier is a reserved name: - if ( isReservedName( property.value.name ) ) { - return; - } - // If object identifier exists in the local scope, don't resolve from global scope... - locals = resolveLocalScope( ast, property.value ); - if ( contains( locals, property.value.name ) ) { - return; - } - // Enter object's namespace: - obj = context; - properties = properties.iterator(); - obj = obj[ properties.next().value.name ]; - if ( !obj ) { - // Object not defined in context: - return; - } - // Fetch properties from context: - property = properties.next(); - while ( !property.done ) { - // Ignore placeholder nodes: - if ( property.value.start >= property.value.end ) { - return; - } - // Case: 'bar' in `foo['bar']` - property already pushed as a string token. Ignore... - if ( property.value.type === 'Literal' ) { - try { - if ( !hasProp( obj, property.value.value ) ) { - // Property not found in context: - break; - } - obj = obj[ property.value.value ]; - } catch ( error ) { // eslint-disable-line no-unused-vars - break; - } - property = properties.next(); - continue; - } - // Case: `foo.bar` - resolve property and push it as a token... - if ( property.value.type === 'Identifier' ) { - try { - if ( !hasProp( obj, property.value.name ) ) { - // Property not found in context: - break; - } - obj = obj[ property.value.name ]; - } catch ( error ) { // eslint-disable-line no-unused-vars - break; - } - if ( !compute ) { - // Push token if property exists in context: - if ( isLiteralType( typeof obj ) ) { - tokens.push({ - 'value': property.value.name, - 'type': 'variable', - 'start': property.value.start, - 'end': property.value.end - }); - } else { - tokens.push({ - 'value': property.value.name, - 'type': typeof obj, - 'start': property.value.start, - 'end': property.value.end - }); - } - } - property = properties.next(); - continue; - } - // Case: `foo[a.b].bar` - recursively compute the internal `MemberExpression`... - if ( property.value.type === 'MemberExpression' ) { - computed = resolveMemberExpression( property.value, true ); - if ( !isLiteralType( typeof computed ) ) { - // Couldn't compute the internal `MemberExpression` into a definite name: - break; - } - try { - if ( !hasProp( obj, computed ) ) { - // Property not found in context: - break; - } - obj = obj[ computed ]; - } catch ( error ) { // eslint-disable-line no-unused-vars - break; - } - property = properties.next(); - continue; - } - break; - } - if ( compute ) { - return obj; - } - - /** - * Resolves members of the `MemberExpression` node. - * - * @private - * @param {Object} node - node to be traversed - */ - function resolveMembers( node ) { - if ( node.object.type === 'Identifier' ) { - // Reached a resolvable MemberExpression (a.b in a.b.c.d), save property(b) & object(a) and exit: - properties.unshift( node.property ); - properties.unshift( node.object ); - } else if ( node.object.type === 'MemberExpression' ) { - // Found node with another MemberExpression as object, save property and traverse it: - properties.unshift( node.property ); - resolveMembers( node.object ); - } - } - } -} - - -// EXPORTS // - -module.exports = tokenizer; diff --git a/lib/node_modules/@stdlib/repl/lib/tutorial_aliases.js b/lib/node_modules/@stdlib/repl/lib/tutorial_aliases.js deleted file mode 100644 index 4ce3ee14a9f4..000000000000 --- a/lib/node_modules/@stdlib/repl/lib/tutorial_aliases.js +++ /dev/null @@ -1,46 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2019 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -// MAIN // - -/* -* List of tutorial API aliases and corresponding argument completion compatibility. -* -* ## Notes -* -* - Each entry in the list has the following format: -* -* ``` -* [ , , ... ] -* ``` -* -* where `` is a tutorial API alias and `` is a `boolean` indicating whether an argument is compatible with tutorial name completion. -* -* - For the purposes of TAB completion, only those positional arguments which expect tutorial names need to be included. For example, if an API has three parameters and only the first argument expects a tutorial name, only that first argument needs to be included below; the remaining two arguments can be omitted, as those arguments are assumed to be incompatible with tutorial name completion. If an API has three parameters and only the second argument expects a tutorial name, only the first two arguments need to be included below, with the first argument documented as `null`; the remaining argument can be omitted. -*/ -var aliases = [ - // Note: keep in alphabetical order... - [ 'tutorial', true ] -]; - - -// EXPORTS // - -module.exports = aliases; diff --git a/lib/node_modules/@stdlib/repl/lib/validate.js b/lib/node_modules/@stdlib/repl/lib/validate.js index c969ab72ccd2..f59b8a2cb8dc 100644 --- a/lib/node_modules/@stdlib/repl/lib/validate.js +++ b/lib/node_modules/@stdlib/repl/lib/validate.js @@ -43,7 +43,7 @@ var validateSettings = require( './validate_settings.js' ); * @param {Options} options - function options * @param {string} [options.inputPrompt] - input prompt * @param {string} [options.outputPrompt] - output prompt -* @param {ReadableStream} [options.input=] - input stream +* @param {ReadableStream} [options.input] - input stream * @param {WritableStream} [options.output] - output stream * @param {boolean} [options.sandbox] - boolean indicating whether to run a REPL in a sandboxed context * @param {PositiveInteger} [options.timeout] - number of milliseconds to execute a command before terminating execution diff --git a/lib/node_modules/@stdlib/repl/presentation/README.md b/lib/node_modules/@stdlib/repl/presentation/README.md index d89fb3627258..d27fc703d301 100644 --- a/lib/node_modules/@stdlib/repl/presentation/README.md +++ b/lib/node_modules/@stdlib/repl/presentation/README.md @@ -46,7 +46,7 @@ This package allows building presentations using only a [REPL][@stdlib/repl] env ### Authoring -A [REPL][@stdlib/repl] presentation source file is a text file which includes minimal markup for delineating slides, slide fragments, speaker notes, code, text alignment, and styling. +A [REPL][@stdlib/repl] presentation source file is a text file which includes minimal markup for delineating slides, slide fragments, speaker notes, code, text alignment, and styling. #### Slides diff --git a/lib/node_modules/@stdlib/repl/test/integration/test.auto_close_pairs.js b/lib/node_modules/@stdlib/repl/test/integration/test.auto_close_pairs.js index 67e6198e2c58..3e4222762350 100644 --- a/lib/node_modules/@stdlib/repl/test/integration/test.auto_close_pairs.js +++ b/lib/node_modules/@stdlib/repl/test/integration/test.auto_close_pairs.js @@ -147,7 +147,6 @@ function defaultSettings() { 'completionPreviews': false, 'syntaxHighlighting': false, 'eagerEvaluation': false - }; } diff --git a/lib/node_modules/@stdlib/repl/test/integration/test.auto_page.js b/lib/node_modules/@stdlib/repl/test/integration/test.auto_page.js index b2b9cf1fc4bc..66c70b020261 100644 --- a/lib/node_modules/@stdlib/repl/test/integration/test.auto_page.js +++ b/lib/node_modules/@stdlib/repl/test/integration/test.auto_page.js @@ -202,7 +202,7 @@ tape( 'a REPL instance avoids auto-paging short outputs', function test( t ) { } // Check if the output is printed without paging: expected = replace( FIXTURE, '\\n', '\n' ) + '\n'; - t.strictEqual( data[ data.length - 1 ], expected, 'returns expected value' ); + t.strictEqual( data[ data.length - 6 ], expected, 'returns expected value' ); t.end(); } diff --git a/lib/node_modules/@stdlib/repl/test/integration/test.completer_engine.js b/lib/node_modules/@stdlib/repl/test/integration/test.completer_engine.js index ffcc95ba8562..289ddb2fe99f 100644 --- a/lib/node_modules/@stdlib/repl/test/integration/test.completer_engine.js +++ b/lib/node_modules/@stdlib/repl/test/integration/test.completer_engine.js @@ -48,8 +48,8 @@ function defaultSettings() { 'autoDisableBracketedPasteOnExit': false, 'completionPreviews': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoPage': false + 'autoPage': false, + 'eagerEvaluation': false }; } diff --git a/lib/node_modules/@stdlib/repl/test/integration/test.completion_previews.js b/lib/node_modules/@stdlib/repl/test/integration/test.completion_previews.js index 6f572938b9a7..58dd382361f1 100644 --- a/lib/node_modules/@stdlib/repl/test/integration/test.completion_previews.js +++ b/lib/node_modules/@stdlib/repl/test/integration/test.completion_previews.js @@ -47,8 +47,8 @@ tape( 'a REPL instance supports displaying a completion preview of user-defined 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose ); @@ -93,8 +93,8 @@ tape( 'a REPL instance supports displaying a completion preview for common prefi 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose ); @@ -140,8 +140,8 @@ tape( 'a REPL instance supports displaying a completion preview for recognized i 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose ); @@ -186,8 +186,8 @@ tape( 'a REPL instance supports displaying a completion preview when a cursor is 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose ); @@ -241,8 +241,8 @@ tape( 'a REPL instance supports auto-completing a completion candidate by moving 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose ); @@ -295,8 +295,8 @@ tape( 'a REPL instance supports auto-completing a completion preview and executi 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose ); @@ -322,16 +322,16 @@ tape( 'a REPL instance supports auto-completing a completion preview and executi return; } // Check for an ANSI-escaped color-coded 'gh' completion: - t.strictEqual( data[ data.length-5 ], '\u001b[90mgh\u001b[0m', 'returns expected value' ); + t.strictEqual( data[ data.length-10 ], '\u001b[90mgh\u001b[0m', 'returns expected value' ); // Check that the cursor is positioned BEFORE the completion preview: - t.strictEqual( data[ data.length-4 ], '\u001b[2D', 'returns expected value' ); + t.strictEqual( data[ data.length-9 ], '\u001b[2D', 'returns expected value' ); // Check that the completion preview was auto-completed prior to execution: - t.strictEqual( data[ data.length-3 ], 'gh', 'returns expected value' ); + t.strictEqual( data[ data.length-8 ], 'gh', 'returns expected value' ); // Check that the expression was executed: - t.strictEqual( trim( data[ data.length-1 ] ), '1', 'returns expected value' ); + t.strictEqual( trim( data[ data.length-6 ] ), '1', 'returns expected value' ); t.end(); } @@ -350,8 +350,8 @@ tape( 'a REPL instance does not display a completion preview when no completion 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose ); @@ -410,8 +410,8 @@ tape( 'a REPL instance does not display a completion preview once a user enters 'settings': { 'autoPage': false, 'syntaxHighlighting': false, - 'eagerEvaluation': false, - 'autoDisableBracketedPasteOnExit': false + 'autoDisableBracketedPasteOnExit': false, + 'eagerEvaluation': false } }; r = repl( opts, onClose );