diff --git a/old_nushell/Cargo_old.lock b/old_nushell/Cargo_old.lock deleted file mode 100644 index 595c1f5a7..000000000 --- a/old_nushell/Cargo_old.lock +++ /dev/null @@ -1,5359 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.3", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "ansi_colours" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e2fb6138a49ad9f1cb3c6d8f8ccbdd5e62b4dab317c1b435a47ecd7da1d28f" -dependencies = [ - "cc", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "anyhow" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" - -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrow-format" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7da2d9660bfaebbdb0a44a33b3bd1dcb5a952fafa02c0dfc6a51ea471fef2a" -dependencies = [ - "flatbuffers", -] - -[[package]] -name = "arrow2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d873e2775c3d87a4e8d77aa544cbd43f34a0779d5164c59e7c6a1dd0678eb395" -dependencies = [ - "ahash", - "arrow-format", - "base64", - "chrono", - "csv", - "futures 0.3.18", - "hash_hasher", - "indexmap", - "lexical-core", - "multiversion", - "num-traits", - "parquet2", - "serde", - "serde_json", - "simdutf8", - "streaming-iterator", - "strength_reduce", -] - -[[package]] -name = "async-stream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" -dependencies = [ - "async-stream-impl", - "futures-core", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-trait" -version = "0.1.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "backtrace" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide 0.4.4", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "bat" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a069bad29696ecaa51ac79d3eb87abe3b65c7808ab2b3836afd9bd6c4009362" -dependencies = [ - "ansi_colours", - "ansi_term", - "bugreport", - "clircle", - "console", - "content_inspector", - "encoding", - "error-chain", - "git2", - "globset", - "grep-cli", - "path_abs", - "semver 0.11.0", - "serde", - "serde_yaml", - "shell-words", - "syntect", - "unicode-width", -] - -[[package]] -name = "bigdecimal" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744" -dependencies = [ - "num-bigint 0.4.3", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "bitpacking" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c7d2ac73c167c06af4a5f37e6e59d84148d57ccbe4480b76f0273eefea82d7" -dependencies = [ - "crunchy", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "brotli" -version = "3.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71cb90ade945043d3d53597b2fc359bb063db8ade2bcffe7997351d0756e9d50" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bson" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff58d466782b57e0001c8e97c6a70c01c2359d7e13e257a83654c0b783ecc139" -dependencies = [ - "ahash", - "base64", - "chrono", - "hex", - "indexmap", - "lazy_static", - "rand 0.8.4", - "serde", - "serde_bytes", - "serde_json", - "uuid", -] - -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - -[[package]] -name = "bugreport" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0014b4b2b4f63bfe69c3838470121290cc437fdc79785d408a761a21e8b2404c" -dependencies = [ - "git-version", - "shell-escape", - "sys-info", -] - -[[package]] -name = "bumpalo" -version = "3.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" - -[[package]] -name = "byte-unit" -version = "4.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ffc5b0ec7d7a6949e3f21fd63ba5af4cffdc2ba1e0b7bf62b481458c4ae7f" -dependencies = [ - "utf8-width", -] - -[[package]] -name = "bytemuck" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] - -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "bzip2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "calamine" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86ca78da4bdce5ac0f0bdbc0218ad14232f1e668376e044233f64c527cf5abb" -dependencies = [ - "byteorder", - "codepage", - "encoding_rs", - "log", - "quick-xml 0.19.0", - "serde", - "zip", -] - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - -[[package]] -name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "serde", - "time 0.1.44", - "winapi 0.3.9", -] - -[[package]] -name = "chrono-humanize" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eddc119501d583fd930cb92144e605f44e0252c38dd89d9247fffa1993375cb" -dependencies = [ - "chrono", -] - -[[package]] -name = "chrono-tz" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120" -dependencies = [ - "chrono", - "parse-zoneinfo", -] - -[[package]] -name = "clipboard-win" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8340083d28acb43451166543b98c838299b7e0863621be53a338adceea0ed" -dependencies = [ - "error-code", - "str-buf", - "winapi 0.3.9", -] - -[[package]] -name = "clircle" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68bbd985a63de680ab4d1ad77b6306611a8f961b282c8b5ab513e6de934e396" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "serde", - "winapi 0.3.9", -] - -[[package]] -name = "codepage" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0e9222c0cdf2c6ac27d73f664f9520266fa911c3106329d359f8861cb8bde9" -dependencies = [ - "encoding_rs", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "serde", - "termcolor", - "unicode-width", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "comfy-table" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a488ea8a8e295a53c7a4514b78a2e54bcff33adf99c15aced97b2a2062d4f8" -dependencies = [ - "crossterm", - "strum", - "strum_macros", -] - -[[package]] -name = "common-path" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" - -[[package]] -name = "console" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "regex", - "terminal_size", - "unicode-width", - "winapi 0.3.9", -] - -[[package]] -name = "const-sha1" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d" - -[[package]] -name = "content_inspector" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" -dependencies = [ - "memchr", -] - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "core-foundation" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "cpufeatures" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" -dependencies = [ - "cfg-if 1.0.0", - "lazy_static", -] - -[[package]] -name = "crossterm" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c" -dependencies = [ - "bitflags", - "crossterm_winapi", - "lazy_static", - "libc", - "mio", - "parking_lot", - "signal-hook", - "winapi 0.3.9", -] - -[[package]] -name = "crossterm_winapi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "cssparser" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "matches", - "phf", - "proc-macro2", - "quote", - "smallvec", - "syn", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "cstr_core" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ba9efe9e1e736671d5a03f006afc4e7e3f32503e2077e0bcaf519c0c8c1d3" -dependencies = [ - "cty", - "memchr", -] - -[[package]] -name = "csv" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" -dependencies = [ - "bstr", - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctrlc" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377c9b002a72a0b2c1a18c62e2f3864bdfea4a015e3683a96e24aa45dd6c02d1" -dependencies = [ - "nix", - "winapi 0.3.9", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - -[[package]] -name = "derive-new" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "directories-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "dtoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" - -[[package]] -name = "dtoa-short" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" -dependencies = [ - "dtoa", -] - -[[package]] -name = "dtparse" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13276c5dbd7f365e00efe6631242772fe6615e1899df84d1f6ce3ae7b48209f6" -dependencies = [ - "chrono", - "chrono-tz", - "lazy_static", - "num-traits", - "rust_decimal", -] - -[[package]] -name = "dunce" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541" - -[[package]] -name = "dyn-clone" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" - -[[package]] -name = "ego-tree" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "eml-parser" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031fe36712cec8b81c5b76b555666ce855a4dfc2dcc35bb907046bf2ef545578" -dependencies = [ - "regex", -] - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -dependencies = [ - "encoding-index-japanese", - "encoding-index-korean", - "encoding-index-simpchinese", - "encoding-index-singlebyte", - "encoding-index-tradchinese", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" - -[[package]] -name = "encoding_rs" -version = "0.8.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "version_check", -] - -[[package]] -name = "error-code" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff" -dependencies = [ - "libc", - "str-buf", -] - -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" - -[[package]] -name = "fd-lock" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc110fe50727d46a428eed832df40affe9bf74d077cac1bf3f2718e823f14c5" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "windows-sys", -] - -[[package]] -name = "filesize" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12d741e2415d4e2e5bd1c1d00409d1a8865a57892c2d689b504365655d237d43" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "flatbuffers" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4c5738bcd7fad10315029c50026f83c9da5e4a21f8ed66826f43e0e2bde5f6" -dependencies = [ - "bitflags", - "smallvec", - "thiserror", -] - -[[package]] -name = "flate2" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" -dependencies = [ - "cfg-if 1.0.0", - "crc32fast", - "libc", - "miniz_oxide 0.4.4", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" - -[[package]] -name = "futf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" -dependencies = [ - "mac", - "new_debug_unreachable", -] - -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - -[[package]] -name = "futures" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" - -[[package]] -name = "futures-executor" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" - -[[package]] -name = "futures-macro" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" - -[[package]] -name = "futures-task" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" - -[[package]] -name = "futures-util" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" -dependencies = [ - "futures 0.1.31", - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", - "tokio-io", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generic-array" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getset" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - -[[package]] -name = "git-version" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899" -dependencies = [ - "git-version-macro", - "proc-macro-hack", -] - -[[package]] -name = "git-version-macro" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "git2" -version = "0.13.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" -dependencies = [ - "bitflags", - "libc", - "libgit2-sys", - "log", - "url", -] - -[[package]] -name = "gjson" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4599d0e9dce476280e2da1f334811e2b26d63a6b000e13b7b50cc980bae49698" - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "globset" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log", - "regex", -] - -[[package]] -name = "grep-cli" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dd110c34bb4460d0de5062413b773e385cbf8a85a63fc535590110a09e79e8a" -dependencies = [ - "atty", - "bstr", - "globset", - "lazy_static", - "log", - "regex", - "same-file", - "termcolor", - "winapi-util", -] - -[[package]] -name = "h2" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" -dependencies = [ - "bytes 1.1.0", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hamcrest2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f837c62de05dc9cc71ff6486cd85de8856a330395ae338a04bfcefe5e91075" -dependencies = [ - "num 0.2.1", - "regex", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hash_hasher" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74721d007512d0cb3338cd20f0654ac913920061a4c4d0d8708edb3f2a698c0c" - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", - "rayon", -] - -[[package]] -name = "hashlink" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "heapless" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1ad878e07405df82b695089e63d278244344f80e764074d0bdfe99b89460f3" -dependencies = [ - "hash32", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "hmac-sha1" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1333fad8d94b82cab989da428b0b36a3435db3870d85e971a1d6dc0a8576722" -dependencies = [ - "sha1", -] - -[[package]] -name = "html5ever" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b" -dependencies = [ - "log", - "mac", - "markup5ever", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "htmlescape" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" - -[[package]] -name = "http" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" -dependencies = [ - "bytes 1.1.0", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" -dependencies = [ - "bytes 1.1.0", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - -[[package]] -name = "hyper" -version = "0.14.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" -dependencies = [ - "bytes 1.1.0", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes 1.1.0", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "ical" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9f7215ad0d77e69644570dee000c7678a47ba7441062c1b5f918adde0d73cf" -dependencies = [ - "thiserror", -] - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "image" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "jpeg-decoder", - "num-iter", - "num-rational 0.3.2", - "num-traits", - "png", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", - "serde", -] - -[[package]] -name = "insta" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15226a375927344c78d39dc6b49e2d5562a5b0705e26a589093c6792e52eed8e" -dependencies = [ - "console", - "lazy_static", - "serde", - "serde_json", - "serde_yaml", - "similar", - "uuid", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "integer-encoding" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90c11140ffea82edce8dcd74137ce9324ec24b3cf0175fc9d7e29164da9915b8" -dependencies = [ - "async-trait", - "futures-util", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "ipnet" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" - -[[package]] -name = "is_debug" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06d198e9919d9822d5f7083ba8530e04de87841eaf21ead9af8f2304efd57c89" - -[[package]] -name = "is_executable" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "itertools" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "jobserver" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" -dependencies = [ - "libc", -] - -[[package]] -name = "jpeg-decoder" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" - -[[package]] -name = "js-sys" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lexical" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34e981f88d060a67815388470172638f1af16b3a12e581cb75142f190161bf9" -dependencies = [ - "lexical-core", -] - -[[package]] -name = "lexical-core" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3926d8f156019890be4abe5fd3785e0cff1001e06f59c597641fd513a5a284" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d066d004fa762d9da995ed21aa8845bb9f6e4265f540d716fb4b315197bf0e" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c92badda8cc0fc4f3d3cc1c30aaefafb830510c8781ce4e8669881f3ed53ac" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff669ccaae16ee33af90dc51125755efed17f1309626ba5c12052512b11e291" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b5186948c7b297abaaa51560f2581dae625e5ce7dfc2d8fdc56345adb6dc576" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece956492e0e40fd95ef8658a34d53a3b8c2015762fdcaaff2167b28de1f56ef" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "libc" -version = "0.2.112" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" - -[[package]] -name = "libgit2-sys" -version = "0.12.26+1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" -dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" - -[[package]] -name = "libsqlite3-sys" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd5850c449b40bacb498b2bbdfaff648b1b055630073ba8db499caf2d0ea9f2" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "libz-sys" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "line-wrap" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" -dependencies = [ - "safemem", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" -dependencies = [ - "serde", - "serde_test", -] - -[[package]] -name = "lock_api" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "lz4" -version = "1.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac20ed6991e01bf6a2e68cc73df2b389707403662a8ba89f68511fb340f724c" -dependencies = [ - "libc", - "lz4-sys", -] - -[[package]] -name = "lz4-sys" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca79aa95d8b3226213ad454d328369853be3a1382d89532a854f4d69640acae" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "markup5ever" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" -dependencies = [ - "log", - "phf", - "phf_codegen", - "string_cache", - "string_cache_codegen", - "tendril", -] - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "md-5" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer", - "digest", - "opaque-debug", -] - -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "memmap2" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4647a11b578fead29cdbb34d4adef8dd3dc35b876c9c6d5240d83f205abfe96e" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" -dependencies = [ - "autocfg", -] - -[[package]] -name = "meval" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79496a5651c8d57cd033c5add8ca7ee4e3d5f7587a4777484640d9cb60392d9" -dependencies = [ - "fnv", - "nom", -] - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "mime_guess" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "miniz_oxide" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "mio" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi 0.3.9", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "mp4" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85660d4d88b9318d95396943adc4a254b3ed8bf1de917e6f093abda1ccf0bec0" -dependencies = [ - "byteorder", - "bytes 0.5.6", - "num-rational 0.3.2", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "multiversion" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025c962a3dd3cc5e0e520aa9c612201d127dcdf28616974961a649dca64f5373" -dependencies = [ - "multiversion-macros", -] - -[[package]] -name = "multiversion-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a3e2bde382ebf960c1f3e79689fa5941625fe9bf694a1cb64af3e85faff3af" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "native-tls" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "neso" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3c31defbcb081163db18437fd88c2a267cb3e26f7bd5e4b186e4b1b38fe8c8" -dependencies = [ - "bincode", - "cfg-if 0.1.10", - "log", - "serde", - "serde_derive", - "wasm-bindgen", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3bb9a13fa32bc5aeb64150cd3f32d6cf4c748f8f8a417cce5d2eb976a8370ba" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[package]] -name = "nom" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" - -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "nu" -version = "0.43.0" -dependencies = [ - "ctrlc", - "futures 0.3.18", - "hamcrest2", - "itertools", - "nu-cli", - "nu-command", - "nu-completion", - "nu-data", - "nu-engine", - "nu-errors", - "nu-parser", - "nu-path", - "nu-plugin", - "nu-protocol", - "nu-source", - "nu-test-support", - "nu-value-ext", - "nu_plugin_binaryview", - "nu_plugin_chart", - "nu_plugin_from_bson", - "nu_plugin_from_sqlite", - "nu_plugin_inc", - "nu_plugin_match", - "nu_plugin_query_json", - "nu_plugin_s3", - "nu_plugin_selector", - "nu_plugin_start", - "nu_plugin_textview", - "nu_plugin_to_bson", - "nu_plugin_to_sqlite", - "nu_plugin_tree", - "nu_plugin_xpath", - "rstest", - "serial_test", -] - -[[package]] -name = "nu-ansi-term" -version = "0.43.0" -dependencies = [ - "doc-comment", - "overload", - "regex", - "serde", - "serde_json", - "winapi 0.3.9", -] - -[[package]] -name = "nu-cli" -version = "0.43.0" -dependencies = [ - "ctrlc", - "indexmap", - "lazy_static", - "log", - "nu-ansi-term", - "nu-command", - "nu-completion", - "nu-data", - "nu-engine", - "nu-errors", - "nu-parser", - "nu-path", - "nu-protocol", - "nu-source", - "nu-stream", - "pretty_env_logger", - "rustyline", - "serde", - "serde_yaml", - "shadow-rs", - "strip-ansi-escapes", -] - -[[package]] -name = "nu-command" -version = "0.43.0" -dependencies = [ - "base64", - "bigdecimal", - "calamine", - "chrono", - "chrono-tz", - "crossterm", - "csv", - "ctrlc", - "derive-new", - "digest", - "dirs-next", - "dtparse", - "eml-parser", - "encoding_rs", - "filesize", - "futures 0.3.18", - "glob", - "hamcrest2", - "heck 0.4.0", - "htmlescape", - "ical", - "indexmap", - "itertools", - "lazy_static", - "log", - "md-5", - "meval", - "mime", - "nu-ansi-term", - "nu-data", - "nu-engine", - "nu-errors", - "nu-json", - "nu-parser", - "nu-path", - "nu-plugin", - "nu-pretty-hex", - "nu-protocol", - "nu-serde", - "nu-source", - "nu-stream", - "nu-table", - "nu-test-support", - "nu-value-ext", - "num-bigint 0.4.3", - "num-format", - "num-traits", - "parking_lot", - "polars", - "quick-xml 0.22.0", - "quickcheck", - "quickcheck_macros", - "rand 0.8.4", - "regex", - "reqwest", - "roxmltree", - "rust-embed", - "rustyline", - "serde", - "serde_ini", - "serde_json", - "serde_urlencoded", - "serde_yaml", - "sha2", - "shadow-rs", - "strip-ansi-escapes", - "sysinfo", - "term", - "term_size", - "thiserror", - "titlecase", - "tokio", - "toml", - "trash", - "umask", - "unicode-segmentation", - "url", - "users", - "uuid", - "which", - "zip", -] - -[[package]] -name = "nu-completion" -version = "0.43.0" -dependencies = [ - "indexmap", - "is_executable", - "nu-data", - "nu-engine", - "nu-parser", - "nu-path", - "nu-protocol", - "nu-source", - "nu-test-support", - "parking_lot", -] - -[[package]] -name = "nu-data" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "byte-unit", - "chrono", - "common-path", - "derive-new", - "directories-next", - "getset", - "indexmap", - "log", - "nu-ansi-term", - "nu-errors", - "nu-path", - "nu-protocol", - "nu-source", - "nu-table", - "nu-test-support", - "nu-value-ext", - "num-bigint 0.4.3", - "num-format", - "num-traits", - "serde", - "sha2", - "sys-locale", - "toml", -] - -[[package]] -name = "nu-engine" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "bytes 1.1.0", - "chrono", - "codespan-reporting", - "derive-new", - "dirs-next", - "encoding_rs", - "filesize", - "fs_extra", - "getset", - "glob", - "hamcrest2", - "indexmap", - "itertools", - "lazy_static", - "log", - "nu-ansi-term", - "nu-data", - "nu-errors", - "nu-parser", - "nu-path", - "nu-plugin", - "nu-protocol", - "nu-source", - "nu-stream", - "nu-test-support", - "nu-value-ext", - "num-bigint 0.4.3", - "parking_lot", - "rayon", - "serde", - "serde_json", - "tempfile", - "term_size", - "termcolor", - "trash", - "umask", - "users", - "which", -] - -[[package]] -name = "nu-errors" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "codespan-reporting", - "derive-new", - "getset", - "glob", - "nu-ansi-term", - "nu-source", - "num-bigint 0.4.3", - "num-traits", - "serde", - "serde_json", - "serde_yaml", - "toml", -] - -[[package]] -name = "nu-json" -version = "0.43.0" -dependencies = [ - "lazy_static", - "linked-hash-map", - "nu-path", - "nu-test-support", - "num-traits", - "regex", - "serde", - "serde_json", -] - -[[package]] -name = "nu-parser" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "derive-new", - "indexmap", - "itertools", - "log", - "nu-data", - "nu-errors", - "nu-path", - "nu-protocol", - "nu-source", - "nu-test-support", - "num-bigint 0.4.3", - "smart-default", -] - -[[package]] -name = "nu-path" -version = "0.43.0" -dependencies = [ - "dirs-next", - "dunce", -] - -[[package]] -name = "nu-plugin" -version = "0.43.0" -dependencies = [ - "indexmap", - "nu-errors", - "nu-protocol", - "nu-source", - "nu-test-support", - "nu-value-ext", - "serde", - "serde_json", -] - -[[package]] -name = "nu-pretty-hex" -version = "0.43.0" -dependencies = [ - "heapless", - "nu-ansi-term", - "rand 0.8.4", -] - -[[package]] -name = "nu-protocol" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "byte-unit", - "chrono", - "chrono-humanize", - "derive-new", - "getset", - "indexmap", - "log", - "nu-errors", - "nu-source", - "num-bigint 0.4.3", - "num-integer", - "num-traits", - "polars", - "serde", - "serde_bytes", -] - -[[package]] -name = "nu-serde" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "insta", - "nu-protocol", - "nu-source", - "serde", - "thiserror", -] - -[[package]] -name = "nu-source" -version = "0.43.0" -dependencies = [ - "derive-new", - "getset", - "pretty", - "serde", - "termcolor", -] - -[[package]] -name = "nu-stream" -version = "0.43.0" -dependencies = [ - "nu-errors", - "nu-protocol", - "nu-source", -] - -[[package]] -name = "nu-table" -version = "0.43.0" -dependencies = [ - "atty", - "nu-ansi-term", - "regex", - "strip-ansi-escapes", - "unicode-width", -] - -[[package]] -name = "nu-test-support" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "chrono", - "getset", - "glob", - "hamcrest2", - "indexmap", - "nu-errors", - "nu-path", - "nu-protocol", - "nu-source", - "num-bigint 0.4.3", - "tempfile", -] - -[[package]] -name = "nu-value-ext" -version = "0.43.0" -dependencies = [ - "indexmap", - "itertools", - "nu-errors", - "nu-protocol", - "nu-source", - "num-traits", -] - -[[package]] -name = "nu_plugin_binaryview" -version = "0.43.0" -dependencies = [ - "crossterm", - "image", - "neso", - "nu-ansi-term", - "nu-errors", - "nu-plugin", - "nu-pretty-hex", - "nu-protocol", - "nu-source", - "rawkey", -] - -[[package]] -name = "nu_plugin_chart" -version = "0.43.0" -dependencies = [ - "crossterm", - "nu-data", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "nu-value-ext", - "tui", -] - -[[package]] -name = "nu_plugin_from_bson" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "bson", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", -] - -[[package]] -name = "nu_plugin_from_mp4" -version = "0.43.0" -dependencies = [ - "mp4", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "tempfile", -] - -[[package]] -name = "nu_plugin_from_sqlite" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "rusqlite", - "tempfile", -] - -[[package]] -name = "nu_plugin_inc" -version = "0.43.0" -dependencies = [ - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "nu-test-support", - "nu-value-ext", - "semver 0.11.0", -] - -[[package]] -name = "nu_plugin_match" -version = "0.43.0" -dependencies = [ - "nu-errors", - "nu-plugin", - "nu-protocol", - "regex", -] - -[[package]] -name = "nu_plugin_query_json" -version = "0.43.0" -dependencies = [ - "gjson", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", -] - -[[package]] -name = "nu_plugin_s3" -version = "0.43.0" -dependencies = [ - "futures 0.3.18", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "s3handler", -] - -[[package]] -name = "nu_plugin_selector" -version = "0.43.0" -dependencies = [ - "indexmap", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "scraper", -] - -[[package]] -name = "nu_plugin_start" -version = "0.43.0" -dependencies = [ - "glob", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "open", - "url", - "webbrowser", -] - -[[package]] -name = "nu_plugin_textview" -version = "0.43.0" -dependencies = [ - "bat", - "nu-data", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "term_size", - "url", -] - -[[package]] -name = "nu_plugin_to_bson" -version = "0.43.0" -dependencies = [ - "bson", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "num-traits", -] - -[[package]] -name = "nu_plugin_to_sqlite" -version = "0.43.0" -dependencies = [ - "hex", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "rusqlite", - "tempfile", -] - -[[package]] -name = "nu_plugin_tree" -version = "0.43.0" -dependencies = [ - "derive-new", - "nu-errors", - "nu-plugin", - "nu-protocol", - "ptree", -] - -[[package]] -name = "nu_plugin_xpath" -version = "0.43.0" -dependencies = [ - "bigdecimal", - "indexmap", - "nu-errors", - "nu-plugin", - "nu-protocol", - "nu-source", - "nu-test-support", - "sxd-document", - "sxd-xpath", -] - -[[package]] -name = "num" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" -dependencies = [ - "num-bigint 0.2.6", - "num-complex 0.2.4", - "num-integer", - "num-iter", - "num-rational 0.2.4", - "num-traits", -] - -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint 0.4.3", - "num-complex 0.4.0", - "num-integer", - "num-iter", - "num-rational 0.4.0", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-complex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-format" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" -dependencies = [ - "arrayvec 0.4.12", - "itoa", - "num-bigint 0.2.6", -] - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-bigint 0.2.6", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg", - "num-bigint 0.3.3", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-rational" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" -dependencies = [ - "autocfg", - "num-bigint 0.4.3", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" - -[[package]] -name = "onig" -version = "6.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ddfe2c93bb389eea6e6d713306880c7f6dcc99a75b659ce145d962c861b225" -dependencies = [ - "bitflags", - "lazy_static", - "libc", - "onig_sys", -] - -[[package]] -name = "onig_sys" -version = "69.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd3eee045c84695b53b20255bb7317063df090b68e18bfac0abb6c39cf7f33e" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "open" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcea7a30d6b81a2423cc59c43554880feff7b57d12916f231a79f8d6d9470201" -dependencies = [ - "pathdiff", - "winapi 0.3.9", -] - -[[package]] -name = "openssl" -version = "0.10.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "foreign-types", - "libc", - "once_cell", - "openssl-sys", -] - -[[package]] -name = "openssl-probe" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" - -[[package]] -name = "openssl-sys" -version = "0.9.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "ordered-float" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" -dependencies = [ - "num-traits", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi 0.3.9", -] - -[[package]] -name = "parquet-format-async-temp" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03abc2f9c83fe9ceec83f47c76cc071bfd56caba33794340330f35623ab1f544" -dependencies = [ - "async-trait", - "byteorder", - "futures 0.3.18", - "integer-encoding", - "ordered-float", -] - -[[package]] -name = "parquet2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db82df54cdd88931d29b850190915b9069bb93fba8e1aefc0d59d8ca81603d6d" -dependencies = [ - "async-stream", - "bitpacking", - "brotli", - "flate2", - "futures 0.3.18", - "lz4", - "parquet-format-async-temp", - "snap", - "streaming-decompression", - "zstd", -] - -[[package]] -name = "parse-zoneinfo" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" -dependencies = [ - "regex", -] - -[[package]] -name = "path_abs" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ef02f6342ac01d8a93b65f96db53fe68a92a15f41144f97fb00a9e669633c3" -dependencies = [ - "std_prelude", -] - -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "peresil" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57" - -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_macros", - "phf_shared", - "proc-macro-hack", -] - -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared", - "rand 0.7.3", -] - -[[package]] -name = "phf_macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" - -[[package]] -name = "plist" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" -dependencies = [ - "base64", - "indexmap", - "line-wrap", - "serde", - "time 0.3.5", - "xml-rs", -] - -[[package]] -name = "png" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" -dependencies = [ - "bitflags", - "crc32fast", - "deflate", - "miniz_oxide 0.3.7", -] - -[[package]] -name = "polars" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c94a25d46e93b64eac7848c028a545dc08fa01e148e4942c5442b3843c3a598" -dependencies = [ - "polars-core", - "polars-io", - "polars-lazy", -] - -[[package]] -name = "polars-arrow" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cc4488d2f2d6b901bb6e5728e58966013a272cae48861070b676215a79b4a99" -dependencies = [ - "arrow2", - "num 0.4.0", - "thiserror", -] - -[[package]] -name = "polars-core" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6771524063d742a08163d96875ca5df71dff7113f27da58db5ec5fa164165bf6" -dependencies = [ - "ahash", - "anyhow", - "arrow2", - "chrono", - "comfy-table", - "hashbrown", - "itertools", - "lazy_static", - "num 0.4.0", - "num_cpus", - "polars-arrow", - "rand 0.7.3", - "rand_distr", - "rayon", - "regex", - "serde", - "serde_json", - "thiserror", - "unsafe_unwrap", -] - -[[package]] -name = "polars-io" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a5f5f51525043ee7befd49e586e6919345237826a5f17b53956f8242100957" -dependencies = [ - "ahash", - "anyhow", - "arrow2", - "csv-core", - "dirs", - "lazy_static", - "lexical", - "memchr", - "memmap2", - "num 0.4.0", - "num_cpus", - "polars-arrow", - "polars-core", - "rayon", - "regex", - "simdutf8", -] - -[[package]] -name = "polars-lazy" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3ea647e2fa59d1bbbf90929c5d10ef6a9018aac256d1c6d0e8248211804b61" -dependencies = [ - "ahash", - "itertools", - "polars-arrow", - "polars-core", - "polars-io", - "rayon", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "pretty" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60c0d9f6fc88ecdd245d90c1920ff76a430ab34303fc778d33b1d0a4c3bf6d3" -dependencies = [ - "typed-arena", -] - -[[package]] -name = "pretty_env_logger" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" -dependencies = [ - "env_logger 0.7.1", - "log", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro2" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "ptree" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0de80796b316aec75344095a6d2ef68ec9b8f573b9e7adc821149ba3598e270" -dependencies = [ - "serde", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quick-xml" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d72d5477478f85bd00b6521780dfba1ec6cdaadcf90b8b181c36d7de561f9b" -dependencies = [ - "encoding_rs", - "memchr", -] - -[[package]] -name = "quick-xml" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" -dependencies = [ - "memchr", -] - -[[package]] -name = "quickcheck" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" -dependencies = [ - "env_logger 0.8.4", - "log", - "rand 0.8.4", -] - -[[package]] -name = "quickcheck_macros" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "quote" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", - "rand_pcg", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.3", - "rand_hc 0.3.1", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.3", -] - -[[package]] -name = "rand_distr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9532ada3929fb8b2e9dbe28d1e06c9b2cc65813f074fcb6bd5fbefeff9d56" -dependencies = [ - "num-traits", - "rand 0.7.3", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rawkey" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad6efac35ef044d565b23f0d111d76aa21ab2e86934b1225f7071d42e58ebad" -dependencies = [ - "readkey", - "user32-sys", - "winapi 0.3.9", - "x11", -] - -[[package]] -name = "rayon" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "readkey" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d401b6d6a1725a59f1b4e813275d289dff3ad09c72b373a10a7a8217ba3146" - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom 0.2.3", - "redox_syscall", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "reqwest" -version = "0.11.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bea77bc708afa10e59905c3d4af7c8fd43c9214251673095ff8b14345fcbc5" -dependencies = [ - "base64", - "bytes 1.1.0", - "encoding_rs", - "futures-core", - "futures-util", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "lazy_static", - "log", - "mime", - "native-tls", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[package]] -name = "result" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194d8e591e405d1eecf28819740abed6d719d1a2db87fc0bcdedee9a26d55560" - -[[package]] -name = "roxmltree" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "rstest" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "041bb0202c14f6a158bbbf086afb03d0c6e975c2dec7d4912f8061ed44f290af" -dependencies = [ - "cfg-if 1.0.0", - "proc-macro2", - "quote", - "rustc_version 0.3.3", - "syn", -] - -[[package]] -name = "rusqlite" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a82b0b91fad72160c56bf8da7a549b25d7c31109f52cc1437eac4c0ad2550a7" -dependencies = [ - "bitflags", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "memchr", - "smallvec", -] - -[[package]] -name = "rust-embed" -version = "5.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fe1fe6aac5d6bb9e1ffd81002340363272a7648234ec7bdfac5ee202cb65523" -dependencies = [ - "rust-embed-impl", - "rust-embed-utils", - "walkdir", -] - -[[package]] -name = "rust-embed-impl" -version = "5.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed91c41c42ef7bf687384439c312e75e0da9c149b0390889b94de3c7d9d9e66" -dependencies = [ - "proc-macro2", - "quote", - "rust-embed-utils", - "syn", - "walkdir", -] - -[[package]] -name = "rust-embed-utils" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a512219132473ab0a77b52077059f1c47ce4af7fbdc94503e9862a34422876d" -dependencies = [ - "walkdir", -] - -[[package]] -name = "rust_decimal" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93c95e3d5c1d997e6e4ba9bda898f4e1d73934cd05510c972f10087d0ef00c1" -dependencies = [ - "byteorder", - "lazy_static", - "num 0.2.1", - "serde", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.4", -] - -[[package]] -name = "rustversion" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" - -[[package]] -name = "rustyline" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790487c3881a63489ae77126f57048b42d62d3b2bafbf37453ea19eedb6340d6" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "clipboard-win", - "dirs-next", - "fd-lock", - "libc", - "log", - "memchr", - "nix", - "radix_trie", - "scopeguard", - "smallvec", - "unicode-segmentation", - "unicode-width", - "utf8parse", - "winapi 0.3.9", -] - -[[package]] -name = "ryu" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568" - -[[package]] -name = "s3handler" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b9590f1cae0b8b38aceabab05885c754416b6d33089c244a25441ae997fdb1" -dependencies = [ - "async-trait", - "base64", - "bytes 1.1.0", - "chrono", - "dyn-clone", - "failure", - "failure_derive", - "futures 0.3.18", - "hex", - "hmac", - "hmac-sha1", - "log", - "md5", - "mime_guess", - "quick-xml 0.22.0", - "regex", - "reqwest", - "rustc-serialize", - "serde", - "serde_derive", - "serde_json", - "sha2", - "tokio", - "url", -] - -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" -dependencies = [ - "lazy_static", - "winapi 0.3.9", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scraper" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e02aa790c80c2e494130dec6a522033b6a23603ffc06360e9fe6c611ea2c12" -dependencies = [ - "cssparser", - "ego-tree", - "getopts", - "html5ever", - "matches", - "selectors", - "smallvec", - "tendril", -] - -[[package]] -name = "security-framework" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "selectors" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" -dependencies = [ - "bitflags", - "cssparser", - "derive_more", - "fxhash", - "log", - "matches", - "phf", - "phf_codegen", - "precomputed-hash", - "servo_arc", - "smallvec", - "thin-slice", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "serde" -version = "1.0.130" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bytes" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.130" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_ini" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb236687e2bb073a7521c021949be944641e671b8505a94069ca37b656c81139" -dependencies = [ - "result", - "serde", - "void", -] - -[[package]] -name = "serde_json" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_test" -version = "1.0.130" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82178225dbdeae2d5d190e8649287db6a3a32c6d24da22ae3146325aa353e4c" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af" -dependencies = [ - "dtoa", - "indexmap", - "serde", - "yaml-rust", -] - -[[package]] -name = "serial_test" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d" -dependencies = [ - "lazy_static", - "parking_lot", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "servo_arc" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" -dependencies = [ - "nodrop", - "stable_deref_trait", -] - -[[package]] -name = "sha1" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" - -[[package]] -name = "sha2" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" -dependencies = [ - "block-buffer", - "cfg-if 1.0.0", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "shadow-rs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8935e920eb80ff8f5a5bced990325d12f6cc1015154a3852c6a23cf5bd71c447" -dependencies = [ - "chrono", - "git2", - "is_debug", -] - -[[package]] -name = "shell-escape" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" - -[[package]] -name = "shell-words" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074" - -[[package]] -name = "signal-hook" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729" -dependencies = [ - "libc", - "mio", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "simdutf8" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970da16e7c682fa90a261cf0724dee241c9f7831635ecc4e988ae8f3b505559" - -[[package]] -name = "similar" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad1d488a557b235fc46dae55512ffbfc429d2482b08b4d9435ab07384ca8aec" - -[[package]] -name = "siphasher" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" - -[[package]] -name = "slab" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" - -[[package]] -name = "smallvec" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" - -[[package]] -name = "smart-default" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "snap" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451" - -[[package]] -name = "socket2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "spin" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "std_prelude" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8207e78455ffdf55661170876f88daf85356e4edd54e0a3dbc79586ca1e50cbe" - -[[package]] -name = "str-buf" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a" - -[[package]] -name = "streaming-decompression" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bc687acd5dc742c4a7094f2927a8614a68e4743ef682e7a2f9f0f711656cc92" -dependencies = [ - "fallible-streaming-iterator", -] - -[[package]] -name = "streaming-iterator" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "303235c177994a476226b80d076bd333b7b560fb05bd242a10609d11b07f81f5" - -[[package]] -name = "strength_reduce" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ff2f71c82567c565ba4b3009a9350a96a7269eaa4001ebedae926230bc2254" - -[[package]] -name = "string_cache" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923f0f39b6267d37d23ce71ae7235602134b250ace715dd2c90421998ddac0c6" -dependencies = [ - "lazy_static", - "new_debug_unreachable", - "parking_lot", - "phf_shared", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", -] - -[[package]] -name = "strip-ansi-escapes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8" -dependencies = [ - "vte", -] - -[[package]] -name = "strum" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" - -[[package]] -name = "strum_macros" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "sxd-document" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d82f37be9faf1b10a82c4bd492b74f698e40082f0f40de38ab275f31d42078" -dependencies = [ - "peresil", - "typed-arena", -] - -[[package]] -name = "sxd-xpath" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36e39da5d30887b5690e29de4c5ebb8ddff64ebd9933f98a01daaa4fd11b36ea" -dependencies = [ - "peresil", - "quick-error", - "sxd-document", -] - -[[package]] -name = "syn" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "syntect" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b20815bbe80ee0be06e6957450a841185fcf690fe0178f14d77a05ce2caa031" -dependencies = [ - "bincode", - "bitflags", - "flate2", - "fnv", - "lazy_static", - "lazycell", - "onig", - "plist", - "regex-syntax", - "serde", - "serde_derive", - "serde_json", - "walkdir", - "yaml-rust", -] - -[[package]] -name = "sys-info" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "sys-locale" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91f89ebb59fa30d4f65fafc2d68e94f6975256fd87e812dd99cb6e020c8563df" -dependencies = [ - "cc", - "cstr_core", - "libc", - "web-sys", - "winapi 0.3.9", -] - -[[package]] -name = "sysinfo" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e757000a4bed2b1be9be65a3f418b9696adf30bb419214c73997422de73a591" -dependencies = [ - "cfg-if 1.0.0", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi 0.3.9", -] - -[[package]] -name = "tempfile" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "rand 0.8.4", - "redox_syscall", - "remove_dir_all", - "winapi 0.3.9", -] - -[[package]] -name = "tendril" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33" -dependencies = [ - "futf", - "mac", - "utf-8", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi 0.3.9", -] - -[[package]] -name = "term_size" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - -[[package]] -name = "time" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" -dependencies = [ - "itoa", - "libc", -] - -[[package]] -name = "tinyvec" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "titlecase" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f565e410cfc24c2f2a89960b023ca192689d7f77d3f8d4f4af50c2d8affe1117" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "tokio" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" -dependencies = [ - "autocfg", - "bytes 1.1.0", - "libc", - "memchr", - "mio", - "num_cpus", - "pin-project-lite", - "tokio-macros", - "winapi 0.3.9", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "log", -] - -[[package]] -name = "tokio-macros" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" -dependencies = [ - "bytes 1.1.0", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "tower-service" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" - -[[package]] -name = "tracing" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" -dependencies = [ - "cfg-if 1.0.0", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "trash" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ebb6cb2db7947ab9f65dec9f7c5dbe01042b708f564242dcfb6d5cb2957cbc" -dependencies = [ - "chrono", - "libc", - "log", - "objc", - "scopeguard", - "url", - "windows", -] - -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - -[[package]] -name = "tui" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "861d8f3ad314ede6219bcb2ab844054b1de279ee37a9bc38e3d606f9d3fb2a71" -dependencies = [ - "bitflags", - "cassowary", - "crossterm", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "typed-arena" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" - -[[package]] -name = "typenum" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" - -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - -[[package]] -name = "umask" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982efbf70ec4d28f7862062c03dd1a4def601a5079e0faf1edc55f2ad0f6fe46" - -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" - -[[package]] -name = "unicode-normalization" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "unsafe_unwrap" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1230ec65f13e0f9b28d789da20d2d419511893ea9dac2c1f4ef67b8b14e5da80" - -[[package]] -name = "url" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" -dependencies = [ - "form_urlencoded", - "idna", - "matches", - "percent-encoding", -] - -[[package]] -name = "user32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "users" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" -dependencies = [ - "libc", - "log", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8-width" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b" - -[[package]] -name = "utf8parse" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom 0.2.3", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "vte" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" -dependencies = [ - "arrayvec 0.5.2", - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi 0.3.9", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasm-bindgen" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" - -[[package]] -name = "web-sys" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecad156490d6b620308ed411cfee90d280b3cbd13e189ea0d3fada8acc89158a" -dependencies = [ - "web-sys", - "widestring", - "winapi 0.3.9", -] - -[[package]] -name = "which" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" -dependencies = [ - "either", - "lazy_static", - "libc", -] - -[[package]] -name = "widestring" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361f3533a83ee1a28c9be59683f40043db02dbedf6479ce8795657386195c97f" -dependencies = [ - "const-sha1", - "windows_gen", - "windows_macros", -] - -[[package]] -name = "windows-sys" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6" -dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2" - -[[package]] -name = "windows_gen" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54154dbc515d58723f6b6053c12f1065da7389f733660581b2391bd1af480452" -dependencies = [ - "syn", -] - -[[package]] -name = "windows_i686_gnu" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a" - -[[package]] -name = "windows_i686_msvc" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64" - -[[package]] -name = "windows_macros" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7794c652845dc466cb8dc1b86c08345707c8144bc53e9086430047c7d33b76" -dependencies = [ - "syn", - "windows_gen", -] - -[[package]] -name = "windows_x86_64_gnu" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f" - -[[package]] -name = "winreg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "x11" -version = "2.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd0565fa8bfba8c5efe02725b14dff114c866724eff2cfd44d76cea74bcd87a" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "xml-rs" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" - -[[package]] -name = "xmlparser" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "114ba2b24d2167ef6d67d7d04c8cc86522b87f490025f39f0303b7db5bf5e3d8" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "zip" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" -dependencies = [ - "byteorder", - "bzip2", - "crc32fast", - "flate2", - "thiserror", - "time 0.1.44", -] - -[[package]] -name = "zstd" -version = "0.9.0+zstd.1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07749a5dc2cb6b36661290245e350f15ec3bbb304e493db54a1d354480522ccd" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "4.1.1+zstd.1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91c90f2c593b003603e5e0493c837088df4469da25aafff8bce42ba48caf079" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "1.6.1+zstd.1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "615120c7a2431d16cf1cf979e7fc31ba7a5b5e5707b29c8a99e5dbf8a8392a33" -dependencies = [ - "cc", - "libc", -] diff --git a/old_nushell/Cargo_old.toml b/old_nushell/Cargo_old.toml deleted file mode 100644 index a83162319..000000000 --- a/old_nushell/Cargo_old.toml +++ /dev/null @@ -1,229 +0,0 @@ -[package] -authors = ["The Nu Project Contributors"] -default-run = "nu" -description = "A new type of shell" -documentation = "https://www.nushell.sh/book/" -edition = "2018" -exclude = ["images"] -homepage = "https://www.nushell.sh" -license = "MIT" -name = "nu" -readme = "README.md" -repository = "https://github.com/nushell/nushell" -version = "0.43.0" - -[workspace] -members = ["crates/*/"] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -nu-cli = { version = "0.43.0", path="./crates/nu-cli", default-features=false } -nu-command = { version = "0.43.0", path="./crates/nu-command" } -nu-completion = { version = "0.43.0", path="./crates/nu-completion" } -nu-data = { version = "0.43.0", path="./crates/nu-data" } -nu-engine = { version = "0.43.0", path="./crates/nu-engine" } -nu-errors = { version = "0.43.0", path="./crates/nu-errors" } -nu-parser = { version = "0.43.0", path="./crates/nu-parser" } -nu-path = { version = "0.43.0", path="./crates/nu-path" } -nu-plugin = { version = "0.43.0", path="./crates/nu-plugin" } -nu-protocol = { version = "0.43.0", path="./crates/nu-protocol" } -nu-source = { version = "0.43.0", path="./crates/nu-source" } -nu-value-ext = { version = "0.43.0", path="./crates/nu-value-ext" } - -nu_plugin_binaryview = { version = "0.43.0", path="./crates/nu_plugin_binaryview", optional=true } -nu_plugin_chart = { version = "0.43.0", path="./crates/nu_plugin_chart", optional=true } -nu_plugin_from_bson = { version = "0.43.0", path="./crates/nu_plugin_from_bson", optional=true } -nu_plugin_from_sqlite = { version = "0.43.0", path="./crates/nu_plugin_from_sqlite", optional=true } -nu_plugin_inc = { version = "0.43.0", path="./crates/nu_plugin_inc", optional=true } -nu_plugin_match = { version = "0.43.0", path="./crates/nu_plugin_match", optional=true } -nu_plugin_query_json = { version = "0.43.0", path="./crates/nu_plugin_query_json", optional=true } -nu_plugin_s3 = { version = "0.43.0", path="./crates/nu_plugin_s3", optional=true } -nu_plugin_selector = { version = "0.43.0", path="./crates/nu_plugin_selector", optional=true } -nu_plugin_start = { version = "0.43.0", path="./crates/nu_plugin_start", optional=true } -nu_plugin_textview = { version = "0.43.0", path="./crates/nu_plugin_textview", optional=true } -nu_plugin_to_bson = { version = "0.43.0", path="./crates/nu_plugin_to_bson", optional=true } -nu_plugin_to_sqlite = { version = "0.43.0", path="./crates/nu_plugin_to_sqlite", optional=true } -nu_plugin_tree = { version = "0.43.0", path="./crates/nu_plugin_tree", optional=true } -nu_plugin_xpath = { version = "0.43.0", path="./crates/nu_plugin_xpath", optional=true } - -# Required to bootstrap the main binary -ctrlc = { version="3.1.7", optional=true } -futures = { version="0.3.12", features=["compat", "io-compat"] } -itertools = "0.10.0" - -[dev-dependencies] -nu-test-support = { version = "0.43.0", path="./crates/nu-test-support" } -serial_test = "0.5.1" -hamcrest2 = "0.3.0" -rstest = "0.10.0" - -[build-dependencies] - -[features] -fetch-support = ["nu-command/fetch", "nu-command/post"] -sys-support = ["nu-command/sys", "nu-command/ps"] -ctrlc-support = ["nu-cli/ctrlc", "nu-command/ctrlc"] -rustyline-support = ["nu-cli/rustyline-support", "nu-command/rustyline-support"] -term-support = ["nu-command/term"] -uuid-support = ["nu-command/uuid_crate"] -which-support = ["nu-command/which", "nu-engine/which"] - -default = [ - "nu-cli/shadow-rs", - "sys-support", - "ctrlc-support", - "which-support", - "term-support", - "rustyline-support", - "match", - "fetch-support", - "zip-support", - "dataframe", -] - -stable = ["default"] -extra = [ - "default", - "binaryview", - "inc", - "tree", - "textview", - "trash-support", - "uuid-support", - "start", - "bson", - "sqlite", - "s3", - "chart", - "xpath", - "selector", - "query-json", -] - -wasi = ["inc", "match", "match", "tree", "rustyline-support"] - -# Stable (Default) -inc = ["nu_plugin_inc"] -match = ["nu_plugin_match"] -textview = ["nu_plugin_textview"] - -# Extra -binaryview = ["nu_plugin_binaryview"] -bson = ["nu_plugin_from_bson", "nu_plugin_to_bson"] -chart = ["nu_plugin_chart"] -query-json = ["nu_plugin_query_json"] -s3 = ["nu_plugin_s3"] -selector = ["nu_plugin_selector"] -sqlite = ["nu_plugin_from_sqlite", "nu_plugin_to_sqlite"] -start = ["nu_plugin_start"] -trash-support = [ - "nu-command/trash-support", - "nu-engine/trash-support", -] -tree = ["nu_plugin_tree"] -xpath = ["nu_plugin_xpath"] -zip-support = ["nu-command/zip"] - -#dataframe feature for nushell -dataframe = [ - "nu-engine/dataframe", - "nu-protocol/dataframe", - "nu-command/dataframe", - "nu-value-ext/dataframe", - "nu-data/dataframe", - "nu_plugin_to_bson/dataframe", -] - -[profile.release] -opt-level = "s" # Optimize for size. - -# Core plugins that ship with `cargo install nu` by default -# Currently, Cargo limits us to installing only one binary -# unless we use [[bin]], so we use this as a workaround -[[bin]] -name = "nu_plugin_core_textview" -path = "src/plugins/nu_plugin_core_textview.rs" -required-features = ["textview"] - -[[bin]] -name = "nu_plugin_core_inc" -path = "src/plugins/nu_plugin_core_inc.rs" -required-features = ["inc"] - -[[bin]] -name = "nu_plugin_core_match" -path = "src/plugins/nu_plugin_core_match.rs" -required-features = ["match"] - -# Extra plugins - -[[bin]] -name = "nu_plugin_extra_binaryview" -path = "src/plugins/nu_plugin_extra_binaryview.rs" -required-features = ["binaryview"] - -[[bin]] -name = "nu_plugin_extra_tree" -path = "src/plugins/nu_plugin_extra_tree.rs" -required-features = ["tree"] - -[[bin]] -name = "nu_plugin_extra_query_json" -path = "src/plugins/nu_plugin_extra_query_json.rs" -required-features = ["query-json"] - -[[bin]] -name = "nu_plugin_extra_start" -path = "src/plugins/nu_plugin_extra_start.rs" -required-features = ["start"] - -[[bin]] -name = "nu_plugin_extra_s3" -path = "src/plugins/nu_plugin_extra_s3.rs" -required-features = ["s3"] - -[[bin]] -name = "nu_plugin_extra_chart_bar" -path = "src/plugins/nu_plugin_extra_chart_bar.rs" -required-features = ["chart"] - -[[bin]] -name = "nu_plugin_extra_chart_line" -path = "src/plugins/nu_plugin_extra_chart_line.rs" -required-features = ["chart"] - -[[bin]] -name = "nu_plugin_extra_xpath" -path = "src/plugins/nu_plugin_extra_xpath.rs" -required-features = ["xpath"] - -[[bin]] -name = "nu_plugin_extra_selector" -path = "src/plugins/nu_plugin_extra_selector.rs" -required-features = ["selector"] - -[[bin]] -name = "nu_plugin_extra_from_bson" -path = "src/plugins/nu_plugin_extra_from_bson.rs" -required-features = ["bson"] - -[[bin]] -name = "nu_plugin_extra_to_bson" -path = "src/plugins/nu_plugin_extra_to_bson.rs" -required-features = ["bson"] - -[[bin]] -name = "nu_plugin_extra_from_sqlite" -path = "src/plugins/nu_plugin_extra_from_sqlite.rs" -required-features = ["sqlite"] - -[[bin]] -name = "nu_plugin_extra_to_sqlite" -path = "src/plugins/nu_plugin_extra_to_sqlite.rs" -required-features = ["sqlite"] - -# Main nu binary -[[bin]] -name = "nu" -path = "src/main.rs" diff --git a/old_nushell/README.md b/old_nushell/README.md deleted file mode 100644 index ea2da1fb1..000000000 --- a/old_nushell/README.md +++ /dev/null @@ -1,283 +0,0 @@ -# README - -[![Crates.io](https://img.shields.io/crates/v/nu.svg)](https://crates.io/crates/nu) -[![Build Status](https://dev.azure.com/nushell/nushell/_apis/build/status/nushell.nushell?branchName=main)](https://dev.azure.com/nushell/nushell/_build/latest?definitionId=2&branchName=main) -[![Discord](https://img.shields.io/discord/601130461678272522.svg?logo=discord)](https://discord.gg/NtAbbGn) -[![The Changelog #363](https://img.shields.io/badge/The%20Changelog-%23363-61c192.svg)](https://changelog.com/podcast/363) -[![@nu_shell](https://img.shields.io/badge/twitter-@nu_shell-1DA1F3?style=flat-square)](https://twitter.com/nu_shell) -![GitHub commit activity](https://img.shields.io/github/commit-activity/m/nushell/nushell) -![GitHub contributors](https://img.shields.io/github/contributors/nushell/nushell) - -## Nushell - -A new type of shell. - -![Example of nushell](images/nushell-autocomplete5.gif "Example of nushell") - -## Status - -This project has reached a minimum-viable product level of quality. -While contributors dogfood it as their daily driver, it may be unstable for some commands. -Future releases will work to fill out missing features and improve stability. -Its design is also subject to change as it matures. - -Nu comes with a set of built-in commands (listed below). -If a command is unknown, the command will shell-out and execute it (using cmd on Windows or bash on Linux and macOS), correctly passing through stdin, stdout, and stderr, so things like your daily git workflows and even `vim` will work just fine. - -## Learning more - -There are a few good resources to learn about Nu. -There is a [book](https://www.nushell.sh/book/) about Nu that is currently in progress. -The book focuses on using Nu and its core concepts. - -If you're a developer who would like to contribute to Nu, we're also working on a [book for developers](https://www.nushell.sh/contributor-book/) to help you get started. -There are also [good first issues](https://github.com/nushell/nushell/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) to help you dive in. - -We also have an active [Discord](https://discord.gg/NtAbbGn) and [Twitter](https://twitter.com/nu_shell) if you'd like to come and chat with us. - -You can also find information on more specific topics in our [cookbook](https://www.nushell.sh/cookbook/). - -## Installation - -### Local - -Up-to-date installation instructions can be found in the [installation chapter of the book](https://www.nushell.sh/book/installation.html). **Windows users**: please note that Nu works on Windows 10 and does not currently have Windows 7/8.1 support. - -To build Nu, you will need to use the **latest stable (1.51 or later)** version of the compiler. - -Required dependencies: - -- pkg-config and libssl (only needed on Linux) - - On Debian/Ubuntu: `apt install pkg-config libssl-dev` - -Optional dependencies: - -- To use Nu with all possible optional features enabled, you'll also need the following: - - On Linux (on Debian/Ubuntu): `apt install libxcb-composite0-dev libx11-dev` - -To install Nu via cargo (make sure you have installed [rustup](https://rustup.rs/) and the latest stable compiler via `rustup install stable`): - -```shell -cargo install nu -``` - -To install Nu via the [Windows Package Manager](https://aka.ms/winget-cli): - -```shell -winget install nushell -``` - -You can also build Nu yourself with all the bells and whistles (be sure to have installed the [dependencies](https://www.nushell.sh/book/installation.html#dependencies) for your platform), once you have checked out this repo with git: - -```shell -cargo build --workspace --features=extra -``` -### Packaging status - -[![Packaging status](https://repology.org/badge/vertical-allrepos/nushell.svg)](https://repology.org/project/nushell/versions) - -#### Fedora - -[COPR repo](https://copr.fedorainfracloud.org/coprs/atim/nushell/): `sudo dnf copr enable atim/nushell -y && sudo dnf install nushell -y` - -## Philosophy - -Nu draws inspiration from projects like PowerShell, functional programming languages, and modern CLI tools. -Rather than thinking of files and services as raw streams of text, Nu looks at each input as something with structure. -For example, when you list the contents of a directory, what you get back is a table of rows, where each row represents an item in that directory. -These values can be piped through a series of steps, in a series of commands called a 'pipeline'. - -### Pipelines - -In Unix, it's common to pipe between commands to split up a sophisticated command over multiple steps. -Nu takes this a step further and builds heavily on the idea of _pipelines_. -Just as the Unix philosophy, Nu allows commands to output to stdout and read from stdin. -Additionally, commands can output structured data (you can think of this as a third kind of stream). -Commands that work in the pipeline fit into one of three categories: - -- Commands that produce a stream (e.g., `ls`) -- Commands that filter a stream (eg, `where type == "Dir"`) -- Commands that consume the output of the pipeline (e.g., `autoview`) - -Commands are separated by the pipe symbol (`|`) to denote a pipeline flowing left to right. - -```shell -> ls | where type == "Dir" | autoview -───┬────────┬──────┬───────┬────────────── - # │ name │ type │ size │ modified -───┼────────┼──────┼───────┼────────────── - 0 │ assets │ Dir │ 128 B │ 5 months ago - 1 │ crates │ Dir │ 704 B │ 50 mins ago - 2 │ debian │ Dir │ 352 B │ 5 months ago - 3 │ docs │ Dir │ 192 B │ 50 mins ago - 4 │ images │ Dir │ 160 B │ 5 months ago - 5 │ src │ Dir │ 128 B │ 1 day ago - 6 │ target │ Dir │ 160 B │ 5 days ago - 7 │ tests │ Dir │ 192 B │ 3 months ago -───┴────────┴──────┴───────┴────────────── -``` - -Because most of the time you'll want to see the output of a pipeline, `autoview` is assumed. -We could have also written the above: - -```shell -> ls | where type == Dir -``` - -Being able to use the same commands and compose them differently is an important philosophy in Nu. -For example, we could use the built-in `ps` command to get a list of the running processes, using the same `where` as above. - -```shell -> ps | where cpu > 0 -───┬────────┬───────────────────┬──────────┬─────────┬──────────┬────────── - # │ pid │ name │ status │ cpu │ mem │ virtual -───┼────────┼───────────────────┼──────────┼─────────┼──────────┼────────── - 0 │ 435 │ irq/142-SYNA327 │ Sleeping │ 7.5699 │ 0 B │ 0 B - 1 │ 1609 │ pulseaudio │ Sleeping │ 6.5605 │ 10.6 MB │ 2.3 GB - 2 │ 1625 │ gnome-shell │ Sleeping │ 6.5684 │ 639.6 MB │ 7.3 GB - 3 │ 2202 │ Web Content │ Sleeping │ 6.8157 │ 320.8 MB │ 3.0 GB - 4 │ 328788 │ nu_plugin_core_ps │ Sleeping │ 92.5750 │ 5.9 MB │ 633.2 MB -───┴────────┴───────────────────┴──────────┴─────────┴──────────┴────────── -``` - -### Opening files - -Nu can load file and URL contents as raw text or structured data (if it recognizes the format). -For example, you can load a .toml file as structured data and explore it: - -```shell -> open Cargo.toml -────────────────────┬─────────────────────────── - bin │ [table 18 rows] - build-dependencies │ [row serde toml] - dependencies │ [row 29 columns] - dev-dependencies │ [row nu-test-support] - features │ [row 19 columns] - package │ [row 12 columns] - workspace │ [row members] -────────────────────┴─────────────────────────── -``` - -We can pipeline this into a command that gets the contents of one of the columns: - -```shell -> open Cargo.toml | get package -───────────────┬──────────────────────────────────── - authors │ [table 1 rows] - default-run │ nu - description │ A new type of shell - documentation │ https://www.nushell.sh/book/ - edition │ 2018 - exclude │ [table 1 rows] - homepage │ https://www.nushell.sh - license │ MIT - name │ nu - readme │ README.md - repository │ https://github.com/nushell/nushell - version │ 0.32.0 -───────────────┴──────────────────────────────────── -``` - -Finally, we can use commands outside of Nu once we have the data we want: - -```shell -> open Cargo.toml | get package.version -0.32.0 -``` - -### Configuration - -Nu has early support for configuring the shell. You can refer to the book for a list of [all supported variables](https://www.nushell.sh/book/configuration.html). - -To set one of these variables, you can use `config set`. For example: - -```shell -> config set line_editor.edit_mode "vi" -> config set path $nu.path -``` - -### Shells - -Nu will work inside of a single directory and allow you to navigate around your filesystem by default. -Nu also offers a way of adding additional working directories that you can jump between, allowing you to work in multiple directories simultaneously. - -To do so, use the `enter` command, which will allow you to create a new "shell" and enter it at the specified path. -You can toggle between this new shell and the original shell with the `p` (for previous) and `n` (for next), allowing you to navigate around a ring buffer of shells. -Once you're done with a shell, you can `exit` it and remove it from the ring buffer. - -Finally, to get a list of all the current shells, you can use the `shells` command. - -### Plugins - -Nu supports plugins that offer additional functionality to the shell and follow the same structured data model that built-in commands use. -This allows you to extend nu for your needs. - -There are a few examples in the `plugins` directory. - -Plugins are binaries that are available in your path and follow a `nu_plugin_*` naming convention. -These binaries interact with nu via a simple JSON-RPC protocol where the command identifies itself and passes along its configuration, making it available for use. -If the plugin is a filter, data streams to it one element at a time, and it can stream data back in return via stdin/stdout. -If the plugin is a sink, it is given the full vector of final data and is given free reign over stdin/stdout to use as it pleases. - -## Goals - -Nu adheres closely to a set of goals that make up its design philosophy. As features are added, they are checked against these goals. - -- First and foremost, Nu is cross-platform. Commands and techniques should carry between platforms and offer consistent first-class support for Windows, macOS, and Linux. - -- Nu ensures direct compatibility with existing platform-specific executables that make up people's workflows. - -- Nu's workflow and tools should have the usability in day-to-day experience of using a shell in 2019 (and beyond). - -- Nu views data as both structured and unstructured. It is a structured shell like PowerShell. - -- Finally, Nu views data functionally. Rather than using mutation, pipelines act as a means to load, change, and save data without mutable state. - -## Commands - -You can find a list of Nu commands, complete with documentation, in [quick command references](https://www.nushell.sh/book/command_reference.html). - -## Progress - -Nu is in heavy development and will naturally change as it matures and people use it. The chart below isn't meant to be exhaustive, but rather helps give an idea for some of the areas of development and their relative completion: - -| Features | Not started | Prototype | MVP | Preview | Mature | Notes | -| ------------- | :---------: | :-------: | :-: | :-----: | :----: | -------------------------------------------------------------------- | -| Aliases | | | X | | | Aliases allow for shortening large commands, while passing flags | -| Notebook | | X | | | | Initial jupyter support, but it loses state and lacks features | -| File ops | | | X | | | cp, mv, rm, mkdir have some support, but lacking others | -| Environment | | | X | | | Temporary environment and scoped environment variables | -| Shells | | X | | | | Basic value and file shells, but no opt-in/opt-out for commands | -| Protocol | | | X | | | Streaming protocol is serviceable | -| Plugins | | X | | | | Plugins work on one row at a time, lack batching and expression eval | -| Errors | | | X | | | Error reporting works, but could use usability polish | -| Documentation | | | X | | | Book updated to latest release, including usage examples | -| Paging | | X | | | | Textview has paging, but we'd like paging for tables | -| Functions | | | X | | | Functions and aliases are supported | -| Variables | | | X | | | Nu supports variables and environment variables | -| Completions | | | X | | | Completions for filepaths | -| Type-checking | | | X | | | Commands check basic types, but input/output isn't checked | - -## Officially Supported By - -Please submit an issue or PR to be added to this list. - -### Integrations -- [zoxide](https://github.com/ajeetdsouza/zoxide) -- [starship](https://github.com/starship/starship) -### Mentions -- [The Python Launcher for Unix](https://github.com/brettcannon/python-launcher#how-do-i-get-a-table-of-python-executables-in-nushell) - -## Contributing - -See [Contributing](CONTRIBUTING.md) for details. - -Thanks to all the people who already contributed! - - - - - -## License - -The project is made available under the MIT license. See the `LICENSE` file for more information. diff --git a/old_nushell/crates/README.md b/old_nushell/crates/README.md deleted file mode 100644 index ca1e44bcc..000000000 --- a/old_nushell/crates/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Nushell core libraries and plugins - -These sub-crates form both the foundation for Nu and a set of plugins which extend Nu with additional functionality. - -Foundational libraries are split into two kinds of crates: - -* Core crates - those crates that work together to build the Nushell language engine -* Support crates - a set of crates that support the engine with additional features like JSON support, ANSI support, and more. - -Plugins are likewise also split into two types: - -* Core plugins - plugins that provide part of the default experience of Nu, including access to the system properties, processes, and web-connectivity features. -* Extra plugins - these plugins run a wide range of different capabilities like working with different file types, charting, viewing binary data, and more. diff --git a/old_nushell/crates/nu-ansi-term/.gitignore b/old_nushell/crates/nu-ansi-term/.gitignore deleted file mode 100644 index f2f9e58ec..000000000 --- a/old_nushell/crates/nu-ansi-term/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target -Cargo.lock \ No newline at end of file diff --git a/old_nushell/crates/nu-ansi-term/Cargo.toml b/old_nushell/crates/nu-ansi-term/Cargo.toml deleted file mode 100644 index 00d744d7a..000000000 --- a/old_nushell/crates/nu-ansi-term/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -authors = [ - "ogham@bsago.me", - "Ryan Scheel (Havvy) ", - "Josh Triplett ", - "The Nu Project Contributors", -] -description = "Library for ANSI terminal colors and styles (bold, underline)" -edition = "2018" -license = "MIT" -name = "nu-ansi-term" -version = "0.43.0" - -[lib] -doctest = false -# name = "nu-ansi-term" - -[features] -derive_serde_style = ["serde"] - -[dependencies] -overload = "0.1.1" -serde = { version="1.0.90", features=["derive"], optional=true } - -# [dependencies.serde] -# version = "1.0.90" -# features = ["derive"] -# optional = true - -[target.'cfg(target_os="windows")'.dependencies.winapi] -version = "0.3.4" -features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"] - -[dev-dependencies] -doc-comment = "0.3" -regex = "1.1.9" - -[dev-dependencies.serde_json] -version = "1.0.39" diff --git a/old_nushell/crates/nu-ansi-term/LICENCE b/old_nushell/crates/nu-ansi-term/LICENCE deleted file mode 100644 index 3228cc99b..000000000 --- a/old_nushell/crates/nu-ansi-term/LICENCE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Benjamin Sago - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/old_nushell/crates/nu-ansi-term/README.md b/old_nushell/crates/nu-ansi-term/README.md deleted file mode 100644 index 8143bb4d3..000000000 --- a/old_nushell/crates/nu-ansi-term/README.md +++ /dev/null @@ -1,182 +0,0 @@ -# nu-ansi-term - -> This is a copy of rust-ansi-term but with Color change to Color and light foreground colors added (90-97) as well as light background colors added (100-107). - -This is a library for controlling colors and formatting, such as red bold text or blue underlined text, on ANSI terminals. - -### [View the Rustdoc](https://docs.rs/nu_ansi_term/) - -# Installation - -This crate works with [Cargo](http://crates.io). Add the following to your `Cargo.toml` dependencies section: - -```toml -[dependencies] -nu_ansi_term = "0.13" -``` - -## Basic usage - -There are three main types in this crate that you need to be concerned with: `ANSIString`, `Style`, and `Color`. - -A `Style` holds stylistic information: foreground and background colors, whether the text should be bold, or blinking, or other properties. -The `Color` enum represents the available colors. -And an `ANSIString` is a string paired with a `Style`. - -`Color` is also available as an alias to `Color`. - -To format a string, call the `paint` method on a `Style` or a `Color`, passing in the string you want to format as the argument. -For example, here’s how to get some red text: - -```rust -use nu_ansi_term::Color::Red; - -println!("This is in red: {}", Red.paint("a red string")); -``` - -It’s important to note that the `paint` method does _not_ actually return a string with the ANSI control characters surrounding it. -Instead, it returns an `ANSIString` value that has a `Display` implementation that, when formatted, returns the characters. -This allows strings to be printed with a minimum of `String` allocations being performed behind the scenes. - -If you _do_ want to get at the escape codes, then you can convert the `ANSIString` to a string as you would any other `Display` value: - -```rust -use nu_ansi_term::Color::Red; - -let red_string = Red.paint("a red string").to_string(); -``` - -**Note for Windows 10 users:** On Windows 10, the application must enable ANSI support first: - -```rust,ignore -let enabled = nu_ansi_term::enable_ansi_support(); -``` - -## Bold, underline, background, and other styles - -For anything more complex than plain foreground color changes, you need to construct `Style` values themselves, rather than beginning with a `Color`. -You can do this by chaining methods based on a new `Style`, created with `Style::new()`. -Each method creates a new style that has that specific property set. -For example: - -```rust -use nu_ansi_term::Style; - -println!("How about some {} and {}?", - Style::new().bold().paint("bold"), - Style::new().underline().paint("underline")); -``` - -For brevity, these methods have also been implemented for `Color` values, so you can give your styles a foreground color without having to begin with an empty `Style` value: - -```rust -use nu_ansi_term::Color::{Blue, Yellow}; - -println!("Demonstrating {} and {}!", - Blue.bold().paint("blue bold"), - Yellow.underline().paint("yellow underline")); - -println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!")); -``` - -The complete list of styles you can use are: -`bold`, `dimmed`, `italic`, `underline`, `blink`, `reverse`, `hidden`, and `on` for background colors. - -In some cases, you may find it easier to change the foreground on an existing `Style` rather than starting from the appropriate `Color`. -You can do this using the `fg` method: - -```rust -use nu_ansi_term::Style; -use nu_ansi_term::Color::{Blue, Cyan, Yellow}; - -println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!")); -println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!")); -``` - -You can turn a `Color` into a `Style` with the `normal` method. -This will produce the exact same `ANSIString` as if you just used the `paint` method on the `Color` directly, but it’s useful in certain cases: for example, you may have a method that returns `Styles`, and need to represent both the “red bold” and “red, but not bold” styles with values of the same type. The `Style` struct also has a `Default` implementation if you want to have a style with _nothing_ set. - -```rust -use nu_ansi_term::Style; -use nu_ansi_term::Color::Red; - -Red.normal().paint("yet another red string"); -Style::default().paint("a completely regular string"); -``` - -## Extended colors - -You can access the extended range of 256 colors by using the `Color::Fixed` variant, which takes an argument of the color number to use. -This can be included wherever you would use a `Color`: - -```rust -use nu_ansi_term::Color::Fixed; - -Fixed(134).paint("A sort of light purple"); -Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup"); -``` - -The first sixteen of these values are the same as the normal and bold standard color variants. -There’s nothing stopping you from using these as `Fixed` colors instead, but there’s nothing to be gained by doing so either. - -You can also access full 24-bit color by using the `Color::RGB` variant, which takes separate `u8` arguments for red, green, and blue: - -```rust -use nu_ansi_term::Color::RGB; - -RGB(70, 130, 180).paint("Steel blue"); -``` - -## Combining successive coloured strings - -The benefit of writing ANSI escape codes to the terminal is that they _stack_: you do not need to end every coloured string with a reset code if the text that follows it is of a similar style. -For example, if you want to have some blue text followed by some blue bold text, it’s possible to send the ANSI code for blue, followed by the ANSI code for bold, and finishing with a reset code without having to have an extra one between the two strings. - -This crate can optimise the ANSI codes that get printed in situations like this, making life easier for your terminal renderer. -The `ANSIStrings` struct takes a slice of several `ANSIString` values, and will iterate over each of them, printing only the codes for the styles that need to be updated as part of its formatting routine. - -The following code snippet uses this to enclose a binary number displayed in red bold text inside some red, but not bold, brackets: - -```rust -use nu_ansi_term::Color::Red; -use nu_ansi_term::{ANSIString, ANSIStrings}; - -let some_value = format!("{:b}", 42); -let strings: &[ANSIString<'static>] = &[ - Red.paint("["), - Red.bold().paint(some_value), - Red.paint("]"), -]; - -println!("Value: {}", ANSIStrings(strings)); -``` - -There are several things to note here. -Firstly, the `paint` method can take _either_ an owned `String` or a borrowed `&str`. -Internally, an `ANSIString` holds a copy-on-write (`Cow`) string value to deal with both owned and borrowed strings at the same time. -This is used here to display a `String`, the result of the `format!` call, using the same mechanism as some statically-available `&str` slices. -Secondly, that the `ANSIStrings` value works in the same way as its singular counterpart, with a `Display` implementation that only performs the formatting when required. - -## Byte strings - -This library also supports formatting `[u8]` byte strings; this supports applications working with text in an unknown encoding. -`Style` and `Color` support painting `[u8]` values, resulting in an `ANSIByteString`. -This type does not implement `Display`, as it may not contain UTF-8, but it does provide a method `write_to` to write the result to any value that implements `Write`: - -```rust -use nu_ansi_term::Color::Green; - -Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap(); -``` - -Similarly, the type `ANSIByteStrings` supports writing a list of `ANSIByteString` values with minimal escape sequences: - -```rust -use nu_ansi_term::Color::Green; -use nu_ansi_term::ANSIByteStrings; - -ANSIByteStrings(&[ - Green.paint("user data 1\n".as_bytes()), - Green.bold().paint("user data 2\n".as_bytes()), -]).write_to(&mut std::io::stdout()).unwrap(); -``` diff --git a/old_nushell/crates/nu-ansi-term/examples/256_colors.rs b/old_nushell/crates/nu-ansi-term/examples/256_colors.rs deleted file mode 100644 index 4766dcdb6..000000000 --- a/old_nushell/crates/nu-ansi-term/examples/256_colors.rs +++ /dev/null @@ -1,72 +0,0 @@ -extern crate nu_ansi_term; -use nu_ansi_term::Color; - -// This example prints out the 256 colors. -// They're arranged like this: -// -// - 0 to 8 are the eight standard colors. -// - 9 to 15 are the eight bold colors. -// - 16 to 231 are six blocks of six-by-six color squares. -// - 232 to 255 are shades of grey. - -fn main() { - // First two lines - for c in 0..8 { - glow(c, c != 0); - print!(" "); - } - println!(); - for c in 8..16 { - glow(c, c != 8); - print!(" "); - } - println!("\n"); - - // Six lines of the first three squares - for row in 0..6 { - for square in 0..3 { - for column in 0..6 { - glow(16 + square * 36 + row * 6 + column, row >= 3); - print!(" "); - } - - print!(" "); - } - - println!(); - } - println!(); - - // Six more lines of the other three squares - for row in 0..6 { - for square in 0..3 { - for column in 0..6 { - glow(124 + square * 36 + row * 6 + column, row >= 3); - print!(" "); - } - - print!(" "); - } - - println!(); - } - println!(); - - // The last greyscale lines - for c in 232..=243 { - glow(c, false); - print!(" "); - } - println!(); - for c in 244..=255 { - glow(c, true); - print!(" "); - } - println!(); -} - -fn glow(c: u8, light_bg: bool) { - let base = if light_bg { Color::Black } else { Color::White }; - let style = base.on(Color::Fixed(c)); - print!("{}", style.paint(&format!(" {:3} ", c))); -} diff --git a/old_nushell/crates/nu-ansi-term/examples/basic_colors.rs b/old_nushell/crates/nu-ansi-term/examples/basic_colors.rs deleted file mode 100644 index 3c2b6817f..000000000 --- a/old_nushell/crates/nu-ansi-term/examples/basic_colors.rs +++ /dev/null @@ -1,18 +0,0 @@ -extern crate nu_ansi_term; -use nu_ansi_term::{Color::*, Style}; - -// This example prints out the 16 basic colors. - -fn main() { - let normal = Style::default(); - - println!("{} {}", normal.paint("Normal"), normal.bold().paint("bold")); - println!("{} {}", Black.paint("Black"), Black.bold().paint("bold")); - println!("{} {}", Red.paint("Red"), Red.bold().paint("bold")); - println!("{} {}", Green.paint("Green"), Green.bold().paint("bold")); - println!("{} {}", Yellow.paint("Yellow"), Yellow.bold().paint("bold")); - println!("{} {}", Blue.paint("Blue"), Blue.bold().paint("bold")); - println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold")); - println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold")); - println!("{} {}", White.paint("White"), White.bold().paint("bold")); -} diff --git a/old_nushell/crates/nu-ansi-term/examples/gradient_colors.rs b/old_nushell/crates/nu-ansi-term/examples/gradient_colors.rs deleted file mode 100644 index 1c9583865..000000000 --- a/old_nushell/crates/nu-ansi-term/examples/gradient_colors.rs +++ /dev/null @@ -1,37 +0,0 @@ -use nu_ansi_term::{build_all_gradient_text, Color, Gradient, Rgb, TargetGround}; - -fn main() { - let text = "lorem ipsum quia dolor sit amet, consectetur, adipisci velit"; - - // a gradient from hex colors - let start = Rgb::from_hex(0x40c9ff); - let end = Rgb::from_hex(0xe81cff); - let grad0 = Gradient::new(start, end); - - // a gradient from color::rgb() - let start = Color::Rgb(64, 201, 255); - let end = Color::Rgb(232, 28, 255); - let gradient = Gradient::from_color_rgb(start, end); - - // a slightly different gradient - let start2 = Color::Rgb(128, 64, 255); - let end2 = Color::Rgb(0, 28, 255); - let gradient2 = Gradient::from_color_rgb(start2, end2); - - // reverse the gradient - let gradient3 = gradient.reverse(); - - let build_fg = gradient.build(text, TargetGround::Foreground); - println!("{}", build_fg); - let build_bg = gradient.build(text, TargetGround::Background); - println!("{}", build_bg); - let bgt = build_all_gradient_text(text, gradient, gradient2); - println!("{}", bgt); - let bgt2 = build_all_gradient_text(text, gradient, gradient3); - println!("{}", bgt2); - - println!( - "{}", - grad0.build("nushell is awesome", TargetGround::Foreground) - ); -} diff --git a/old_nushell/crates/nu-ansi-term/examples/rgb_colors.rs b/old_nushell/crates/nu-ansi-term/examples/rgb_colors.rs deleted file mode 100644 index 4657d401f..000000000 --- a/old_nushell/crates/nu-ansi-term/examples/rgb_colors.rs +++ /dev/null @@ -1,23 +0,0 @@ -extern crate nu_ansi_term; -use nu_ansi_term::{Color, Style}; - -// This example prints out a color gradient in a grid by calculating each -// character’s red, green, and blue components, and using 24-bit color codes -// to display them. - -const WIDTH: i32 = 80; -const HEIGHT: i32 = 24; - -fn main() { - for row in 0..HEIGHT { - for col in 0..WIDTH { - let r = (row * 255 / HEIGHT) as u8; - let g = (col * 255 / WIDTH) as u8; - let b = 128; - - print!("{}", Style::default().on(Color::Rgb(r, g, b)).paint(" ")); - } - - println!(); - } -} diff --git a/old_nushell/crates/nu-ansi-term/src/ansi.rs b/old_nushell/crates/nu-ansi-term/src/ansi.rs deleted file mode 100644 index 8f2454dba..000000000 --- a/old_nushell/crates/nu-ansi-term/src/ansi.rs +++ /dev/null @@ -1,405 +0,0 @@ -#![allow(missing_docs)] -use crate::style::{Color, Style}; -use crate::write::AnyWrite; -use std::fmt; - -impl Style { - /// Write any bytes that go *before* a piece of text to the given writer. - fn write_prefix(&self, f: &mut W) -> Result<(), W::Error> { - // If there are actually no styles here, then don’t write *any* codes - // as the prefix. An empty ANSI code may not affect the terminal - // output at all, but a user may just want a code-free string. - if self.is_plain() { - return Ok(()); - } - - // Write the codes’ prefix, then write numbers, separated by - // semicolons, for each text style we want to apply. - write!(f, "\x1B[")?; - let mut written_anything = false; - - { - let mut write_char = |c| { - if written_anything { - write!(f, ";")?; - } - written_anything = true; - write!(f, "{}", c)?; - Ok(()) - }; - - if self.is_bold { - write_char('1')? - } - if self.is_dimmed { - write_char('2')? - } - if self.is_italic { - write_char('3')? - } - if self.is_underline { - write_char('4')? - } - if self.is_blink { - write_char('5')? - } - if self.is_reverse { - write_char('7')? - } - if self.is_hidden { - write_char('8')? - } - if self.is_strikethrough { - write_char('9')? - } - } - - // The foreground and background colors, if specified, need to be - // handled specially because the number codes are more complicated. - // (see `write_background_code` and `write_foreground_code`) - if let Some(bg) = self.background { - if written_anything { - write!(f, ";")?; - } - written_anything = true; - bg.write_background_code(f)?; - } - - if let Some(fg) = self.foreground { - if written_anything { - write!(f, ";")?; - } - fg.write_foreground_code(f)?; - } - - // All the codes end with an `m`, because reasons. - write!(f, "m")?; - - Ok(()) - } - - /// Write any bytes that go *after* a piece of text to the given writer. - fn write_suffix(&self, f: &mut W) -> Result<(), W::Error> { - if self.is_plain() { - Ok(()) - } else { - write!(f, "{}", RESET) - } - } -} - -/// The code to send to reset all styles and return to `Style::default()`. -pub static RESET: &str = "\x1B[0m"; - -impl Color { - fn write_foreground_code(&self, f: &mut W) -> Result<(), W::Error> { - match self { - Color::Black => write!(f, "30"), - Color::Red => write!(f, "31"), - Color::Green => write!(f, "32"), - Color::Yellow => write!(f, "33"), - Color::Blue => write!(f, "34"), - Color::Purple => write!(f, "35"), - Color::Magenta => write!(f, "35"), - Color::Cyan => write!(f, "36"), - Color::White => write!(f, "37"), - Color::Fixed(num) => write!(f, "38;5;{}", num), - Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", r, g, b), - Color::DarkGray => write!(f, "90"), - Color::LightRed => write!(f, "91"), - Color::LightGreen => write!(f, "92"), - Color::LightYellow => write!(f, "93"), - Color::LightBlue => write!(f, "94"), - Color::LightPurple => write!(f, "95"), - Color::LightMagenta => write!(f, "95"), - Color::LightCyan => write!(f, "96"), - Color::LightGray => write!(f, "97"), - } - } - - fn write_background_code(&self, f: &mut W) -> Result<(), W::Error> { - match self { - Color::Black => write!(f, "40"), - Color::Red => write!(f, "41"), - Color::Green => write!(f, "42"), - Color::Yellow => write!(f, "43"), - Color::Blue => write!(f, "44"), - Color::Purple => write!(f, "45"), - Color::Magenta => write!(f, "45"), - Color::Cyan => write!(f, "46"), - Color::White => write!(f, "47"), - Color::Fixed(num) => write!(f, "48;5;{}", num), - Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", r, g, b), - Color::DarkGray => write!(f, "100"), - Color::LightRed => write!(f, "101"), - Color::LightGreen => write!(f, "102"), - Color::LightYellow => write!(f, "103"), - Color::LightBlue => write!(f, "104"), - Color::LightPurple => write!(f, "105"), - Color::LightMagenta => write!(f, "105"), - Color::LightCyan => write!(f, "106"), - Color::LightGray => write!(f, "107"), - } - } -} - -/// Like `ANSIString`, but only displays the style prefix. -/// -/// This type implements the `Display` trait, meaning it can be written to a -/// `std::fmt` formatting without doing any extra allocation, and written to a -/// string with the `.to_string()` method. For examples, see -/// [`Style::prefix`](struct.Style.html#method.prefix). -#[derive(Clone, Copy, Debug)] -pub struct Prefix(Style); - -/// Like `ANSIString`, but only displays the difference between two -/// styles. -/// -/// This type implements the `Display` trait, meaning it can be written to a -/// `std::fmt` formatting without doing any extra allocation, and written to a -/// string with the `.to_string()` method. For examples, see -/// [`Style::infix`](struct.Style.html#method.infix). -#[derive(Clone, Copy, Debug)] -pub struct Infix(Style, Style); - -/// Like `ANSIString`, but only displays the style suffix. -/// -/// This type implements the `Display` trait, meaning it can be written to a -/// `std::fmt` formatting without doing any extra allocation, and written to a -/// string with the `.to_string()` method. For examples, see -/// [`Style::suffix`](struct.Style.html#method.suffix). -#[derive(Clone, Copy, Debug)] -pub struct Suffix(Style); - -impl Style { - /// The prefix bytes for this style. These are the bytes that tell the - /// terminal to use a different color or font style. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::{Style, Color::Blue}; - /// - /// let style = Style::default().bold(); - /// assert_eq!("\x1b[1m", - /// style.prefix().to_string()); - /// - /// let style = Blue.bold(); - /// assert_eq!("\x1b[1;34m", - /// style.prefix().to_string()); - /// - /// let style = Style::default(); - /// assert_eq!("", - /// style.prefix().to_string()); - /// ``` - pub fn prefix(self) -> Prefix { - Prefix(self) - } - - /// The infix bytes between this style and `next` style. These are the bytes - /// that tell the terminal to change the style to `next`. These may include - /// a reset followed by the next color and style, depending on the two styles. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::{Style, Color::Green}; - /// - /// let style = Style::default().bold(); - /// assert_eq!("\x1b[32m", - /// style.infix(Green.bold()).to_string()); - /// - /// let style = Green.normal(); - /// assert_eq!("\x1b[1m", - /// style.infix(Green.bold()).to_string()); - /// - /// let style = Style::default(); - /// assert_eq!("", - /// style.infix(style).to_string()); - /// ``` - pub fn infix(self, next: Style) -> Infix { - Infix(self, next) - } - - /// The suffix for this style. These are the bytes that tell the terminal - /// to reset back to its normal color and font style. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::{Style, Color::Green}; - /// - /// let style = Style::default().bold(); - /// assert_eq!("\x1b[0m", - /// style.suffix().to_string()); - /// - /// let style = Green.normal().bold(); - /// assert_eq!("\x1b[0m", - /// style.suffix().to_string()); - /// - /// let style = Style::default(); - /// assert_eq!("", - /// style.suffix().to_string()); - /// ``` - pub fn suffix(self) -> Suffix { - Suffix(self) - } -} - -impl Color { - /// The prefix bytes for this color as a `Style`. These are the bytes - /// that tell the terminal to use a different color or font style. - /// - /// See also [`Style::prefix`](struct.Style.html#method.prefix). - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color::Green; - /// - /// assert_eq!("\x1b[0m", - /// Green.suffix().to_string()); - /// ``` - pub fn prefix(self) -> Prefix { - Prefix(self.normal()) - } - - /// The infix bytes between this color and `next` color. These are the bytes - /// that tell the terminal to use the `next` color, or to do nothing if - /// the two colors are equal. - /// - /// See also [`Style::infix`](struct.Style.html#method.infix). - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color::{Red, Yellow}; - /// - /// assert_eq!("\x1b[33m", - /// Red.infix(Yellow).to_string()); - /// ``` - pub fn infix(self, next: Color) -> Infix { - Infix(self.normal(), next.normal()) - } - - /// The suffix for this color as a `Style`. These are the bytes that - /// tell the terminal to reset back to its normal color and font style. - /// - /// See also [`Style::suffix`](struct.Style.html#method.suffix). - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color::Purple; - /// - /// assert_eq!("\x1b[0m", - /// Purple.suffix().to_string()); - /// ``` - pub fn suffix(self) -> Suffix { - Suffix(self.normal()) - } -} - -impl fmt::Display for Prefix { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let f: &mut dyn fmt::Write = f; - self.0.write_prefix(f) - } -} - -impl fmt::Display for Infix { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use crate::difference::Difference; - - match Difference::between(&self.0, &self.1) { - Difference::ExtraStyles(style) => { - let f: &mut dyn fmt::Write = f; - style.write_prefix(f) - } - Difference::Reset => { - let f: &mut dyn fmt::Write = f; - write!(f, "{}{}", RESET, self.1.prefix()) - } - Difference::Empty => { - Ok(()) // nothing to write - } - } - } -} - -impl fmt::Display for Suffix { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let f: &mut dyn fmt::Write = f; - self.0.write_suffix(f) - } -} - -#[cfg(test)] -mod test { - use crate::style::Color::*; - use crate::style::Style; - - macro_rules! test { - ($name: ident: $style: expr; $input: expr => $result: expr) => { - #[test] - fn $name() { - assert_eq!($style.paint($input).to_string(), $result.to_string()); - - let mut v = Vec::new(); - $style.paint($input.as_bytes()).write_to(&mut v).unwrap(); - assert_eq!(v.as_slice(), $result.as_bytes()); - } - }; - } - - test!(plain: Style::default(); "text/plain" => "text/plain"); - test!(red: Red; "hi" => "\x1B[31mhi\x1B[0m"); - test!(black: Black.normal(); "hi" => "\x1B[30mhi\x1B[0m"); - test!(yellow_bold: Yellow.bold(); "hi" => "\x1B[1;33mhi\x1B[0m"); - test!(yellow_bold_2: Yellow.normal().bold(); "hi" => "\x1B[1;33mhi\x1B[0m"); - test!(blue_underline: Blue.underline(); "hi" => "\x1B[4;34mhi\x1B[0m"); - test!(green_bold_ul: Green.bold().underline(); "hi" => "\x1B[1;4;32mhi\x1B[0m"); - test!(green_bold_ul_2: Green.underline().bold(); "hi" => "\x1B[1;4;32mhi\x1B[0m"); - test!(purple_on_white: Purple.on(White); "hi" => "\x1B[47;35mhi\x1B[0m"); - test!(purple_on_white_2: Purple.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m"); - test!(yellow_on_blue: Style::new().on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m"); - test!(magenta_on_white: Magenta.on(White); "hi" => "\x1B[47;35mhi\x1B[0m"); - test!(magenta_on_white_2: Magenta.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m"); - test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m"); - test!(cyan_bold_on_white: Cyan.bold().on(White); "hi" => "\x1B[1;47;36mhi\x1B[0m"); - test!(cyan_ul_on_white: Cyan.underline().on(White); "hi" => "\x1B[4;47;36mhi\x1B[0m"); - test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m"); - test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m"); - test!(fixed: Fixed(100); "hi" => "\x1B[38;5;100mhi\x1B[0m"); - test!(fixed_on_purple: Fixed(100).on(Purple); "hi" => "\x1B[45;38;5;100mhi\x1B[0m"); - test!(fixed_on_fixed: Fixed(100).on(Fixed(200)); "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m"); - test!(rgb: Rgb(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m"); - test!(rgb_on_blue: Rgb(70,130,180).on(Blue); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m"); - test!(blue_on_rgb: Blue.on(Rgb(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m"); - test!(rgb_on_rgb: Rgb(70,130,180).on(Rgb(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m"); - test!(bold: Style::new().bold(); "hi" => "\x1B[1mhi\x1B[0m"); - test!(underline: Style::new().underline(); "hi" => "\x1B[4mhi\x1B[0m"); - test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m"); - test!(dimmed: Style::new().dimmed(); "hi" => "\x1B[2mhi\x1B[0m"); - test!(italic: Style::new().italic(); "hi" => "\x1B[3mhi\x1B[0m"); - test!(blink: Style::new().blink(); "hi" => "\x1B[5mhi\x1B[0m"); - test!(reverse: Style::new().reverse(); "hi" => "\x1B[7mhi\x1B[0m"); - test!(hidden: Style::new().hidden(); "hi" => "\x1B[8mhi\x1B[0m"); - test!(stricken: Style::new().strikethrough(); "hi" => "\x1B[9mhi\x1B[0m"); - test!(lr_on_lr: LightRed.on(LightRed); "hi" => "\x1B[101;91mhi\x1B[0m"); - - #[test] - fn test_infix() { - assert_eq!( - Style::new().dimmed().infix(Style::new()).to_string(), - "\x1B[0m" - ); - assert_eq!( - White.dimmed().infix(White.normal()).to_string(), - "\x1B[0m\x1B[37m" - ); - assert_eq!(White.normal().infix(White.bold()).to_string(), "\x1B[1m"); - assert_eq!(White.normal().infix(Blue.normal()).to_string(), "\x1B[34m"); - assert_eq!(Blue.bold().infix(Blue.bold()).to_string(), ""); - } -} diff --git a/old_nushell/crates/nu-ansi-term/src/debug.rs b/old_nushell/crates/nu-ansi-term/src/debug.rs deleted file mode 100644 index 1dcde52be..000000000 --- a/old_nushell/crates/nu-ansi-term/src/debug.rs +++ /dev/null @@ -1,152 +0,0 @@ -use crate::style::Style; -use std::fmt; - -/// Styles have a special `Debug` implementation that only shows the fields that -/// are set. Fields that haven’t been touched aren’t included in the output. -/// -/// This behaviour gets bypassed when using the alternate formatting mode -/// `format!("{:#?}")`. -/// -/// use nu_ansi_term::Color::{Red, Blue}; -/// assert_eq!("Style { fg(Red), on(Blue), bold, italic }", -/// format!("{:?}", Red.on(Blue).bold().italic())); -impl fmt::Debug for Style { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - if fmt.alternate() { - fmt.debug_struct("Style") - .field("foreground", &self.foreground) - .field("background", &self.background) - .field("blink", &self.is_blink) - .field("bold", &self.is_bold) - .field("dimmed", &self.is_dimmed) - .field("hidden", &self.is_hidden) - .field("italic", &self.is_italic) - .field("reverse", &self.is_reverse) - .field("strikethrough", &self.is_strikethrough) - .field("underline", &self.is_underline) - .finish() - } else if self.is_plain() { - fmt.write_str("Style {}") - } else { - fmt.write_str("Style { ")?; - - let mut written_anything = false; - - if let Some(fg) = self.foreground { - if written_anything { - fmt.write_str(", ")? - } - written_anything = true; - write!(fmt, "fg({:?})", fg)? - } - - if let Some(bg) = self.background { - if written_anything { - fmt.write_str(", ")? - } - written_anything = true; - write!(fmt, "on({:?})", bg)? - } - - { - let mut write_flag = |name| { - if written_anything { - fmt.write_str(", ")? - } - written_anything = true; - fmt.write_str(name) - }; - - if self.is_blink { - write_flag("blink")? - } - if self.is_bold { - write_flag("bold")? - } - if self.is_dimmed { - write_flag("dimmed")? - } - if self.is_hidden { - write_flag("hidden")? - } - if self.is_italic { - write_flag("italic")? - } - if self.is_reverse { - write_flag("reverse")? - } - if self.is_strikethrough { - write_flag("strikethrough")? - } - if self.is_underline { - write_flag("underline")? - } - } - - write!(fmt, " }}") - } - } -} - -#[cfg(test)] -mod test { - use crate::style::Color::*; - use crate::style::Style; - - fn style() -> Style { - Style::new() - } - - macro_rules! test { - ($name: ident: $obj: expr => $result: expr) => { - #[test] - fn $name() { - assert_eq!($result, format!("{:?}", $obj)); - } - }; - } - - test!(empty: style() => "Style {}"); - test!(bold: style().bold() => "Style { bold }"); - test!(italic: style().italic() => "Style { italic }"); - test!(both: style().bold().italic() => "Style { bold, italic }"); - - test!(red: Red.normal() => "Style { fg(Red) }"); - test!(redblue: Red.normal().on(Rgb(3, 2, 4)) => "Style { fg(Red), on(Rgb(3, 2, 4)) }"); - - test!(everything: - Red.on(Blue).blink().bold().dimmed().hidden().italic().reverse().strikethrough().underline() => - "Style { fg(Red), on(Blue), blink, bold, dimmed, hidden, italic, reverse, strikethrough, underline }"); - - #[test] - fn long_and_detailed() { - extern crate regex; - let expected_debug = "Style { fg(Blue), bold }"; - let expected_pretty_repat = r##"(?x) - Style\s+\{\s+ - foreground:\s+Some\(\s+ - Blue,?\s+ - \),\s+ - background:\s+None,\s+ - blink:\s+false,\s+ - bold:\s+true,\s+ - dimmed:\s+false,\s+ - hidden:\s+false,\s+ - italic:\s+false,\s+ - reverse:\s+false,\s+ - strikethrough:\s+ - false,\s+ - underline:\s+false,?\s+ - \}"##; - let re = regex::Regex::new(expected_pretty_repat).unwrap(); - - let style = Blue.bold(); - let style_fmt_debug = format!("{:?}", style); - let style_fmt_pretty = format!("{:#?}", style); - println!("style_fmt_debug:\n{}", style_fmt_debug); - println!("style_fmt_pretty:\n{}", style_fmt_pretty); - - assert_eq!(expected_debug, style_fmt_debug); - assert!(re.is_match(&style_fmt_pretty)); - } -} diff --git a/old_nushell/crates/nu-ansi-term/src/difference.rs b/old_nushell/crates/nu-ansi-term/src/difference.rs deleted file mode 100644 index beee8ea25..000000000 --- a/old_nushell/crates/nu-ansi-term/src/difference.rs +++ /dev/null @@ -1,174 +0,0 @@ -use super::Style; - -/// When printing out one colored string followed by another, use one of -/// these rules to figure out which *extra* control codes need to be sent. -#[derive(PartialEq, Clone, Copy, Debug)] -pub enum Difference { - /// Print out the control codes specified by this style to end up looking - /// like the second string's styles. - ExtraStyles(Style), - - /// Converting between these two is impossible, so just send a reset - /// command and then the second string's styles. - Reset, - - /// The before style is exactly the same as the after style, so no further - /// control codes need to be printed. - Empty, -} - -impl Difference { - /// Compute the 'style difference' required to turn an existing style into - /// the given, second style. - /// - /// For example, to turn green text into green bold text, it's redundant - /// to write a reset command then a second green+bold command, instead of - /// just writing one bold command. This method should see that both styles - /// use the foreground color green, and reduce it to a single command. - /// - /// This method returns an enum value because it's not actually always - /// possible to turn one style into another: for example, text could be - /// made bold and underlined, but you can't remove the bold property - /// without also removing the underline property. So when this has to - /// happen, this function returns None, meaning that the entire set of - /// styles should be reset and begun again. - pub fn between(first: &Style, next: &Style) -> Difference { - use self::Difference::*; - - // XXX(Havvy): This algorithm is kind of hard to replicate without - // having the Plain/Foreground enum variants, so I'm just leaving - // it commented out for now, and defaulting to Reset. - - if first == next { - return Empty; - } - - // Cannot un-bold, so must Reset. - if first.is_bold && !next.is_bold { - return Reset; - } - - if first.is_dimmed && !next.is_dimmed { - return Reset; - } - - if first.is_italic && !next.is_italic { - return Reset; - } - - // Cannot un-underline, so must Reset. - if first.is_underline && !next.is_underline { - return Reset; - } - - if first.is_blink && !next.is_blink { - return Reset; - } - - if first.is_reverse && !next.is_reverse { - return Reset; - } - - if first.is_hidden && !next.is_hidden { - return Reset; - } - - if first.is_strikethrough && !next.is_strikethrough { - return Reset; - } - - // Cannot go from foreground to no foreground, so must Reset. - if first.foreground.is_some() && next.foreground.is_none() { - return Reset; - } - - // Cannot go from background to no background, so must Reset. - if first.background.is_some() && next.background.is_none() { - return Reset; - } - - let mut extra_styles = Style::default(); - - if first.is_bold != next.is_bold { - extra_styles.is_bold = true; - } - - if first.is_dimmed != next.is_dimmed { - extra_styles.is_dimmed = true; - } - - if first.is_italic != next.is_italic { - extra_styles.is_italic = true; - } - - if first.is_underline != next.is_underline { - extra_styles.is_underline = true; - } - - if first.is_blink != next.is_blink { - extra_styles.is_blink = true; - } - - if first.is_reverse != next.is_reverse { - extra_styles.is_reverse = true; - } - - if first.is_hidden != next.is_hidden { - extra_styles.is_hidden = true; - } - - if first.is_strikethrough != next.is_strikethrough { - extra_styles.is_strikethrough = true; - } - - if first.foreground != next.foreground { - extra_styles.foreground = next.foreground; - } - - if first.background != next.background { - extra_styles.background = next.background; - } - - ExtraStyles(extra_styles) - } -} - -#[cfg(test)] -mod test { - use super::Difference::*; - use super::*; - use crate::style::Color::*; - use crate::style::Style; - - fn style() -> Style { - Style::new() - } - - macro_rules! test { - ($name: ident: $first: expr; $next: expr => $result: expr) => { - #[test] - fn $name() { - assert_eq!($result, Difference::between(&$first, &$next)); - } - }; - } - - test!(nothing: Green.normal(); Green.normal() => Empty); - test!(uppercase: Green.normal(); Green.bold() => ExtraStyles(style().bold())); - test!(lowercase: Green.bold(); Green.normal() => Reset); - test!(nothing2: Green.bold(); Green.bold() => Empty); - - test!(color_change: Red.normal(); Blue.normal() => ExtraStyles(Blue.normal())); - - test!(addition_of_blink: style(); style().blink() => ExtraStyles(style().blink())); - test!(addition_of_dimmed: style(); style().dimmed() => ExtraStyles(style().dimmed())); - test!(addition_of_hidden: style(); style().hidden() => ExtraStyles(style().hidden())); - test!(addition_of_reverse: style(); style().reverse() => ExtraStyles(style().reverse())); - test!(addition_of_strikethrough: style(); style().strikethrough() => ExtraStyles(style().strikethrough())); - - test!(removal_of_strikethrough: style().strikethrough(); style() => Reset); - test!(removal_of_reverse: style().reverse(); style() => Reset); - test!(removal_of_hidden: style().hidden(); style() => Reset); - test!(removal_of_dimmed: style().dimmed(); style() => Reset); - test!(removal_of_blink: style().blink(); style() => Reset); -} diff --git a/old_nushell/crates/nu-ansi-term/src/display.rs b/old_nushell/crates/nu-ansi-term/src/display.rs deleted file mode 100644 index db5221f35..000000000 --- a/old_nushell/crates/nu-ansi-term/src/display.rs +++ /dev/null @@ -1,303 +0,0 @@ -use crate::ansi::RESET; -use crate::difference::Difference; -use crate::style::{Color, Style}; -use crate::write::AnyWrite; -use std::borrow::Cow; -use std::fmt; -use std::io; -use std::ops::Deref; - -/// An `ANSIGenericString` includes a generic string type and a `Style` to -/// display that string. `ANSIString` and `ANSIByteString` are aliases for -/// this type on `str` and `\[u8]`, respectively. -#[derive(PartialEq, Debug)] -pub struct AnsiGenericString<'a, S: 'a + ToOwned + ?Sized> -where - ::Owned: fmt::Debug, -{ - style: Style, - string: Cow<'a, S>, -} - -/// Cloning an `ANSIGenericString` will clone its underlying string. -/// -/// # Examples -/// -/// ``` -/// use nu_ansi_term::ANSIString; -/// -/// let plain_string = ANSIString::from("a plain string"); -/// let clone_string = plain_string.clone(); -/// assert_eq!(clone_string, plain_string); -/// ``` -impl<'a, S: 'a + ToOwned + ?Sized> Clone for AnsiGenericString<'a, S> -where - ::Owned: fmt::Debug, -{ - fn clone(&self) -> AnsiGenericString<'a, S> { - AnsiGenericString { - style: self.style, - string: self.string.clone(), - } - } -} - -// You might think that the hand-written Clone impl above is the same as the -// one that gets generated with #[derive]. But it’s not *quite* the same! -// -// `str` is not Clone, and the derived Clone implementation puts a Clone -// constraint on the S type parameter (generated using --pretty=expanded): -// -// ↓_________________↓ -// impl <'a, S: ::std::clone::Clone + 'a + ToOwned + ?Sized> ::std::clone::Clone -// for ANSIGenericString<'a, S> where -// ::Owned: fmt::Debug { ... } -// -// This resulted in compile errors when you tried to derive Clone on a type -// that used it: -// -// #[derive(PartialEq, Debug, Clone, Default)] -// pub struct TextCellContents(Vec>); -// ^^^^^^^^^^^^^^^^^^^^^^^^^ -// error[E0277]: the trait `std::clone::Clone` is not implemented for `str` -// -// The hand-written impl above can ignore that constraint and still compile. - -/// An ANSI String is a string coupled with the `Style` to display it -/// in a terminal. -/// -/// Although not technically a string itself, it can be turned into -/// one with the `to_string` method. -/// -/// # Examples -/// -/// ``` -/// use nu_ansi_term::ANSIString; -/// use nu_ansi_term::Color::Red; -/// -/// let red_string = Red.paint("a red string"); -/// println!("{}", red_string); -/// ``` -/// -/// ``` -/// use nu_ansi_term::ANSIString; -/// -/// let plain_string = ANSIString::from("a plain string"); -/// assert_eq!(&*plain_string, "a plain string"); -/// ``` -pub type AnsiString<'a> = AnsiGenericString<'a, str>; - -/// An `AnsiByteString` represents a formatted series of bytes. Use -/// `AnsiByteString` when styling text with an unknown encoding. -pub type AnsiByteString<'a> = AnsiGenericString<'a, [u8]>; - -impl<'a, I, S: 'a + ToOwned + ?Sized> From for AnsiGenericString<'a, S> -where - I: Into>, - ::Owned: fmt::Debug, -{ - fn from(input: I) -> AnsiGenericString<'a, S> { - AnsiGenericString { - string: input.into(), - style: Style::default(), - } - } -} - -impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S> -where - ::Owned: fmt::Debug, -{ - /// Directly access the style - pub fn style_ref(&self) -> &Style { - &self.style - } - - /// Directly access the style mutably - pub fn style_ref_mut(&mut self) -> &mut Style { - &mut self.style - } -} - -impl<'a, S: 'a + ToOwned + ?Sized> Deref for AnsiGenericString<'a, S> -where - ::Owned: fmt::Debug, -{ - type Target = S; - - fn deref(&self) -> &S { - self.string.deref() - } -} - -/// A set of `AnsiGenericStrings`s collected together, in order to be -/// written with a minimum of control characters. -#[derive(Debug, PartialEq)] -pub struct AnsiGenericStrings<'a, S: 'a + ToOwned + ?Sized>(pub &'a [AnsiGenericString<'a, S>]) -where - ::Owned: fmt::Debug, - S: PartialEq; - -/// A set of `AnsiString`s collected together, in order to be written with a -/// minimum of control characters. -pub type AnsiStrings<'a> = AnsiGenericStrings<'a, str>; - -/// A function to construct an `AnsiStrings` instance. -#[allow(non_snake_case)] -pub fn AnsiStrings<'a>(arg: &'a [AnsiString<'a>]) -> AnsiStrings<'a> { - AnsiGenericStrings(arg) -} - -/// A set of `AnsiByteString`s collected together, in order to be -/// written with a minimum of control characters. -pub type AnsiByteStrings<'a> = AnsiGenericStrings<'a, [u8]>; - -/// A function to construct an `ANSIByteStrings` instance. -#[allow(non_snake_case)] -pub fn ANSIByteStrings<'a>(arg: &'a [AnsiByteString<'a>]) -> AnsiByteStrings<'a> { - AnsiGenericStrings(arg) -} - -// ---- paint functions ---- - -impl Style { - /// Paints the given text with this color, returning an ANSI string. - #[must_use] - pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S> - where - I: Into>, - ::Owned: fmt::Debug, - { - AnsiGenericString { - string: input.into(), - style: self, - } - } -} - -impl Color { - /// Paints the given text with this color, returning an ANSI string. - /// This is a short-cut so you don’t have to use `Blue.normal()` just - /// to get blue text. - /// - /// ``` - /// use nu_ansi_term::Color::Blue; - /// println!("{}", Blue.paint("da ba dee")); - /// ``` - #[must_use] - pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S> - where - I: Into>, - ::Owned: fmt::Debug, - { - AnsiGenericString { - string: input.into(), - style: self.normal(), - } - } -} - -// ---- writers for individual ANSI strings ---- - -impl<'a> fmt::Display for AnsiString<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let w: &mut dyn fmt::Write = f; - self.write_to_any(w) - } -} - -impl<'a> AnsiByteString<'a> { - /// Write an `ANSIByteString` to an `io::Write`. This writes the escape - /// sequences for the associated `Style` around the bytes. - pub fn write_to(&self, w: &mut W) -> io::Result<()> { - let w: &mut dyn io::Write = w; - self.write_to_any(w) - } -} - -impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S> -where - ::Owned: fmt::Debug, - &'a S: AsRef<[u8]>, -{ - fn write_to_any + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> { - write!(w, "{}", self.style.prefix())?; - w.write_str(self.string.as_ref())?; - write!(w, "{}", self.style.suffix()) - } -} - -// ---- writers for combined ANSI strings ---- - -impl<'a> fmt::Display for AnsiStrings<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let f: &mut dyn fmt::Write = f; - self.write_to_any(f) - } -} - -impl<'a> AnsiByteStrings<'a> { - /// Write `ANSIByteStrings` to an `io::Write`. This writes the minimal - /// escape sequences for the associated `Style`s around each set of - /// bytes. - pub fn write_to(&self, w: &mut W) -> io::Result<()> { - let w: &mut dyn io::Write = w; - self.write_to_any(w) - } -} - -impl<'a, S: 'a + ToOwned + ?Sized + PartialEq> AnsiGenericStrings<'a, S> -where - ::Owned: fmt::Debug, - &'a S: AsRef<[u8]>, -{ - fn write_to_any + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> { - use self::Difference::*; - - let first = match self.0.first() { - None => return Ok(()), - Some(f) => f, - }; - - write!(w, "{}", first.style.prefix())?; - w.write_str(first.string.as_ref())?; - - for window in self.0.windows(2) { - match Difference::between(&window[0].style, &window[1].style) { - ExtraStyles(style) => write!(w, "{}", style.prefix())?, - Reset => write!(w, "{}{}", RESET, window[1].style.prefix())?, - Empty => { /* Do nothing! */ } - } - - w.write_str(&window[1].string)?; - } - - // Write the final reset string after all of the ANSIStrings have been - // written, *except* if the last one has no styles, because it would - // have already been written by this point. - if let Some(last) = self.0.last() { - if !last.style.is_plain() { - write!(w, "{}", RESET)?; - } - } - - Ok(()) - } -} - -// ---- tests ---- - -#[cfg(test)] -mod tests { - pub use super::super::AnsiStrings; - pub use crate::style::Color::*; - pub use crate::style::Style; - - #[test] - fn no_control_codes_for_plain() { - let one = Style::default().paint("one"); - let two = Style::default().paint("two"); - let output = AnsiStrings(&[one, two]).to_string(); - assert_eq!(output, "onetwo"); - } -} diff --git a/old_nushell/crates/nu-ansi-term/src/gradient.rs b/old_nushell/crates/nu-ansi-term/src/gradient.rs deleted file mode 100644 index a0d94c8cd..000000000 --- a/old_nushell/crates/nu-ansi-term/src/gradient.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::{rgb::Rgb, Color}; - -/// Linear color gradient between two color stops -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Gradient { - /// Start Color of Gradient - pub start: Rgb, - - /// End Color of Gradient - pub end: Rgb, -} - -impl Gradient { - /// Creates a new [Gradient] with two [Rgb] colors, `start` and `end` - #[inline] - pub const fn new(start: Rgb, end: Rgb) -> Self { - Self { start, end } - } - pub const fn from_color_rgb(start: Color, end: Color) -> Self { - let start_grad = match start { - Color::Rgb(r, g, b) => Rgb { r, g, b }, - _ => Rgb { r: 0, g: 0, b: 0 }, - }; - let end_grad = match end { - Color::Rgb(r, g, b) => Rgb { r, g, b }, - _ => Rgb { r: 0, g: 0, b: 0 }, - }; - - Self { - start: start_grad, - end: end_grad, - } - } - - /// Computes the [Rgb] color between `start` and `end` for `t` - pub fn at(&self, t: f32) -> Rgb { - self.start.lerp(self.end, t) - } - - /// Returns the reverse of `self` - #[inline] - pub const fn reverse(&self) -> Self { - Self::new(self.end, self.start) - } - - #[allow(dead_code)] - pub fn build(&self, text: &str, target: TargetGround) -> String { - let delta = 1.0 / text.len() as f32; - let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| { - let temp = format!( - "\x1B[{}m{}", - self.at(i as f32 * delta).ansi_color_code(target), - c - ); - acc.push_str(&temp); - acc - }); - - result.push_str("\x1B[0m"); - result - } -} - -#[allow(dead_code)] -pub fn build_all_gradient_text(text: &str, foreground: Gradient, background: Gradient) -> String { - let delta = 1.0 / text.len() as f32; - let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| { - let step = i as f32 * delta; - let temp = format!( - "\x1B[{};{}m{}", - foreground - .at(step) - .ansi_color_code(TargetGround::Foreground), - background - .at(step) - .ansi_color_code(TargetGround::Background), - c - ); - acc.push_str(&temp); - acc - }); - - result.push_str("\x1B[0m"); - result -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum TargetGround { - Foreground, - Background, -} - -impl TargetGround { - #[inline] - pub const fn code(&self) -> u8 { - match self { - Self::Foreground => 30, - Self::Background => 40, - } - } -} - -pub trait ANSIColorCode { - fn ansi_color_code(&self, target: TargetGround) -> String; -} diff --git a/old_nushell/crates/nu-ansi-term/src/lib.rs b/old_nushell/crates/nu-ansi-term/src/lib.rs deleted file mode 100644 index d33b9bb52..000000000 --- a/old_nushell/crates/nu-ansi-term/src/lib.rs +++ /dev/null @@ -1,272 +0,0 @@ -//! This is a library for controlling colors and formatting, such as -//! red bold text or blue underlined text, on ANSI terminals. -//! -//! -//! ## Basic usage -//! -//! There are three main types in this crate that you need to be -//! concerned with: [`ANSIString`], [`Style`], and [`Color`]. -//! -//! A `Style` holds stylistic information: foreground and background colors, -//! whether the text should be bold, or blinking, or other properties. The -//! [`Color`] enum represents the available colors. And an [`ANSIString`] is a -//! string paired with a [`Style`]. -//! -//! [`Color`] is also available as an alias to `Color`. -//! -//! To format a string, call the `paint` method on a `Style` or a `Color`, -//! passing in the string you want to format as the argument. For example, -//! here’s how to get some red text: -//! -//! ``` -//! use nu_ansi_term::Color::Red; -//! -//! println!("This is in red: {}", Red.paint("a red string")); -//! ``` -//! -//! It’s important to note that the `paint` method does *not* actually return a -//! string with the ANSI control characters surrounding it. Instead, it returns -//! an [`ANSIString`] value that has a [`Display`] implementation that, when -//! formatted, returns the characters. This allows strings to be printed with a -//! minimum of [`String`] allocations being performed behind the scenes. -//! -//! If you *do* want to get at the escape codes, then you can convert the -//! [`ANSIString`] to a string as you would any other `Display` value: -//! -//! ``` -//! use nu_ansi_term::Color::Red; -//! -//! let red_string = Red.paint("a red string").to_string(); -//! ``` -//! -//! -//! ## Bold, underline, background, and other styles -//! -//! For anything more complex than plain foreground color changes, you need to -//! construct `Style` values themselves, rather than beginning with a `Color`. -//! You can do this by chaining methods based on a new `Style`, created with -//! [`Style::new()`]. Each method creates a new style that has that specific -//! property set. For example: -//! -//! ``` -//! use nu_ansi_term::Style; -//! -//! println!("How about some {} and {}?", -//! Style::new().bold().paint("bold"), -//! Style::new().underline().paint("underline")); -//! ``` -//! -//! For brevity, these methods have also been implemented for `Color` values, -//! so you can give your styles a foreground color without having to begin with -//! an empty `Style` value: -//! -//! ``` -//! use nu_ansi_term::Color::{Blue, Yellow}; -//! -//! println!("Demonstrating {} and {}!", -//! Blue.bold().paint("blue bold"), -//! Yellow.underline().paint("yellow underline")); -//! -//! println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!")); -//! ``` -//! -//! The complete list of styles you can use are: [`bold`], [`dimmed`], [`italic`], -//! [`underline`], [`blink`], [`reverse`], [`hidden`], [`strikethrough`], and [`on`] for -//! background colors. -//! -//! In some cases, you may find it easier to change the foreground on an -//! existing `Style` rather than starting from the appropriate `Color`. -//! You can do this using the [`fg`] method: -//! -//! ``` -//! use nu_ansi_term::Style; -//! use nu_ansi_term::Color::{Blue, Cyan, Yellow}; -//! -//! println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!")); -//! println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!")); -//! ``` -//! -//! You can turn a `Color` into a `Style` with the [`normal`] method. -//! This will produce the exact same `ANSIString` as if you just used the -//! `paint` method on the `Color` directly, but it’s useful in certain cases: -//! for example, you may have a method that returns `Styles`, and need to -//! represent both the “red bold” and “red, but not bold” styles with values of -//! the same type. The `Style` struct also has a [`Default`] implementation if you -//! want to have a style with *nothing* set. -//! -//! ``` -//! use nu_ansi_term::Style; -//! use nu_ansi_term::Color::Red; -//! -//! Red.normal().paint("yet another red string"); -//! Style::default().paint("a completely regular string"); -//! ``` -//! -//! -//! ## Extended colors -//! -//! You can access the extended range of 256 colors by using the `Color::Fixed` -//! variant, which takes an argument of the color number to use. This can be -//! included wherever you would use a `Color`: -//! -//! ``` -//! use nu_ansi_term::Color::Fixed; -//! -//! Fixed(134).paint("A sort of light purple"); -//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup"); -//! ``` -//! -//! The first sixteen of these values are the same as the normal and bold -//! standard color variants. There’s nothing stopping you from using these as -//! `Fixed` colors instead, but there’s nothing to be gained by doing so -//! either. -//! -//! You can also access full 24-bit color by using the `Color::Rgb` variant, -//! which takes separate `u8` arguments for red, green, and blue: -//! -//! ``` -//! use nu_ansi_term::Color::Rgb; -//! -//! Rgb(70, 130, 180).paint("Steel blue"); -//! ``` -//! -//! ## Combining successive colored strings -//! -//! The benefit of writing ANSI escape codes to the terminal is that they -//! *stack*: you do not need to end every colored string with a reset code if -//! the text that follows it is of a similar style. For example, if you want to -//! have some blue text followed by some blue bold text, it’s possible to send -//! the ANSI code for blue, followed by the ANSI code for bold, and finishing -//! with a reset code without having to have an extra one between the two -//! strings. -//! -//! This crate can optimise the ANSI codes that get printed in situations like -//! this, making life easier for your terminal renderer. The [`ANSIStrings`] -//! type takes a slice of several [`ANSIString`] values, and will iterate over -//! each of them, printing only the codes for the styles that need to be updated -//! as part of its formatting routine. -//! -//! The following code snippet uses this to enclose a binary number displayed in -//! red bold text inside some red, but not bold, brackets: -//! -//! ``` -//! use nu_ansi_term::Color::Red; -//! use nu_ansi_term::{ANSIString, ANSIStrings}; -//! -//! let some_value = format!("{:b}", 42); -//! let strings: &[ANSIString<'static>] = &[ -//! Red.paint("["), -//! Red.bold().paint(some_value), -//! Red.paint("]"), -//! ]; -//! -//! println!("Value: {}", ANSIStrings(strings)); -//! ``` -//! -//! There are several things to note here. Firstly, the [`paint`] method can take -//! *either* an owned [`String`] or a borrowed [`&str`]. Internally, an [`ANSIString`] -//! holds a copy-on-write ([`Cow`]) string value to deal with both owned and -//! borrowed strings at the same time. This is used here to display a `String`, -//! the result of the `format!` call, using the same mechanism as some -//! statically-available `&str` slices. Secondly, that the [`ANSIStrings`] value -//! works in the same way as its singular counterpart, with a [`Display`] -//! implementation that only performs the formatting when required. -//! -//! ## Byte strings -//! -//! This library also supports formatting `\[u8]` byte strings; this supports -//! applications working with text in an unknown encoding. [`Style`] and -//! [`Color`] support painting `\[u8]` values, resulting in an [`ANSIByteString`]. -//! This type does not implement [`Display`], as it may not contain UTF-8, but -//! it does provide a method [`write_to`] to write the result to any value that -//! implements [`Write`]: -//! -//! ``` -//! use nu_ansi_term::Color::Green; -//! -//! Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap(); -//! ``` -//! -//! Similarly, the type [`ANSIByteStrings`] supports writing a list of -//! [`ANSIByteString`] values with minimal escape sequences: -//! -//! ``` -//! use nu_ansi_term::Color::Green; -//! use nu_ansi_term::ANSIByteStrings; -//! -//! ANSIByteStrings(&[ -//! Green.paint("user data 1\n".as_bytes()), -//! Green.bold().paint("user data 2\n".as_bytes()), -//! ]).write_to(&mut std::io::stdout()).unwrap(); -//! ``` -//! -//! [`Cow`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html -//! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html -//! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html -//! [`String`]: https://doc.rust-lang.org/std/string/struct.String.html -//! [`&str`]: https://doc.rust-lang.org/std/primitive.str.html -//! [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html -//! [`Style`]: struct.Style.html -//! [`Style::new()`]: struct.Style.html#method.new -//! [`Color`]: enum.Color.html -//! [`Color`]: enum.Color.html -//! [`ANSIString`]: type.ANSIString.html -//! [`ANSIStrings`]: type.ANSIStrings.html -//! [`ANSIByteString`]: type.ANSIByteString.html -//! [`ANSIByteStrings`]: type.ANSIByteStrings.html -//! [`write_to`]: type.ANSIByteString.html#method.write_to -//! [`paint`]: type.ANSIByteString.html#method.write_to -//! [`normal`]: enum.Color.html#method.normal -//! -//! [`bold`]: struct.Style.html#method.bold -//! [`dimmed`]: struct.Style.html#method.dimmed -//! [`italic`]: struct.Style.html#method.italic -//! [`underline`]: struct.Style.html#method.underline -//! [`blink`]: struct.Style.html#method.blink -//! [`reverse`]: struct.Style.html#method.reverse -//! [`hidden`]: struct.Style.html#method.hidden -//! [`strikethrough`]: struct.Style.html#method.strikethrough -//! [`fg`]: struct.Style.html#method.fg -//! [`on`]: struct.Style.html#method.on - -#![crate_name = "nu_ansi_term"] -#![crate_type = "rlib"] -#![warn(missing_copy_implementations)] -// #![warn(missing_docs)] -#![warn(trivial_casts, trivial_numeric_casts)] -// #![warn(unused_extern_crates, unused_qualifications)] - -#[cfg(target_os = "windows")] -extern crate winapi; -#[cfg(test)] -#[macro_use] -extern crate doc_comment; - -#[cfg(test)] -doctest!("../README.md"); - -pub mod ansi; -pub use ansi::{Infix, Prefix, Suffix}; - -mod style; -pub use style::{Color, Style}; - -mod difference; -mod display; -pub use display::*; - -mod write; - -mod windows; -pub use windows::*; - -mod util; -pub use util::*; - -mod debug; - -pub mod gradient; -pub use gradient::*; - -mod rgb; -pub use rgb::*; diff --git a/old_nushell/crates/nu-ansi-term/src/rgb.rs b/old_nushell/crates/nu-ansi-term/src/rgb.rs deleted file mode 100644 index 19475c36b..000000000 --- a/old_nushell/crates/nu-ansi-term/src/rgb.rs +++ /dev/null @@ -1,173 +0,0 @@ -// Code liberally borrowed from here -// https://github.com/navierr/coloriz -use std::ops; -use std::u32; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Rgb { - /// Red - pub r: u8, - /// Green - pub g: u8, - /// Blue - pub b: u8, -} - -impl Rgb { - /// Creates a new [Rgb] color - #[inline] - pub const fn new(r: u8, g: u8, b: u8) -> Self { - Self { r, g, b } - } - - /// Creates a new [Rgb] color with a hex code - #[inline] - pub const fn from_hex(hex: u32) -> Self { - Self::new((hex >> 16) as u8, (hex >> 8) as u8, hex as u8) - } - - pub fn from_hex_string(hex: String) -> Self { - if hex.chars().count() == 8 && hex.starts_with("0x") { - // eprintln!("hex:{:?}", hex); - let (_, value_string) = hex.split_at(2); - // eprintln!("value_string:{:?}", value_string); - let int_val = u64::from_str_radix(value_string, 16); - match int_val { - Ok(num) => Self::new( - ((num & 0xff0000) >> 16) as u8, - ((num & 0xff00) >> 8) as u8, - (num & 0xff) as u8, - ), - // Don't fail, just make the color black - // Should we fail? - _ => Self::new(0, 0, 0), - } - } else { - // Don't fail, just make the color black. - // Should we fail? - Self::new(0, 0, 0) - } - } - - /// Creates a new [Rgb] color with three [f32] values - pub fn from_f32(r: f32, g: f32, b: f32) -> Self { - Self::new( - (r.clamp(0.0, 1.0) * 255.0) as u8, - (g.clamp(0.0, 1.0) * 255.0) as u8, - (b.clamp(0.0, 1.0) * 255.0) as u8, - ) - } - - /// Creates a grayscale [Rgb] color - #[inline] - pub const fn gray(x: u8) -> Self { - Self::new(x, x, x) - } - - /// Creates a grayscale [Rgb] color with a [f32] value - pub fn gray_f32(x: f32) -> Self { - Self::from_f32(x, x, x) - } - - /// Creates a new [Rgb] color from a [HSL] color - // pub fn from_hsl(hsl: HSL) -> Self { - // if hsl.s == 0.0 { - // return Self::gray_f32(hsl.l); - // } - - // let q = if hsl.l < 0.5 { - // hsl.l * (1.0 + hsl.s) - // } else { - // hsl.l + hsl.s - hsl.l * hsl.s - // }; - // let p = 2.0 * hsl.l - q; - // let h2c = |t: f32| { - // let t = t.clamp(0.0, 1.0); - // if 6.0 * t < 1.0 { - // p + 6.0 * (q - p) * t - // } else if t < 0.5 { - // q - // } else if 1.0 < 1.5 * t { - // p + 6.0 * (q - p) * (1.0 / 1.5 - t) - // } else { - // p - // } - // }; - - // Self::from_f32(h2c(hsl.h + 1.0 / 3.0), h2c(hsl.h), h2c(hsl.h - 1.0 / 3.0)) - // } - - /// Computes the linear interpolation between `self` and `other` for `t` - pub fn lerp(&self, other: Self, t: f32) -> Self { - let t = t.clamp(0.0, 1.0); - self * (1.0 - t) + other * t - } -} - -impl From<(u8, u8, u8)> for Rgb { - fn from((r, g, b): (u8, u8, u8)) -> Self { - Self::new(r, g, b) - } -} - -impl From<(f32, f32, f32)> for Rgb { - fn from((r, g, b): (f32, f32, f32)) -> Self { - Self::from_f32(r, g, b) - } -} - -use crate::ANSIColorCode; -use crate::TargetGround; -impl ANSIColorCode for Rgb { - fn ansi_color_code(&self, target: TargetGround) -> String { - format!("{};2;{};{};{}", target.code() + 8, self.r, self.g, self.b) - } -} - -overload::overload!( - (lhs: ?Rgb) + (rhs: ?Rgb) -> Rgb { - Rgb::new( - lhs.r.saturating_add(rhs.r), - lhs.g.saturating_add(rhs.g), - lhs.b.saturating_add(rhs.b) - ) - } -); - -overload::overload!( - (lhs: ?Rgb) - (rhs: ?Rgb) -> Rgb { - Rgb::new( - lhs.r.saturating_sub(rhs.r), - lhs.g.saturating_sub(rhs.g), - lhs.b.saturating_sub(rhs.b) - ) - } -); - -overload::overload!( - (lhs: ?Rgb) * (rhs: ?f32) -> Rgb { - Rgb::new( - (lhs.r as f32 * rhs.clamp(0.0, 1.0)) as u8, - (lhs.g as f32 * rhs.clamp(0.0, 1.0)) as u8, - (lhs.b as f32 * rhs.clamp(0.0, 1.0)) as u8 - ) - } -); - -overload::overload!( - (lhs: ?f32) * (rhs: ?Rgb) -> Rgb { - Rgb::new( - (rhs.r as f32 * lhs.clamp(0.0, 1.0)) as u8, - (rhs.g as f32 * lhs.clamp(0.0, 1.0)) as u8, - (rhs.b as f32 * lhs.clamp(0.0, 1.0)) as u8 - ) - } -); - -overload::overload!( - -(rgb: ?Rgb) -> Rgb { - Rgb::new( - 255 - rgb.r, - 255 - rgb.g, - 255 - rgb.b) - } -); diff --git a/old_nushell/crates/nu-ansi-term/src/style.rs b/old_nushell/crates/nu-ansi-term/src/style.rs deleted file mode 100644 index c4f1d7514..000000000 --- a/old_nushell/crates/nu-ansi-term/src/style.rs +++ /dev/null @@ -1,626 +0,0 @@ -/// A style is a collection of properties that can format a string -/// using ANSI escape codes. -/// -/// # Examples -/// -/// ``` -/// use nu_ansi_term::{Style, Color}; -/// -/// let style = Style::new().bold().on(Color::Black); -/// println!("{}", style.paint("Bold on black")); -/// ``` -#[derive(PartialEq, Clone, Copy)] -#[cfg_attr( - feature = "derive_serde_style", - derive(serde::Deserialize, serde::Serialize) -)] -pub struct Style { - /// The style's foreground color, if it has one. - pub foreground: Option, - - /// The style's background color, if it has one. - pub background: Option, - - /// Whether this style is bold. - pub is_bold: bool, - - /// Whether this style is dimmed. - pub is_dimmed: bool, - - /// Whether this style is italic. - pub is_italic: bool, - - /// Whether this style is underlined. - pub is_underline: bool, - - /// Whether this style is blinking. - pub is_blink: bool, - - /// Whether this style has reverse colors. - pub is_reverse: bool, - - /// Whether this style is hidden. - pub is_hidden: bool, - - /// Whether this style is struckthrough. - pub is_strikethrough: bool, -} - -impl Style { - /// Creates a new Style with no properties set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new(); - /// println!("{}", style.paint("hi")); - /// ``` - pub fn new() -> Style { - Style::default() - } - - /// Returns a `Style` with the bold property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().bold(); - /// println!("{}", style.paint("hey")); - /// ``` - pub fn bold(&self) -> Style { - Style { - is_bold: true, - ..*self - } - } - - /// Returns a `Style` with the dimmed property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().dimmed(); - /// println!("{}", style.paint("sup")); - /// ``` - pub fn dimmed(&self) -> Style { - Style { - is_dimmed: true, - ..*self - } - } - - /// Returns a `Style` with the italic property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().italic(); - /// println!("{}", style.paint("greetings")); - /// ``` - pub fn italic(&self) -> Style { - Style { - is_italic: true, - ..*self - } - } - - /// Returns a `Style` with the underline property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().underline(); - /// println!("{}", style.paint("salutations")); - /// ``` - pub fn underline(&self) -> Style { - Style { - is_underline: true, - ..*self - } - } - - /// Returns a `Style` with the blink property set. - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().blink(); - /// println!("{}", style.paint("wazzup")); - /// ``` - pub fn blink(&self) -> Style { - Style { - is_blink: true, - ..*self - } - } - - /// Returns a `Style` with the reverse property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().reverse(); - /// println!("{}", style.paint("aloha")); - /// ``` - pub fn reverse(&self) -> Style { - Style { - is_reverse: true, - ..*self - } - } - - /// Returns a `Style` with the hidden property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().hidden(); - /// println!("{}", style.paint("ahoy")); - /// ``` - pub fn hidden(&self) -> Style { - Style { - is_hidden: true, - ..*self - } - } - - /// Returns a `Style` with the strikethrough property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// let style = Style::new().strikethrough(); - /// println!("{}", style.paint("yo")); - /// ``` - pub fn strikethrough(&self) -> Style { - Style { - is_strikethrough: true, - ..*self - } - } - - /// Returns a `Style` with the foreground color property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::{Style, Color}; - /// - /// let style = Style::new().fg(Color::Yellow); - /// println!("{}", style.paint("hi")); - /// ``` - pub fn fg(&self, foreground: Color) -> Style { - Style { - foreground: Some(foreground), - ..*self - } - } - - /// Returns a `Style` with the background color property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::{Style, Color}; - /// - /// let style = Style::new().on(Color::Blue); - /// println!("{}", style.paint("eyyyy")); - /// ``` - pub fn on(&self, background: Color) -> Style { - Style { - background: Some(background), - ..*self - } - } - - /// Return true if this `Style` has no actual styles, and can be written - /// without any control characters. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Style; - /// - /// assert_eq!(true, Style::default().is_plain()); - /// assert_eq!(false, Style::default().bold().is_plain()); - /// ``` - pub fn is_plain(self) -> bool { - self == Style::default() - } -} - -impl Default for Style { - /// Returns a style with *no* properties set. Formatting text using this - /// style returns the exact same text. - /// - /// ``` - /// use nu_ansi_term::Style; - /// assert_eq!(None, Style::default().foreground); - /// assert_eq!(None, Style::default().background); - /// assert_eq!(false, Style::default().is_bold); - /// assert_eq!("txt", Style::default().paint("txt").to_string()); - /// ``` - fn default() -> Style { - Style { - foreground: None, - background: None, - is_bold: false, - is_dimmed: false, - is_italic: false, - is_underline: false, - is_blink: false, - is_reverse: false, - is_hidden: false, - is_strikethrough: false, - } - } -} - -// ---- colors ---- - -/// A color is one specific type of ANSI escape code, and can refer -/// to either the foreground or background color. -/// -/// These use the standard numeric sequences. -/// See -#[derive(PartialEq, Clone, Copy, Debug)] -#[cfg_attr( - feature = "derive_serde_style", - derive(serde::Deserialize, serde::Serialize) -)] -pub enum Color { - /// Color #0 (foreground code `30`, background code `40`). - /// - /// This is not necessarily the background color, and using it as one may - /// render the text hard to read on terminals with dark backgrounds. - Black, - - /// Color #0 (foreground code `90`, background code `100`). - DarkGray, - - /// Color #1 (foreground code `31`, background code `41`). - Red, - - /// Color #1 (foreground code `91`, background code `101`). - LightRed, - - /// Color #2 (foreground code `32`, background code `42`). - Green, - - /// Color #2 (foreground code `92`, background code `102`). - LightGreen, - - /// Color #3 (foreground code `33`, background code `43`). - Yellow, - - /// Color #3 (foreground code `93`, background code `103`). - LightYellow, - - /// Color #4 (foreground code `34`, background code `44`). - Blue, - - /// Color #4 (foreground code `94`, background code `104`). - LightBlue, - - /// Color #5 (foreground code `35`, background code `45`). - Purple, - - /// Color #5 (foreground code `95`, background code `105`). - LightPurple, - - /// Color #5 (foreground code `35`, background code `45`). - Magenta, - - /// Color #5 (foreground code `95`, background code `105`). - LightMagenta, - - /// Color #6 (foreground code `36`, background code `46`). - Cyan, - - /// Color #6 (foreground code `96`, background code `106`). - LightCyan, - - /// Color #7 (foreground code `37`, background code `47`). - /// - /// As above, this is not necessarily the foreground color, and may be - /// hard to read on terminals with light backgrounds. - White, - - /// Color #7 (foreground code `97`, background code `107`). - LightGray, - - /// A color number from 0 to 255, for use in 256-color terminal - /// environments. - /// - /// - colors 0 to 7 are the `Black` to `White` variants respectively. - /// These colors can usually be changed in the terminal emulator. - /// - colors 8 to 15 are brighter versions of the eight colors above. - /// These can also usually be changed in the terminal emulator, or it - /// could be configured to use the original colors and show the text in - /// bold instead. It varies depending on the program. - /// - colors 16 to 231 contain several palettes of bright colors, - /// arranged in six squares measuring six by six each. - /// - colors 232 to 255 are shades of grey from black to white. - /// - /// It might make more sense to look at a [color chart][cc]. - /// - /// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg - Fixed(u8), - - /// A 24-bit Rgb color, as specified by ISO-8613-3. - Rgb(u8, u8, u8), -} - -impl Default for Color { - fn default() -> Self { - Color::White - } -} - -impl Color { - /// Returns a `Style` with the foreground color set to this color. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Red.normal(); - /// println!("{}", style.paint("hi")); - /// ``` - pub fn normal(self) -> Style { - Style { - foreground: Some(self), - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// bold property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Green.bold(); - /// println!("{}", style.paint("hey")); - /// ``` - pub fn bold(self) -> Style { - Style { - foreground: Some(self), - is_bold: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// dimmed property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Yellow.dimmed(); - /// println!("{}", style.paint("sup")); - /// ``` - pub fn dimmed(self) -> Style { - Style { - foreground: Some(self), - is_dimmed: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// italic property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Blue.italic(); - /// println!("{}", style.paint("greetings")); - /// ``` - pub fn italic(self) -> Style { - Style { - foreground: Some(self), - is_italic: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// underline property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Purple.underline(); - /// println!("{}", style.paint("salutations")); - /// ``` - pub fn underline(self) -> Style { - Style { - foreground: Some(self), - is_underline: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// blink property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Cyan.blink(); - /// println!("{}", style.paint("wazzup")); - /// ``` - pub fn blink(self) -> Style { - Style { - foreground: Some(self), - is_blink: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// reverse property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Black.reverse(); - /// println!("{}", style.paint("aloha")); - /// ``` - pub fn reverse(self) -> Style { - Style { - foreground: Some(self), - is_reverse: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// hidden property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::White.hidden(); - /// println!("{}", style.paint("ahoy")); - /// ``` - pub fn hidden(self) -> Style { - Style { - foreground: Some(self), - is_hidden: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// strikethrough property set. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Fixed(244).strikethrough(); - /// println!("{}", style.paint("yo")); - /// ``` - pub fn strikethrough(self) -> Style { - Style { - foreground: Some(self), - is_strikethrough: true, - ..Style::default() - } - } - - /// Returns a `Style` with the foreground color set to this color and the - /// background color property set to the given color. - /// - /// # Examples - /// - /// ``` - /// use nu_ansi_term::Color; - /// - /// let style = Color::Rgb(31, 31, 31).on(Color::White); - /// println!("{}", style.paint("eyyyy")); - /// ``` - pub fn on(self, background: Color) -> Style { - Style { - foreground: Some(self), - background: Some(background), - ..Style::default() - } - } -} - -impl From for Style { - /// You can turn a `Color` into a `Style` with the foreground color set - /// with the `From` trait. - /// - /// ``` - /// use nu_ansi_term::{Style, Color}; - /// let green_foreground = Style::default().fg(Color::Green); - /// assert_eq!(green_foreground, Color::Green.normal()); - /// assert_eq!(green_foreground, Color::Green.into()); - /// assert_eq!(green_foreground, Style::from(Color::Green)); - /// ``` - fn from(color: Color) -> Style { - color.normal() - } -} - -#[cfg(test)] -#[cfg(feature = "derive_serde_style")] -mod serde_json_tests { - use super::{Color, Style}; - - #[test] - fn color_serialization() { - let colors = &[ - Color::Red, - Color::Blue, - Color::Rgb(123, 123, 123), - Color::Fixed(255), - ]; - - assert_eq!( - serde_json::to_string(&colors).unwrap(), - String::from("[\"Red\",\"Blue\",{\"Rgb\":[123,123,123]},{\"Fixed\":255}]") - ); - } - - #[test] - fn color_deserialization() { - let colors = [ - Color::Red, - Color::Blue, - Color::Rgb(123, 123, 123), - Color::Fixed(255), - ]; - - for color in colors { - let serialized = serde_json::to_string(&color).unwrap(); - let deserialized: Color = serde_json::from_str(&serialized).unwrap(); - - assert_eq!(color, deserialized); - } - } - - #[test] - fn style_serialization() { - let style = Style::default(); - - assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string()); - } -} diff --git a/old_nushell/crates/nu-ansi-term/src/util.rs b/old_nushell/crates/nu-ansi-term/src/util.rs deleted file mode 100644 index d66645958..000000000 --- a/old_nushell/crates/nu-ansi-term/src/util.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::display::{AnsiString, AnsiStrings}; -use std::ops::Deref; - -/// Return a substring of the given ANSIStrings sequence, while keeping the formatting. -pub fn sub_string<'a>( - start: usize, - len: usize, - strs: &AnsiStrings<'a>, -) -> Vec> { - let mut vec = Vec::new(); - let mut pos = start; - let mut len_rem = len; - - for i in strs.0.iter() { - let fragment = i.deref(); - let frag_len = fragment.len(); - if pos >= frag_len { - pos -= frag_len; - continue; - } - if len_rem == 0 { - break; - } - - let end = pos + len_rem; - let pos_end = if end >= frag_len { frag_len } else { end }; - - vec.push(i.style_ref().paint(String::from(&fragment[pos..pos_end]))); - - if end <= frag_len { - break; - } - - len_rem -= pos_end - pos; - pos = 0; - } - - vec -} - -/// Return a concatenated copy of `strs` without the formatting, as an allocated `String`. -pub fn unstyle(strs: &AnsiStrings) -> String { - let mut s = String::new(); - - for i in strs.0.iter() { - s += i.deref(); - } - - s -} - -/// Return the unstyled length of ANSIStrings. This is equaivalent to `unstyle(strs).len()`. -pub fn unstyled_len(strs: &AnsiStrings) -> usize { - let mut l = 0; - for i in strs.0.iter() { - l += i.deref().len(); - } - l -} - -#[cfg(test)] -mod test { - use super::*; - use crate::Color::*; - - #[test] - fn test() { - let l = [ - Black.paint("first"), - Red.paint("-second"), - White.paint("-third"), - ]; - let a = AnsiStrings(&l); - assert_eq!(unstyle(&a), "first-second-third"); - assert_eq!(unstyled_len(&a), 18); - - let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")]; - assert_eq!(sub_string(3, 11, &a), l2); - } -} diff --git a/old_nushell/crates/nu-ansi-term/src/windows.rs b/old_nushell/crates/nu-ansi-term/src/windows.rs deleted file mode 100644 index 828e35573..000000000 --- a/old_nushell/crates/nu-ansi-term/src/windows.rs +++ /dev/null @@ -1,62 +0,0 @@ -/// Enables ANSI code support on Windows 10. -/// -/// This uses Windows API calls to alter the properties of the console that -/// the program is running in. -/// -/// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx -/// -/// Returns a `Result` with the Windows error code if unsuccessful. -#[cfg(windows)] -pub fn enable_ansi_support() -> Result<(), u32> { - // ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76% - - use std::ffi::OsStr; - use std::iter::once; - use std::os::windows::ffi::OsStrExt; - use std::ptr::null_mut; - use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode}; - use winapi::um::errhandlingapi::GetLastError; - use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING}; - use winapi::um::handleapi::INVALID_HANDLE_VALUE; - use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}; - - const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004; - - unsafe { - // ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew - // Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected - let console_out_name: Vec = - OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect(); - let console_handle = CreateFileW( - console_out_name.as_ptr(), - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_WRITE, - null_mut(), - OPEN_EXISTING, - 0, - null_mut(), - ); - if console_handle == INVALID_HANDLE_VALUE { - return Err(GetLastError()); - } - - // ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode - let mut console_mode: u32 = 0; - if 0 == GetConsoleMode(console_handle, &mut console_mode) { - return Err(GetLastError()); - } - - // VT processing not already enabled? - if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 { - // https://docs.microsoft.com/en-us/windows/console/setconsolemode - if 0 == SetConsoleMode( - console_handle, - console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING, - ) { - return Err(GetLastError()); - } - } - } - - Ok(()) -} diff --git a/old_nushell/crates/nu-ansi-term/src/write.rs b/old_nushell/crates/nu-ansi-term/src/write.rs deleted file mode 100644 index 552771918..000000000 --- a/old_nushell/crates/nu-ansi-term/src/write.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::fmt; -use std::io; - -pub trait AnyWrite { - type Wstr: ?Sized; - type Error; - - fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error>; - - fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error>; -} - -impl<'a> AnyWrite for dyn fmt::Write + 'a { - type Wstr = str; - type Error = fmt::Error; - - fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> { - fmt::Write::write_fmt(self, fmt) - } - - fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> { - fmt::Write::write_str(self, s) - } -} - -impl<'a> AnyWrite for dyn io::Write + 'a { - type Wstr = [u8]; - type Error = io::Error; - - fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> { - io::Write::write_fmt(self, fmt) - } - - fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> { - io::Write::write_all(self, s) - } -} diff --git a/old_nushell/crates/nu-cli/Cargo.toml b/old_nushell/crates/nu-cli/Cargo.toml deleted file mode 100644 index 305edeb45..000000000 --- a/old_nushell/crates/nu-cli/Cargo.toml +++ /dev/null @@ -1,43 +0,0 @@ -[package] -authors = ["The Nu Project Contributors"] -description = "CLI for nushell" -edition = "2018" -license = "MIT" -name = "nu-cli" -version = "0.43.0" -build = "build.rs" - -[lib] -doctest = false - -[dependencies] -nu-completion = { version = "0.43.0", path="../nu-completion" } -nu-command = { version = "0.43.0", path="../nu-command" } -nu-data = { version = "0.43.0", path="../nu-data" } -nu-engine = { version = "0.43.0", path="../nu-engine" } -nu-errors = { version = "0.43.0", path="../nu-errors" } -nu-parser = { version = "0.43.0", path="../nu-parser" } -nu-protocol = { version = "0.43.0", path="../nu-protocol" } -nu-source = { version = "0.43.0", path="../nu-source" } -nu-stream = { version = "0.43.0", path="../nu-stream" } -nu-ansi-term = { version = "0.43.0", path="../nu-ansi-term" } -nu-path = { version = "0.43.0", path="../nu-path" } - -indexmap ="1.6.1" -log = "0.4.14" -pretty_env_logger = "0.4.0" -strip-ansi-escapes = "0.1.0" -rustyline = { version="9.0.0", optional=true } -ctrlc = { version="3.1.7", optional=true } -shadow-rs = { version = "0.8.1", default-features = false, optional = true } -serde = { version="1.0.123", features=["derive"] } -serde_yaml = "0.8.16" -lazy_static = "1.4.0" - -[build-dependencies] -shadow-rs = "0.8.1" - -[features] -default = ["shadow-rs"] -rustyline-support = ["rustyline", "nu-engine/rustyline-support"] -stable = [] diff --git a/old_nushell/crates/nu-cli/README.md b/old_nushell/crates/nu-cli/README.md deleted file mode 100644 index ae7eeaed7..000000000 --- a/old_nushell/crates/nu-cli/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# nu-cli - -This crate provides the fundamental needs when creating the Nushell interactive REPL. In it, you'll find features for interacting with the line editor (the piece which writes the prompt and takes input from the user), keybindings, handlers for the commandline arguments passed to the REPL as it starts up, and more. - diff --git a/old_nushell/crates/nu-cli/build.rs b/old_nushell/crates/nu-cli/build.rs deleted file mode 100644 index 4a0dfc459..000000000 --- a/old_nushell/crates/nu-cli/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() -> shadow_rs::SdResult<()> { - shadow_rs::new() -} diff --git a/old_nushell/crates/nu-cli/src/app.rs b/old_nushell/crates/nu-cli/src/app.rs deleted file mode 100644 index 51cd6be0f..000000000 --- a/old_nushell/crates/nu-cli/src/app.rs +++ /dev/null @@ -1,638 +0,0 @@ -mod logger; -mod options; -mod options_parser; -pub mod stopwatch; - -use self::stopwatch::Stopwatch; -use lazy_static::lazy_static; -use nu_command::{commands::NuSignature as Nu, utils::test_bins as binaries}; -use nu_engine::{get_full_help, EvaluationContext}; -use nu_errors::ShellError; -use nu_protocol::hir::{Call, Expression, SpannedExpression, Synthetic}; -use nu_protocol::{Primitive, UntaggedValue}; -use nu_source::{Span, Tag}; -use nu_stream::InputStream; -pub use options::{CliOptions, NuScript, Options}; -use options_parser::{NuParser, OptionsParser}; -use std::sync::Mutex; - -lazy_static! { - pub static ref STOPWATCH: Mutex = { - let mut sw = Stopwatch::default(); - sw.start(); - sw.stop(); - Mutex::new(sw) - }; -} - -pub struct App { - parser: Box, - pub options: Options, -} - -impl App { - pub fn new(parser: Box, options: Options) -> Self { - Self { parser, options } - } - - pub fn run(args: &[String]) -> Result<(), ShellError> { - let nu = Box::new(NuParser::new()); - let options = Options::default(); - let ui = App::new(nu, options); - - ui.main(args) - } - - pub fn main(&self, argv: &[String]) -> Result<(), ShellError> { - if self.perf() { - // start the stopwatch running - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start(); - } - - let argv = quote_positionals(argv).join(" "); - - if let Err(cause) = self.parse(&argv) { - self.parser - .context() - .host() - .lock() - .print_err(cause, &nu_source::Text::from(argv)); - std::process::exit(1); - } - - if self.help() { - let context = self.parser.context(); - let stream = nu_stream::OutputStream::one( - UntaggedValue::string(get_full_help(&Nu, &context.scope)) - .into_value(nu_source::Tag::unknown()), - ); - - consume(context, stream)?; - - if self.perf() { - // stop the stopwatch since we're exiting - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .stop(); - eprintln!( - "help {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed() - ); - } - - std::process::exit(0); - } - - if self.version() { - let context = self.parser.context(); - - let stream = nu_command::commands::version(nu_engine::CommandArgs { - context: context.clone(), - call_info: nu_engine::UnevaluatedCallInfo { - args: Call::new( - Box::new(SpannedExpression::new( - Expression::Synthetic(Synthetic::String("version".to_string())), - Span::unknown(), - )), - Span::unknown(), - ), - name_tag: Tag::unknown(), - }, - input: InputStream::empty(), - })?; - - let stream = { - let command = context - .get_command("pivot") - .expect("could not find version command"); - - context.run_command( - command, - Tag::unknown(), - Call::new( - Box::new(SpannedExpression::new( - Expression::Synthetic(Synthetic::String("pivot".to_string())), - Span::unknown(), - )), - Span::unknown(), - ), - stream, - )? - }; - - consume(context, stream)?; - - if self.perf() { - // stop the stopwatch since we're exiting - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .stop(); - eprintln!( - "version {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed() - ); - } - - std::process::exit(0); - } - - if let Some(bin) = self.testbin() { - match bin.as_deref() { - Ok("echo_env") => binaries::echo_env(), - Ok("cococo") => binaries::cococo(), - Ok("meow") => binaries::meow(), - Ok("iecho") => binaries::iecho(), - Ok("fail") => binaries::fail(), - Ok("nonu") => binaries::nonu(), - Ok("chop") => binaries::chop(), - Ok("repeater") => binaries::repeater(), - _ => unreachable!(), - } - - return Ok(()); - } - - let mut opts = CliOptions::new(); - opts.config = self.config().map(std::ffi::OsString::from); - opts.stdin = self.takes_stdin(); - opts.save_history = self.save_history(); - opts.perf = self.perf(); - - use logger::{configure, debug_filters, logger, trace_filters}; - - logger(|builder| { - configure(self, builder)?; - trace_filters(self, builder)?; - debug_filters(self, builder)?; - - Ok(()) - })?; - - if self.perf() { - // start a new split - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start() - } - - if let Some(commands) = self.commands() { - let commands = commands?; - let script = NuScript::code(&commands)?; - opts.scripts = vec![script]; - let context = crate::create_default_context(false)?; - return crate::run_script_file(context, opts); - } - - if self.perf() { - // start a new spit - eprintln!( - "commands using -c at launch: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start(); - } - - if let Some(scripts) = self.scripts() { - let mut source_files = vec![]; - for script in scripts { - let script_name = script?; - let path = std::ffi::OsString::from(&script_name); - - match NuScript::source_file(path.as_os_str()) { - Ok(file) => source_files.push(file), - Err(_) => { - eprintln!("File not found: {}", script_name); - return Ok(()); - } - } - } - - for file in source_files { - let mut opts = opts.clone(); - opts.scripts = vec![file]; - - let context = crate::create_default_context(false)?; - crate::run_script_file(context, opts)?; - } - - return Ok(()); - } - - if self.perf() { - // start a new split - eprintln!( - "script file(s) passed in: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start(); - } - - let context = crate::create_default_context(true)?; - - if !self.skip_plugins() { - let _ = crate::register_plugins(&context); - } - - if self.perf() { - // start a new split - eprintln!( - "plugins registered: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - } - - #[cfg(feature = "rustyline-support")] - { - crate::cli(context, opts)?; - } - - #[cfg(not(feature = "rustyline-support"))] - { - println!("Nushell needs the 'rustyline-support' feature for CLI support"); - } - - Ok(()) - } - - pub fn commands(&self) -> Option> { - self.options.get("commands").map(|v| match v.value { - UntaggedValue::Error(err) => Err(err), - UntaggedValue::Primitive(Primitive::String(name)) => Ok(name), - _ => Err(ShellError::untagged_runtime_error("Unsupported option")), - }) - } - - pub fn perf(&self) -> bool { - self.options - .get("perf") - .map(|v| matches!(v.as_bool(), Ok(true))) - .unwrap_or(false) - } - - pub fn help(&self) -> bool { - self.options - .get("help") - .map(|v| matches!(v.as_bool(), Ok(true))) - .unwrap_or(false) - } - - pub fn version(&self) -> bool { - self.options - .get("version") - .map(|v| matches!(v.as_bool(), Ok(true))) - .unwrap_or(false) - } - - pub fn scripts(&self) -> Option>> { - self.options.get("args").map(|v| { - v.table_entries() - .map(|v| match &v.value { - UntaggedValue::Error(err) => Err(err.clone()), - UntaggedValue::Primitive(Primitive::FilePath(path)) => { - Ok(path.display().to_string()) - } - UntaggedValue::Primitive(Primitive::String(name)) => Ok(name.clone()), - _ => Err(ShellError::untagged_runtime_error("Unsupported option")), - }) - .collect() - }) - } - - pub fn takes_stdin(&self) -> bool { - self.options - .get("stdin") - .map(|v| matches!(v.as_bool(), Ok(true))) - .unwrap_or(false) - } - - pub fn config(&self) -> Option { - self.options - .get("config-file") - .map(|v| v.as_string().expect("not a string")) - } - - pub fn develop(&self) -> Option>> { - self.options.get("develop").map(|v| { - let mut values = vec![]; - - match v.value { - UntaggedValue::Error(err) => values.push(Err(err)), - UntaggedValue::Primitive(Primitive::String(filters)) => { - values.extend(filters.split(',').map(|filter| Ok(filter.to_string()))); - } - _ => values.push(Err(ShellError::untagged_runtime_error( - "Unsupported option", - ))), - }; - - values - }) - } - - pub fn debug(&self) -> Option>> { - self.options.get("debug").map(|v| { - let mut values = vec![]; - - match v.value { - UntaggedValue::Error(err) => values.push(Err(err)), - UntaggedValue::Primitive(Primitive::String(filters)) => { - values.extend(filters.split(',').map(|filter| Ok(filter.to_string()))); - } - _ => values.push(Err(ShellError::untagged_runtime_error( - "Unsupported option", - ))), - }; - - values - }) - } - - pub fn loglevel(&self) -> Option> { - self.options.get("loglevel").map(|v| match v.value { - UntaggedValue::Error(err) => Err(err), - UntaggedValue::Primitive(Primitive::String(name)) => Ok(name), - _ => Err(ShellError::untagged_runtime_error("Unsupported option")), - }) - } - - pub fn testbin(&self) -> Option> { - self.options.get("testbin").map(|v| match v.value { - UntaggedValue::Error(err) => Err(err), - UntaggedValue::Primitive(Primitive::String(name)) => Ok(name), - _ => Err(ShellError::untagged_runtime_error("Unsupported option")), - }) - } - - pub fn skip_plugins(&self) -> bool { - self.options - .get("skip-plugins") - .map(|v| matches!(v.as_bool(), Ok(true))) - .unwrap_or(false) - } - - pub fn save_history(&self) -> bool { - self.options - .get("no-history") - .map(|v| !matches!(v.as_bool(), Ok(true))) - .unwrap_or(true) - } - - pub fn parse(&self, args: &str) -> Result<(), ShellError> { - self.parser.parse(args).map(|options| { - self.options.swap(&options); - }) - } -} - -fn quote_positionals(parameters: &[String]) -> Vec { - parameters - .iter() - .cloned() - .map(|arg| { - if arg.contains(' ') { - format!("\"{}\"", arg) - } else { - arg - } - }) - .collect::>() -} - -fn consume(context: &EvaluationContext, stream: InputStream) -> Result<(), ShellError> { - let autoview_cmd = context - .get_command("autoview") - .expect("could not find autoview command"); - - let stream = context.run_command( - autoview_cmd, - Tag::unknown(), - Call::new( - Box::new(SpannedExpression::new( - Expression::Synthetic(Synthetic::String("autoview".to_string())), - Span::unknown(), - )), - Span::unknown(), - ), - stream, - )?; - - for _ in stream {} - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn cli_app() -> App { - let parser = Box::new(NuParser::new()); - let options = Options::default(); - - App::new(parser, options) - } - - #[test] - fn default_options() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu")?; - assert!(!ui.version()); - assert!(!ui.help()); - assert!(!ui.takes_stdin()); - assert!(ui.save_history()); - assert!(!ui.skip_plugins()); - assert_eq!(ui.config(), None); - assert_eq!(ui.loglevel(), None); - assert_eq!(ui.debug(), None); - assert_eq!(ui.develop(), None); - assert_eq!(ui.testbin(), None); - assert_eq!(ui.commands(), None); - assert_eq!(ui.scripts(), None); - Ok(()) - } - - #[test] - fn reports_errors_on_unsupported_flags() -> Result<(), ShellError> { - let ui = cli_app(); - - assert!(ui.parse("nu --coonfig-file /path/to/config.toml").is_err()); - assert!(ui.config().is_none()); - Ok(()) - } - - #[test] - fn configures_debug_trace_level_with_filters() -> Result<(), ShellError> { - let ui = cli_app(); - ui.parse("nu --develop=cli,parser")?; - assert_eq!(ui.develop().unwrap()[0], Ok("cli".to_string())); - assert_eq!(ui.develop().unwrap()[1], Ok("parser".to_string())); - Ok(()) - } - - #[test] - fn configures_debug_level_with_filters() -> Result<(), ShellError> { - let ui = cli_app(); - ui.parse("nu --debug=cli,run")?; - assert_eq!(ui.debug().unwrap()[0], Ok("cli".to_string())); - assert_eq!(ui.debug().unwrap()[1], Ok("run".to_string())); - Ok(()) - } - - #[test] - fn can_use_loglevels() -> Result<(), ShellError> { - for level in ["error", "warn", "info", "debug", "trace"] { - let ui = cli_app(); - let args = format!("nu --loglevel={}", level); - ui.parse(&args)?; - assert_eq!(ui.loglevel().unwrap(), Ok(level.to_string())); - } - - let ui = cli_app(); - ui.parse("nu --loglevel=nada")?; - assert_eq!( - ui.loglevel().unwrap(), - Err(ShellError::untagged_runtime_error("nada is not supported.")) - ); - - Ok(()) - } - - #[test] - fn can_be_login() -> Result<(), ShellError> { - let ui = cli_app(); - ui.parse("nu -l")?; - - let ui = cli_app(); - ui.parse("nu --login")?; - - Ok(()) - } - - #[test] - fn can_be_passed_nu_scripts() -> Result<(), ShellError> { - let ui = cli_app(); - ui.parse("nu code.nu bootstrap.nu")?; - assert_eq!(ui.scripts().unwrap()[0], Ok("code.nu".into())); - assert_eq!(ui.scripts().unwrap()[1], Ok("bootstrap.nu".into())); - Ok(()) - } - - #[test] - fn can_use_test_binaries() -> Result<(), ShellError> { - for binarie_name in [ - "echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", "meow", - ] { - let ui = cli_app(); - let args = format!("nu --testbin={}", binarie_name); - ui.parse(&args)?; - assert_eq!(ui.testbin().unwrap(), Ok(binarie_name.to_string())); - } - - let ui = cli_app(); - ui.parse("nu --testbin=andres")?; - assert_eq!( - ui.testbin().unwrap(), - Err(ShellError::untagged_runtime_error( - "andres is not supported." - )) - ); - - Ok(()) - } - - #[test] - fn has_version() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu --version")?; - assert!(ui.version()); - Ok(()) - } - - #[test] - fn has_help() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu --help")?; - assert!(ui.help()); - Ok(()) - } - - #[test] - fn can_take_stdin() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu --stdin")?; - assert!(ui.takes_stdin()); - Ok(()) - } - - #[test] - fn can_opt_to_avoid_saving_history() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu --no-history")?; - assert!(!ui.save_history()); - Ok(()) - } - - #[test] - fn can_opt_to_skip_plugins() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu --skip-plugins")?; - assert!(ui.skip_plugins()); - Ok(()) - } - - #[test] - fn understands_commands_need_to_be_run() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu -c \"ls | get name\"")?; - assert_eq!(ui.commands().unwrap(), Ok(String::from("ls | get name"))); - - let ui = cli_app(); - - ui.parse("nu -c \"echo 'hola'\"")?; - assert_eq!(ui.commands().unwrap(), Ok(String::from("echo 'hola'"))); - Ok(()) - } - - #[test] - fn knows_custom_configurations() -> Result<(), ShellError> { - let ui = cli_app(); - - ui.parse("nu --config-file /path/to/config.toml")?; - assert_eq!(ui.config().unwrap(), String::from("/path/to/config.toml")); - Ok(()) - } -} diff --git a/old_nushell/crates/nu-cli/src/app/logger.rs b/old_nushell/crates/nu-cli/src/app/logger.rs deleted file mode 100644 index 02644a856..000000000 --- a/old_nushell/crates/nu-cli/src/app/logger.rs +++ /dev/null @@ -1,52 +0,0 @@ -use super::App; -use log::LevelFilter; -use nu_errors::ShellError; -use pretty_env_logger::env_logger::Builder; - -pub fn logger(f: impl FnOnce(&mut Builder) -> Result<(), ShellError>) -> Result<(), ShellError> { - let mut builder = pretty_env_logger::formatted_builder(); - f(&mut builder)?; - let _ = builder.try_init(); - Ok(()) -} - -pub fn configure(app: &App, logger: &mut Builder) -> Result<(), ShellError> { - if let Some(level) = app.loglevel() { - let level = match level.as_deref() { - Ok("error") => LevelFilter::Error, - Ok("warn") => LevelFilter::Warn, - Ok("info") => LevelFilter::Info, - Ok("debug") => LevelFilter::Debug, - Ok("trace") => LevelFilter::Trace, - Ok(_) | Err(_) => LevelFilter::Warn, - }; - - logger.filter_module("nu", level); - }; - - if let Ok(s) = std::env::var("RUST_LOG") { - logger.parse_filters(&s); - } - - Ok(()) -} - -pub fn trace_filters(app: &App, logger: &mut Builder) -> Result<(), ShellError> { - if let Some(filters) = app.develop() { - filters.into_iter().filter_map(Result::ok).for_each(|name| { - logger.filter_module(&name, LevelFilter::Trace); - }) - } - - Ok(()) -} - -pub fn debug_filters(app: &App, logger: &mut Builder) -> Result<(), ShellError> { - if let Some(filters) = app.debug() { - filters.into_iter().filter_map(Result::ok).for_each(|name| { - logger.filter_module(&name, LevelFilter::Debug); - }) - } - - Ok(()) -} diff --git a/old_nushell/crates/nu-cli/src/app/options.rs b/old_nushell/crates/nu-cli/src/app/options.rs deleted file mode 100644 index 025316578..000000000 --- a/old_nushell/crates/nu-cli/src/app/options.rs +++ /dev/null @@ -1,102 +0,0 @@ -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_protocol::{UntaggedValue, Value}; -use std::cell::RefCell; -use std::ffi::{OsStr, OsString}; - -#[derive(Debug, Clone)] -pub struct CliOptions { - pub config: Option, - pub stdin: bool, - pub scripts: Vec, - pub save_history: bool, - pub perf: bool, -} - -impl Default for CliOptions { - fn default() -> Self { - Self::new() - } -} - -impl CliOptions { - pub fn new() -> Self { - Self { - config: None, - stdin: false, - scripts: vec![], - save_history: true, - perf: false, - } - } -} - -#[derive(Debug)] -pub struct Options { - inner: RefCell>, -} - -impl Options { - pub fn default() -> Self { - Self { - inner: RefCell::new(IndexMap::default()), - } - } - - pub fn get(&self, key: &str) -> Option { - self.inner.borrow().get(key).cloned() - } - - pub fn put(&self, key: &str, value: Value) { - self.inner.borrow_mut().insert(key.into(), value); - } - - pub fn shift(&self) { - if let Some(Value { - value: UntaggedValue::Table(ref mut args), - .. - }) = self.inner.borrow_mut().get_mut("args") - { - args.remove(0); - } - } - - pub fn swap(&self, other: &Options) { - self.inner.swap(&other.inner); - } -} - -#[derive(Debug, Clone)] -pub struct NuScript { - pub filepath: Option, - pub contents: String, -} - -impl NuScript { - pub fn code(content: &str) -> Result { - Ok(Self { - filepath: None, - contents: content.to_string(), - }) - } - - pub fn get_code(&self) -> &str { - &self.contents - } - - pub fn source_file(path: &OsStr) -> Result { - use std::fs::File; - use std::io::Read; - - let path = path.to_os_string(); - let mut file = File::open(&path)?; - let mut buffer = String::new(); - - file.read_to_string(&mut buffer)?; - - Ok(Self { - filepath: Some(path), - contents: buffer, - }) - } -} diff --git a/old_nushell/crates/nu-cli/src/app/options_parser.rs b/old_nushell/crates/nu-cli/src/app/options_parser.rs deleted file mode 100644 index d6efb6b0b..000000000 --- a/old_nushell/crates/nu-cli/src/app/options_parser.rs +++ /dev/null @@ -1,132 +0,0 @@ -use super::Options; - -use nu_command::commands::{loglevels, testbins, NuSignature as Nu}; -use nu_command::commands::{Autoview, Pivot, Table, Version as NuVersion}; -use nu_engine::{whole_stream_command, EvaluationContext}; -use nu_errors::ShellError; -use nu_protocol::hir::{ClassifiedCommand, InternalCommand, NamedValue}; -use nu_protocol::UntaggedValue; -use nu_source::Tag; - -pub struct NuParser { - context: EvaluationContext, -} - -pub trait OptionsParser { - fn parse(&self, input: &str) -> Result; - fn context(&self) -> &EvaluationContext; -} - -impl NuParser { - pub fn new() -> Self { - let context = EvaluationContext::basic(); - context.add_commands(vec![ - whole_stream_command(Nu {}), - whole_stream_command(NuVersion {}), - whole_stream_command(Autoview {}), - whole_stream_command(Pivot {}), - whole_stream_command(Table {}), - ]); - - Self { context } - } -} - -impl OptionsParser for NuParser { - fn context(&self) -> &EvaluationContext { - &self.context - } - - fn parse(&self, input: &str) -> Result { - let options = Options::default(); - let (lite_result, _err) = nu_parser::lex(input, 0, nu_parser::NewlineMode::Normal); - let (lite_result, _err) = nu_parser::parse_block(lite_result); - - let (parsed, err) = nu_parser::classify_block(&lite_result, &self.context.scope); - - if let Some(reason) = err { - return Err(reason.into()); - } - - match parsed.block[0].pipelines[0].list[0] { - ClassifiedCommand::Internal(InternalCommand { ref args, .. }) => { - if let Some(ref params) = args.named { - params.iter().for_each(|(k, v)| { - let value = match v { - NamedValue::AbsentSwitch => { - Some(UntaggedValue::from(false).into_untagged_value()) - } - NamedValue::PresentSwitch(span) => { - Some(UntaggedValue::from(true).into_value(Tag::from(span))) - } - NamedValue::AbsentValue => None, - NamedValue::Value(span, exprs) => { - let value = nu_engine::evaluate_baseline_expr(exprs, &self.context) - .expect("value"); - Some(value.value.into_value(Tag::from(span))) - } - }; - - let value = value.map(|v| match k.as_ref() { - "testbin" => { - if let Ok(name) = v.as_string() { - if testbins().iter().any(|n| name == *n) { - v - } else { - UntaggedValue::Error(ShellError::untagged_runtime_error( - format!("{} is not supported.", name), - )) - .into_value(v.tag) - } - } else { - v - } - } - "loglevel" => { - if let Ok(name) = v.as_string() { - if loglevels().iter().any(|n| name == *n) { - v - } else { - UntaggedValue::Error(ShellError::untagged_runtime_error( - format!("{} is not supported.", name), - )) - .into_value(v.tag) - } - } else { - v - } - } - _ => v, - }); - - if let Some(value) = value { - options.put(k, value); - } - }); - } - - let mut positional_args = vec![]; - - if let Some(positional) = &args.positional { - for pos in positional { - let result = nu_engine::evaluate_baseline_expr(pos, &self.context)?; - positional_args.push(result); - } - } - - if !positional_args.is_empty() { - options.put( - "args", - UntaggedValue::Table(positional_args).into_untagged_value(), - ); - } - } - ClassifiedCommand::Error(ref reason) => { - return Err(reason.clone().into()); - } - _ => return Err(ShellError::untagged_runtime_error("unrecognized command")), - } - - Ok(options) - } -} diff --git a/old_nushell/crates/nu-cli/src/app/stopwatch.rs b/old_nushell/crates/nu-cli/src/app/stopwatch.rs deleted file mode 100644 index e433782af..000000000 --- a/old_nushell/crates/nu-cli/src/app/stopwatch.rs +++ /dev/null @@ -1,118 +0,0 @@ -#![allow(dead_code)] -use std::default::Default; -use std::fmt; -use std::time::{Duration, Instant}; - -#[derive(Clone, Copy)] -pub struct Stopwatch { - /// The time the stopwatch was started last, if ever. - start_time: Option, - /// The time the stopwatch was split last, if ever. - split_time: Option, - /// The time elapsed while the stopwatch was running (between start() and stop()). - elapsed: Duration, -} - -impl Default for Stopwatch { - fn default() -> Stopwatch { - Stopwatch { - start_time: None, - split_time: None, - elapsed: Duration::from_secs(0), - } - } -} - -impl fmt::Display for Stopwatch { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - return write!(f, "{}ms", self.elapsed_ms()); - } -} - -impl Stopwatch { - /// Returns a new stopwatch. - pub fn new() -> Stopwatch { - let sw: Stopwatch = Default::default(); - sw - } - - /// Returns a new stopwatch which will immediately be started. - pub fn start_new() -> Stopwatch { - let mut sw = Stopwatch::new(); - sw.start(); - sw - } - - /// Starts the stopwatch. - pub fn start(&mut self) { - self.start_time = Some(Instant::now()); - } - - /// Stops the stopwatch. - pub fn stop(&mut self) { - self.elapsed = self.elapsed(); - self.start_time = None; - self.split_time = None; - } - - /// Resets all counters and stops the stopwatch. - pub fn reset(&mut self) { - self.elapsed = Duration::from_secs(0); - self.start_time = None; - self.split_time = None; - } - - /// Resets and starts the stopwatch again. - pub fn restart(&mut self) { - self.reset(); - self.start(); - } - - /// Returns whether the stopwatch is running. - pub fn is_running(&self) -> bool { - self.start_time.is_some() - } - - /// Returns the elapsed time since the start of the stopwatch. - pub fn elapsed(&self) -> Duration { - match self.start_time { - // stopwatch is running - Some(t1) => t1.elapsed() + self.elapsed, - // stopwatch is not running - None => self.elapsed, - } - } - - /// Returns the elapsed time since the start of the stopwatch in milliseconds. - pub fn elapsed_ms(&self) -> i64 { - let dur = self.elapsed(); - (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64 - } - - /// Returns the elapsed time since last split or start/restart. - /// - /// If the stopwatch is in stopped state this will always return a zero Duration. - pub fn elapsed_split(&mut self) -> Duration { - match self.start_time { - // stopwatch is running - Some(start) => { - let res = match self.split_time { - Some(split) => split.elapsed(), - None => start.elapsed(), - }; - self.split_time = Some(Instant::now()); - res - } - // stopwatch is not running - None => Duration::from_secs(0), - } - } - - /// Returns the elapsed time since last split or start/restart in milliseconds. - /// - /// If the stopwatch is in stopped state this will always return zero. - pub fn elapsed_split_ms(&mut self) -> i64 { - let dur = self.elapsed_split(); - (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64 - } -} diff --git a/old_nushell/crates/nu-cli/src/cli.rs b/old_nushell/crates/nu-cli/src/cli.rs deleted file mode 100644 index 72f2f4c97..000000000 --- a/old_nushell/crates/nu-cli/src/cli.rs +++ /dev/null @@ -1,538 +0,0 @@ -use crate::app::STOPWATCH; -use crate::line_editor::configure_ctrl_c; -use nu_ansi_term::Color; -use nu_engine::{maybe_print_errors, run_block, script::run_script_standalone, EvaluationContext}; - -#[allow(unused_imports)] -pub(crate) use nu_engine::script::{process_script, LineResult}; - -#[cfg(feature = "rustyline-support")] -use crate::line_editor::{ - configure_rustyline_editor, convert_rustyline_result_to_string, - default_rustyline_editor_configuration, nu_line_editor_helper, -}; - -#[allow(unused_imports)] -use nu_data::config; -use nu_source::{Tag, Text}; -use nu_stream::InputStream; -#[allow(unused_imports)] -use std::sync::atomic::Ordering; - -#[cfg(feature = "rustyline-support")] -use rustyline::{self, error::ReadlineError}; - -use nu_errors::ShellError; -use nu_parser::ParserScope; -use nu_path::expand_tilde; -use nu_protocol::{hir::ExternalRedirection, ConfigPath, UntaggedValue, Value}; - -use log::trace; -use std::error::Error; -use std::iter::Iterator; -use std::path::PathBuf; - -// Name of environment variable where the prompt could be stored -#[cfg(feature = "rustyline-support")] -const PROMPT_COMMAND: &str = "PROMPT_COMMAND"; - -pub fn search_paths() -> Vec { - use std::env; - let mut search_paths = Vec::new(); - - // Automatically add path `nu` is in as a search path - if let Ok(exe_path) = env::current_exe() { - if let Some(exe_dir) = exe_path.parent() { - search_paths.push(exe_dir.to_path_buf()); - } - } - - if let Ok(config) = nu_data::config::config(Tag::unknown()) { - if let Some(Value { - value: UntaggedValue::Table(pipelines), - .. - }) = config.get("plugin_dirs") - { - for pipeline in pipelines { - if let Ok(plugin_dir) = pipeline.as_string() { - search_paths.push(expand_tilde(plugin_dir)); - } - } - } - } - - search_paths -} - -pub fn run_script_file( - context: EvaluationContext, - options: super::app::CliOptions, -) -> Result<(), ShellError> { - if let Some(cfg) = options.config { - load_cfg_as_global_cfg(&context, PathBuf::from(cfg)); - } else { - load_global_cfg(&context); - } - - let _ = register_plugins(&context); - let _ = configure_ctrl_c(&context); - - let script = options - .scripts - .get(0) - .ok_or_else(|| ShellError::unexpected("Nu source code not available"))?; - - run_script_standalone(script.get_code().to_string(), options.stdin, &context, true)?; - - Ok(()) -} - -#[cfg(feature = "rustyline-support")] -fn default_prompt_string(cwd: &str) -> String { - format!( - "{}{}{}{}{}{}> ", - Color::Green.bold().prefix(), - cwd, - nu_ansi_term::ansi::RESET, - Color::Cyan.bold().prefix(), - current_branch(), - nu_ansi_term::ansi::RESET - ) -} - -#[cfg(feature = "rustyline-support")] -fn evaluate_prompt_string(prompt_line: &str, context: &EvaluationContext, cwd: &str) -> String { - context.scope.enter_scope(); - let (prompt_block, err) = nu_parser::parse(prompt_line, 0, &context.scope); - - if err.is_some() { - context.scope.exit_scope(); - default_prompt_string(cwd) - } else { - let run_result = run_block( - &prompt_block, - context, - InputStream::empty(), - ExternalRedirection::Stdout, - ); - context.scope.exit_scope(); - - match run_result { - Ok(result) => match result.collect_string(Tag::unknown()) { - Ok(string_result) => { - let errors = context.get_errors(); - maybe_print_errors(context, Text::from(prompt_line)); - context.clear_errors(); - - if !errors.is_empty() { - "> ".into() - } else { - string_result.item - } - } - Err(e) => { - context.host().lock().print_err(e, &Text::from(prompt_line)); - context.clear_errors(); - - "> ".into() - } - }, - Err(e) => { - context.host().lock().print_err(e, &Text::from(prompt_line)); - context.clear_errors(); - - "> ".into() - } - } - } -} - -#[cfg(feature = "rustyline-support")] -pub fn cli( - context: EvaluationContext, - options: super::app::CliOptions, -) -> Result<(), Box> { - let _ = configure_ctrl_c(&context); - - // start time for running startup scripts (this metric includes loading of the cfg, but w/e) - let startup_commands_start_time = std::time::Instant::now(); - - if let Some(cfg) = options.config { - load_cfg_as_global_cfg(&context, PathBuf::from(cfg)); - } else { - load_global_cfg(&context); - } - - // Store cmd duration in an env var - context.scope.add_env_var( - "CMD_DURATION_MS", - startup_commands_start_time - .elapsed() - .as_millis() - .to_string(), - ); - - if options.perf { - eprintln!( - "config loaded: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start(); - } - - //Configure rustyline - let mut rl = default_rustyline_editor_configuration(); - let history_path = if let Some(cfg) = &context.configs().lock().global_config { - let _ = configure_rustyline_editor(&mut rl, cfg); - let helper = Some(nu_line_editor_helper(&context, cfg)); - rl.set_helper(helper); - nu_data::config::path::history_path_or_default(cfg) - } else { - nu_data::config::path::default_history_path() - }; - - if options.perf { - eprintln!( - "rustyline configuration: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start(); - } - - // Don't load history if it's not necessary - if options.save_history { - let _ = rl.load_history(&history_path); - } - - if options.perf { - eprintln!( - "history load: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start(); - } - - //set vars from cfg if present - let (skip_welcome_message, prompt) = if let Some(cfg) = &context.configs().lock().global_config - { - ( - cfg.var("skip_welcome_message") - .map(|x| x.is_true()) - .unwrap_or(false), - cfg.var("prompt"), - ) - } else { - (false, None) - }; - - if options.perf { - eprintln!( - "load custom prompt: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .start(); - } - - //Check whether dir we start in contains local cfg file and if so load it. - load_local_cfg_if_present(&context); - - // Give ourselves a scope to work in - context.scope.enter_scope(); - - let mut session_text = String::new(); - let mut line_start: usize = 0; - - if !skip_welcome_message { - println!( - "Welcome to Nushell {} (type 'help' for more info)", - nu_command::commands::core_version() - ); - } - - #[cfg(windows)] - { - let _ = nu_ansi_term::enable_ansi_support(); - } - - let mut ctrlcbreak = false; - - if options.perf { - eprintln!( - "timing stopped. starting run loop: {:?}", - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .elapsed_split() - ); - STOPWATCH - .lock() - .expect("unable to lock the stopwatch") - .stop(); - } - - loop { - if context.ctrl_c().load(Ordering::SeqCst) { - context.ctrl_c().store(false, Ordering::SeqCst); - continue; - } - - let cwd = context.shell_manager().path(); - - // Check if the PROMPT_COMMAND env variable is set. This env variable - // contains nu code that is used to overwrite the prompt - let colored_prompt = match context.scope.get_env(PROMPT_COMMAND) { - Some(env_prompt) => evaluate_prompt_string(&env_prompt, &context, &cwd), - None => { - if let Some(prompt) = &prompt { - let prompt_line = prompt.as_string()?; - evaluate_prompt_string(&prompt_line, &context, &cwd) - } else { - default_prompt_string(&cwd) - } - } - }; - - let prompt = { - if let Ok(bytes) = strip_ansi_escapes::strip(&colored_prompt) { - String::from_utf8_lossy(&bytes).to_string() - } else { - "> ".to_string() - } - }; - - if let Some(helper) = rl.helper_mut() { - helper.colored_prompt = colored_prompt; - } - let mut initial_command = Some(String::new()); - let mut readline = Err(ReadlineError::Eof); - while let Some(ref cmd) = initial_command { - readline = rl.readline_with_initial(&prompt, (cmd, "")); - initial_command = None; - } - - if let Ok(line) = &readline { - line_start = session_text.len(); - session_text.push_str(line); - session_text.push('\n'); - } - - // start time for command duration - let cmd_start_time = std::time::Instant::now(); - - let line = match convert_rustyline_result_to_string(readline) { - LineResult::Success(_) => process_script( - &session_text[line_start..], - &context, - false, - line_start, - true, - ), - x => x, - }; - - // Store cmd duration in an env var - context.scope.add_env_var( - "CMD_DURATION_MS", - cmd_start_time.elapsed().as_millis().to_string(), - ); - - match line { - LineResult::Success(line) => { - if options.save_history && !line.trim().is_empty() { - rl.add_history_entry(&line); - let _ = rl.append_history(&history_path); - } - maybe_print_errors(&context, Text::from(session_text.clone())); - } - - LineResult::ClearHistory => { - if options.save_history { - rl.clear_history(); - std::fs::remove_file(&history_path)?; - } - } - - LineResult::Error(line, err) => { - if options.save_history && !line.trim().is_empty() { - rl.add_history_entry(&line); - let _ = rl.append_history(&history_path); - } - - context - .host() - .lock() - .print_err(err, &Text::from(session_text.clone())); - - // I am not so sure, we don't need maybe_print_errors here (as we printed an err - // above), because maybe_print_errors also clears the errors. - // TODO Analyze where above err comes from, and whether we need to clear - // context.errors here - // Or just be consistent and return errors always in context.errors... - maybe_print_errors(&context, Text::from(session_text.clone())); - } - - LineResult::CtrlC => { - let config_ctrlc_exit = context - .configs() - .lock() - .global_config - .as_ref() - .and_then(|cfg| cfg.var("ctrlc_exit")) - .map(|ctrl_c| ctrl_c.is_true()) - .unwrap_or(false); // default behavior is to allow CTRL-C spamming similar to other shells - - if !config_ctrlc_exit { - continue; - } - - if ctrlcbreak { - if options.save_history { - let _ = rl.append_history(&history_path); - } - std::process::exit(0); - } else { - context.with_host(|host| host.stdout("CTRL-C pressed (again to quit)")); - ctrlcbreak = true; - continue; - } - } - - LineResult::CtrlD => { - context.shell_manager().remove_at_current(); - if context.shell_manager().is_empty() { - break; - } - } - - LineResult::Break => { - break; - } - } - ctrlcbreak = false; - } - - // we are ok if we can not save history - if options.save_history { - let _ = rl.append_history(&history_path); - } - - Ok(()) -} - -#[cfg(feature = "rustyline-support")] -pub fn load_local_cfg_if_present(context: &EvaluationContext) { - trace!("Loading local cfg if present"); - match config::loadable_cfg_exists_in_dir(PathBuf::from(context.shell_manager().path())) { - Ok(Some(cfg_path)) => { - if let Err(err) = context.load_config(&ConfigPath::Local(cfg_path)) { - context.host().lock().print_err(err, &Text::from("")) - } - } - Err(e) => { - //Report error while checking for local cfg file - context.host().lock().print_err(e, &Text::from("")) - } - Ok(None) => { - //No local cfg file present in start dir - } - } -} - -fn load_cfg_as_global_cfg(context: &EvaluationContext, path: PathBuf) { - if let Err(err) = context.load_config(&ConfigPath::Global(path)) { - context.host().lock().print_err(err, &Text::from("")); - } -} - -pub fn load_global_cfg(context: &EvaluationContext) { - match config::default_path() { - Ok(path) => { - load_cfg_as_global_cfg(context, path); - } - Err(e) => { - context.host().lock().print_err(e, &Text::from("")); - } - } -} - -pub fn register_plugins(context: &EvaluationContext) -> Result<(), ShellError> { - if let Ok(plugins) = nu_engine::plugin::build_plugin::scan(search_paths()) { - context.add_commands( - plugins - .into_iter() - .filter(|p| !context.is_command_registered(p.name())) - .collect(), - ); - } - - Ok(()) -} - -pub fn parse_and_eval(line: &str, ctx: &EvaluationContext) -> Result { - // FIXME: do we still need this? - let line = if let Some(s) = line.strip_suffix('\n') { - s - } else { - line - }; - - // TODO ensure the command whose examples we're testing is actually in the pipeline - ctx.scope.enter_scope(); - let (classified_block, err) = nu_parser::parse(line, 0, &ctx.scope); - if let Some(err) = err { - ctx.scope.exit_scope(); - return Err(err.into()); - } - - let input_stream = InputStream::empty(); - - let result = run_block( - &classified_block, - ctx, - input_stream, - ExternalRedirection::Stdout, - ); - ctx.scope.exit_scope(); - - result?.collect_string(Tag::unknown()).map(|x| x.item) -} - -#[allow(dead_code)] -fn current_branch() -> String { - #[cfg(feature = "shadow-rs")] - { - Some(shadow_rs::branch()) - .map(|x| x.trim().to_string()) - .filter(|x| !x.is_empty()) - .map(|x| format!("({})", x)) - .unwrap_or_default() - } - #[cfg(not(feature = "shadow-rs"))] - { - "".to_string() - } -} diff --git a/old_nushell/crates/nu-cli/src/keybinding.rs b/old_nushell/crates/nu-cli/src/keybinding.rs deleted file mode 100644 index 0b90255ed..000000000 --- a/old_nushell/crates/nu-cli/src/keybinding.rs +++ /dev/null @@ -1,473 +0,0 @@ -use rustyline::{KeyCode as RustyKeyCode, Modifiers}; -use serde::{Deserialize, Serialize}; - -pub fn convert_keyevent(key_event: KeyCode, modifiers: Option) -> rustyline::KeyEvent { - match key_event { - KeyCode::UnknownEscSeq => convert_to_rl_keyevent(RustyKeyCode::UnknownEscSeq, modifiers), - KeyCode::Backspace => convert_to_rl_keyevent(RustyKeyCode::Backspace, modifiers), - KeyCode::BackTab => convert_to_rl_keyevent(RustyKeyCode::BackTab, modifiers), - KeyCode::BracketedPasteStart => { - convert_to_rl_keyevent(RustyKeyCode::BracketedPasteStart, modifiers) - } - KeyCode::BracketedPasteEnd => { - convert_to_rl_keyevent(RustyKeyCode::BracketedPasteEnd, modifiers) - } - KeyCode::Char(c) => convert_to_rl_keyevent(RustyKeyCode::Char(c), modifiers), - KeyCode::Delete => convert_to_rl_keyevent(RustyKeyCode::Delete, modifiers), - KeyCode::Down => convert_to_rl_keyevent(RustyKeyCode::Down, modifiers), - KeyCode::End => convert_to_rl_keyevent(RustyKeyCode::End, modifiers), - KeyCode::Enter => convert_to_rl_keyevent(RustyKeyCode::Enter, modifiers), - KeyCode::Esc => convert_to_rl_keyevent(RustyKeyCode::Esc, modifiers), - KeyCode::F(u) => convert_to_rl_keyevent(RustyKeyCode::F(u), modifiers), - KeyCode::Home => convert_to_rl_keyevent(RustyKeyCode::Home, modifiers), - KeyCode::Insert => convert_to_rl_keyevent(RustyKeyCode::Insert, modifiers), - KeyCode::Left => convert_to_rl_keyevent(RustyKeyCode::Left, modifiers), - KeyCode::Null => convert_to_rl_keyevent(RustyKeyCode::Null, modifiers), - KeyCode::PageDown => convert_to_rl_keyevent(RustyKeyCode::PageDown, modifiers), - KeyCode::PageUp => convert_to_rl_keyevent(RustyKeyCode::PageUp, modifiers), - KeyCode::Right => convert_to_rl_keyevent(RustyKeyCode::Right, modifiers), - KeyCode::Tab => convert_to_rl_keyevent(RustyKeyCode::Tab, modifiers), - KeyCode::Up => convert_to_rl_keyevent(RustyKeyCode::Up, modifiers), - } -} - -fn convert_to_rl_keyevent( - key_code: RustyKeyCode, - modifier: Option, -) -> rustyline::KeyEvent { - rustyline::KeyEvent { - 0: key_code, - 1: modifier.unwrap_or(Modifiers::NONE), - } -} - -fn convert_word(word: Word) -> rustyline::Word { - match word { - Word::Big => rustyline::Word::Big, - Word::Emacs => rustyline::Word::Emacs, - Word::Vi => rustyline::Word::Vi, - } -} - -fn convert_at(at: At) -> rustyline::At { - match at { - At::AfterEnd => rustyline::At::AfterEnd, - At::BeforeEnd => rustyline::At::BeforeEnd, - At::Start => rustyline::At::Start, - } -} - -fn convert_char_search(search: CharSearch) -> rustyline::CharSearch { - match search { - CharSearch::Backward(c) => rustyline::CharSearch::Backward(c), - CharSearch::BackwardAfter(c) => rustyline::CharSearch::BackwardAfter(c), - CharSearch::Forward(c) => rustyline::CharSearch::Forward(c), - CharSearch::ForwardBefore(c) => rustyline::CharSearch::ForwardBefore(c), - } -} - -fn convert_movement(movement: Movement) -> rustyline::Movement { - match movement { - Movement::BackwardChar(u) => rustyline::Movement::BackwardChar(u), - Movement::BackwardWord { repeat, word } => { - rustyline::Movement::BackwardWord(repeat, convert_word(word)) - } - Movement::BeginningOfBuffer => rustyline::Movement::BeginningOfBuffer, - Movement::BeginningOfLine => rustyline::Movement::BeginningOfLine, - Movement::EndOfBuffer => rustyline::Movement::EndOfBuffer, - Movement::EndOfLine => rustyline::Movement::EndOfLine, - Movement::ForwardChar(u) => rustyline::Movement::ForwardChar(u), - Movement::ForwardWord { repeat, at, word } => { - rustyline::Movement::ForwardWord(repeat, convert_at(at), convert_word(word)) - } - Movement::LineDown(u) => rustyline::Movement::LineDown(u), - Movement::LineUp(u) => rustyline::Movement::LineUp(u), - Movement::ViCharSearch { repeat, search } => { - rustyline::Movement::ViCharSearch(repeat, convert_char_search(search)) - } - Movement::ViFirstPrint => rustyline::Movement::ViFirstPrint, - Movement::WholeBuffer => rustyline::Movement::WholeBuffer, - Movement::WholeLine => rustyline::Movement::WholeLine, - } -} - -fn convert_anchor(anchor: Anchor) -> rustyline::Anchor { - match anchor { - Anchor::After => rustyline::Anchor::After, - Anchor::Before => rustyline::Anchor::Before, - } -} - -fn convert_cmd(cmd: Cmd) -> rustyline::Cmd { - match cmd { - Cmd::Abort => rustyline::Cmd::Abort, - Cmd::AcceptLine => rustyline::Cmd::AcceptLine, - Cmd::AcceptOrInsertLine => rustyline::Cmd::AcceptOrInsertLine { - accept_in_the_middle: false, - }, - Cmd::BeginningOfHistory => rustyline::Cmd::BeginningOfHistory, - Cmd::CapitalizeWord => rustyline::Cmd::CapitalizeWord, - Cmd::ClearScreen => rustyline::Cmd::ClearScreen, - Cmd::Complete => rustyline::Cmd::Complete, - Cmd::CompleteBackward => rustyline::Cmd::CompleteBackward, - Cmd::CompleteHint => rustyline::Cmd::CompleteHint, - Cmd::Dedent(movement) => rustyline::Cmd::Dedent(convert_movement(movement)), - Cmd::DowncaseWord => rustyline::Cmd::DowncaseWord, - Cmd::EndOfFile => rustyline::Cmd::EndOfFile, - Cmd::EndOfHistory => rustyline::Cmd::EndOfHistory, - Cmd::ForwardSearchHistory => rustyline::Cmd::ForwardSearchHistory, - Cmd::HistorySearchBackward => rustyline::Cmd::HistorySearchBackward, - Cmd::HistorySearchForward => rustyline::Cmd::HistorySearchForward, - Cmd::Indent(movement) => rustyline::Cmd::Indent(convert_movement(movement)), - Cmd::Insert { repeat, string } => rustyline::Cmd::Insert(repeat, string), - Cmd::Interrupt => rustyline::Cmd::Interrupt, - Cmd::Kill(movement) => rustyline::Cmd::Kill(convert_movement(movement)), - Cmd::LineDownOrNextHistory(u) => rustyline::Cmd::LineDownOrNextHistory(u), - Cmd::LineUpOrPreviousHistory(u) => rustyline::Cmd::LineUpOrPreviousHistory(u), - Cmd::Move(movement) => rustyline::Cmd::Move(convert_movement(movement)), - Cmd::NextHistory => rustyline::Cmd::NextHistory, - Cmd::Newline => rustyline::Cmd::Newline, - Cmd::Noop => rustyline::Cmd::Noop, - Cmd::Overwrite(c) => rustyline::Cmd::Overwrite(c), - #[cfg(windows)] - Cmd::PasteFromClipboard => rustyline::Cmd::PasteFromClipboard, - Cmd::PreviousHistory => rustyline::Cmd::PreviousHistory, - Cmd::QuotedInsert => rustyline::Cmd::QuotedInsert, - Cmd::Replace { - movement, - replacement, - } => rustyline::Cmd::Replace(convert_movement(movement), replacement), - Cmd::ReplaceChar { repeat, ch } => rustyline::Cmd::ReplaceChar(repeat, ch), - Cmd::ReverseSearchHistory => rustyline::Cmd::ReverseSearchHistory, - Cmd::SelfInsert { repeat, ch } => rustyline::Cmd::SelfInsert(repeat, ch), - Cmd::Suspend => rustyline::Cmd::Suspend, - Cmd::TransposeChars => rustyline::Cmd::TransposeChars, - Cmd::TransposeWords(u) => rustyline::Cmd::TransposeWords(u), - Cmd::Undo(u) => rustyline::Cmd::Undo(u), - Cmd::Unknown => rustyline::Cmd::Unknown, - Cmd::UpcaseWord => rustyline::Cmd::UpcaseWord, - Cmd::ViYankTo(movement) => rustyline::Cmd::ViYankTo(convert_movement(movement)), - Cmd::Yank { repeat, anchor } => rustyline::Cmd::Yank(repeat, convert_anchor(anchor)), - Cmd::YankPop => rustyline::Cmd::YankPop, - } -} - -fn convert_keybinding(keybinding: Keybinding) -> (rustyline::KeyEvent, rustyline::Cmd) { - let rusty_modifiers = match keybinding.modifiers { - Some(mods) => match mods { - NuModifiers::Ctrl => Some(Modifiers::CTRL), - NuModifiers::Alt => Some(Modifiers::ALT), - NuModifiers::Shift => Some(Modifiers::SHIFT), - NuModifiers::None => Some(Modifiers::NONE), - NuModifiers::CtrlShift => Some(Modifiers::CTRL_SHIFT), - NuModifiers::AltShift => Some(Modifiers::ALT_SHIFT), - NuModifiers::CtrlAlt => Some(Modifiers::CTRL_ALT), - NuModifiers::CtrlAltShift => Some(Modifiers::CTRL_ALT_SHIFT), - // _ => None, - }, - None => None, - }; - ( - convert_keyevent(keybinding.key, rusty_modifiers), - convert_cmd(keybinding.binding), - ) -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum KeyCode { - /// Unsupported escape sequence (on unix platform) - UnknownEscSeq, - /// ⌫ or `KeyEvent::Ctrl('H')` - Backspace, - /// ⇤ (usually Shift-Tab) - BackTab, - /// Paste (on unix platform) - BracketedPasteStart, - /// Paste (on unix platform) - BracketedPasteEnd, - /// Single char - Char(char), - /// ⌦ - Delete, - /// ↓ arrow key - Down, - /// ⇲ - End, - /// ↵ or `KeyEvent::Ctrl('M')` - Enter, - /// Escape or `KeyEvent::Ctrl('[')` - Esc, - /// Function key - F(u8), - /// ⇱ - Home, - /// Insert key - Insert, - /// ← arrow key - Left, - // /// `KeyEvent::Char('\0')` - Null, - /// ⇟ - PageDown, - /// ⇞ - PageUp, - /// → arrow key - Right, - /// ⇥ or `KeyEvent::Ctrl('I')` - Tab, - /// ↑ arrow key - Up, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum Cmd { - /// abort - Abort, // Miscellaneous Command - /// accept-line - AcceptLine, - /// beginning-of-history - BeginningOfHistory, - /// capitalize-word - CapitalizeWord, - /// clear-screen - ClearScreen, - /// complete - Complete, - /// complete-backward - CompleteBackward, - /// complete-hint - CompleteHint, - /// Dedent current line - Dedent(Movement), - /// downcase-word - DowncaseWord, - /// vi-eof-maybe - EndOfFile, - /// end-of-history - EndOfHistory, - /// forward-search-history - ForwardSearchHistory, - /// history-search-backward - HistorySearchBackward, - /// history-search-forward - HistorySearchForward, - /// Indent current line - Indent(Movement), - /// Insert text - Insert { repeat: RepeatCount, string: String }, - /// Interrupt signal (Ctrl-C) - Interrupt, - /// backward-delete-char, backward-kill-line, backward-kill-word - /// delete-char, kill-line, kill-word, unix-line-discard, unix-word-rubout, - /// vi-delete, vi-delete-to, vi-rubout - Kill(Movement), - /// backward-char, backward-word, beginning-of-line, end-of-line, - /// forward-char, forward-word, vi-char-search, vi-end-word, vi-next-word, - /// vi-prev-word - Move(Movement), - /// Inserts a newline - Newline, - /// next-history - NextHistory, - /// No action - Noop, - /// vi-replace - Overwrite(char), - /// Paste from the clipboard - #[cfg(windows)] - PasteFromClipboard, - /// previous-history - PreviousHistory, - /// quoted-insert - QuotedInsert, - /// vi-change-char - ReplaceChar { repeat: RepeatCount, ch: char }, - /// vi-change-to, vi-substitute - Replace { - movement: Movement, - replacement: Option, - }, - /// reverse-search-history - ReverseSearchHistory, - /// self-insert - SelfInsert { repeat: RepeatCount, ch: char }, - /// Suspend signal (Ctrl-Z on unix platform) - Suspend, - /// transpose-chars - TransposeChars, - /// transpose-words - TransposeWords(RepeatCount), - /// undo - Undo(RepeatCount), - /// Unsupported / unexpected - Unknown, - /// upcase-word - UpcaseWord, - /// vi-yank-to - ViYankTo(Movement), - /// yank, vi-put - Yank { repeat: RepeatCount, anchor: Anchor }, - /// yank-pop - YankPop, - /// moves cursor to the line above or switches to prev history entry if - /// the cursor is already on the first line - LineUpOrPreviousHistory(RepeatCount), - /// moves cursor to the line below or switches to next history entry if - /// the cursor is already on the last line - LineDownOrNextHistory(RepeatCount), - /// accepts the line when cursor is at the end of the text (non including - /// trailing whitespace), inserts newline character otherwise - AcceptOrInsertLine, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum Movement { - /// Whole current line (not really a movement but a range) - WholeLine, - /// beginning-of-line - BeginningOfLine, - /// end-of-line - EndOfLine, - /// backward-word, vi-prev-word - BackwardWord { repeat: RepeatCount, word: Word }, // Backward until start of word - /// forward-word, vi-end-word, vi-next-word - ForwardWord { - repeat: RepeatCount, - at: At, - word: Word, - }, // Forward until start/end of word - /// vi-char-search - ViCharSearch { - repeat: RepeatCount, - search: CharSearch, - }, - /// vi-first-print - ViFirstPrint, - /// backward-char - BackwardChar(RepeatCount), - /// forward-char - ForwardChar(RepeatCount), - /// move to the same column on the previous line - LineUp(RepeatCount), - /// move to the same column on the next line - LineDown(RepeatCount), - /// Whole user input (not really a movement but a range) - WholeBuffer, - /// beginning-of-buffer - BeginningOfBuffer, - /// end-of-buffer - EndOfBuffer, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -enum InputMode { - /// Vi Command/Alternate - Command, - /// Insert/Input mode - Insert, - /// Overwrite mode - Replace, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum Word { - /// non-blanks characters - Big, - /// alphanumeric characters - Emacs, - /// alphanumeric (and '_') characters - Vi, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum At { - /// Start of word. - Start, - /// Before end of word. - BeforeEnd, - /// After end of word. - AfterEnd, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum Anchor { - /// After cursor - After, - /// Before cursor - Before, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum CharSearch { - /// Forward search - Forward(char), - /// Forward search until - ForwardBefore(char), - /// Backward search - Backward(char), - /// Backward search until - BackwardAfter(char), -} - -/// The set of modifier keys that were triggered along with a key press. -#[derive(Debug, Serialize, Deserialize)] -#[allow(non_camel_case_types)] -pub enum NuModifiers { - /// Control modifier - #[serde(alias = "CTRL")] - Ctrl = 8, - /// Escape or Alt modifier - #[serde(alias = "ALT")] - Alt = 4, - /// Shift modifier - #[serde(alias = "SHIFT")] - Shift = 2, - /// No modifier - #[serde(alias = "NONE")] - None = 0, - /// Ctrl + Shift - #[serde(alias = "CTRL_SHIFT")] - CtrlShift = 10, - /// Alt + Shift - #[serde(alias = "ALT_SHIFT")] - AltShift = 6, - /// Ctrl + Alt - #[serde(alias = "CTRL_ALT")] - CtrlAlt = 12, - /// Ctrl + Alt + Shift - #[serde(alias = "CTRL_ALT_SHIFT")] - CtrlAltShift = 14, -} - -/// The number of times one command should be repeated. -pub type RepeatCount = usize; - -#[derive(Debug, Serialize, Deserialize)] -pub struct Keybinding { - key: KeyCode, - modifiers: Option, - binding: Cmd, -} - -type Keybindings = Vec; - -pub(crate) fn load_keybindings( - rl: &mut rustyline::Editor, -) -> Result<(), nu_errors::ShellError> { - let filename = nu_data::keybinding::keybinding_path()?; - let contents = std::fs::read_to_string(filename); - - // Silently fail if there is no file there - if let Ok(contents) = contents { - let keybindings: Keybindings = serde_yaml::from_str(&contents)?; - // eprintln!("{:#?}", keybindings); - for keybinding in keybindings { - let (k, b) = convert_keybinding(keybinding); - // eprintln!("{:?} {:?}", k, b); - - rl.bind_sequence(k, b); - } - } - - Ok(()) -} diff --git a/old_nushell/crates/nu-cli/src/lib.rs b/old_nushell/crates/nu-cli/src/lib.rs deleted file mode 100644 index 4b3e2fb93..000000000 --- a/old_nushell/crates/nu-cli/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub mod app; -mod cli; -#[cfg(feature = "rustyline-support")] -mod keybinding; -mod line_editor; -#[cfg(feature = "rustyline-support")] -mod shell; - -#[cfg(feature = "rustyline-support")] -pub use crate::cli::cli; - -pub use crate::app::App; -pub use crate::cli::{parse_and_eval, register_plugins, run_script_file}; - -pub use nu_command::create_default_context; diff --git a/old_nushell/crates/nu-cli/src/line_editor.rs b/old_nushell/crates/nu-cli/src/line_editor.rs deleted file mode 100644 index 7c36021b8..000000000 --- a/old_nushell/crates/nu-cli/src/line_editor.rs +++ /dev/null @@ -1,276 +0,0 @@ -use nu_engine::EvaluationContext; -use nu_errors::ShellError; -use std::error::Error; - -#[allow(unused_imports)] -use std::sync::atomic::Ordering; - -#[allow(unused_imports)] -use nu_engine::script::LineResult; - -#[cfg(feature = "rustyline-support")] -use crate::keybinding::{convert_keyevent, KeyCode}; - -#[cfg(feature = "rustyline-support")] -use crate::shell::Helper; - -#[cfg(feature = "rustyline-support")] -use rustyline::{ - self, - config::Configurer, - config::{ColorMode, CompletionType, Config}, - error::ReadlineError, - line_buffer::LineBuffer, - At, Cmd, ConditionalEventHandler, Editor, EventHandler, Modifiers, Movement, Word, -}; - -#[cfg(feature = "rustyline-support")] -pub fn convert_rustyline_result_to_string(input: Result) -> LineResult { - match input { - Ok(s) if s == "history -c" || s == "history --clear" => LineResult::ClearHistory, - Ok(s) => LineResult::Success(s), - Err(ReadlineError::Interrupted) => LineResult::CtrlC, - Err(ReadlineError::Eof) => LineResult::CtrlD, - Err(err) => { - eprintln!("Error: {:?}", err); - LineResult::Break - } - } -} - -#[derive(Clone)] -#[cfg(feature = "rustyline-support")] -struct PartialCompleteHintHandler; - -#[cfg(feature = "rustyline-support")] -impl ConditionalEventHandler for PartialCompleteHintHandler { - fn handle( - &self, - _evt: &rustyline::Event, - _n: rustyline::RepeatCount, - _positive: bool, - ctx: &rustyline::EventContext, - ) -> Option { - Some(match ctx.hint_text() { - Some(hint_text) if ctx.pos() == ctx.line().len() => { - let mut line_buffer = LineBuffer::with_capacity(hint_text.len()); - line_buffer.update(hint_text, 0); - line_buffer.move_to_next_word(At::AfterEnd, Word::Vi, 1); - - let text = hint_text[0..line_buffer.pos()].to_string(); - - Cmd::Insert(1, text) - } - _ => Cmd::Move(Movement::ForwardWord(1, At::AfterEnd, Word::Vi)), - }) - } -} - -#[cfg(feature = "rustyline-support")] -pub fn default_rustyline_editor_configuration() -> Editor { - #[cfg(windows)] - const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::Circular; - #[cfg(not(windows))] - const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::List; - - let config = Config::builder() - .check_cursor_position(true) - .color_mode(ColorMode::Forced) - .history_ignore_dups(false) - .max_history_size(10_000) - .build(); - let mut rl: Editor<_> = Editor::with_config(config); - - // add key bindings to move over a whole word with Ctrl+ArrowLeft and Ctrl+ArrowRight - //M modifier, E KeyEvent, K KeyCode - rl.bind_sequence( - convert_keyevent(KeyCode::Left, Some(Modifiers::CTRL)), - Cmd::Move(Movement::BackwardWord(1, Word::Vi)), - ); - - rl.bind_sequence( - convert_keyevent(KeyCode::Right, Some(Modifiers::CTRL)), - EventHandler::Conditional(Box::new(PartialCompleteHintHandler)), - ); - - // workaround for multiline-paste hang in rustyline (see https://github.com/kkawakam/rustyline/issues/202) - rl.bind_sequence( - convert_keyevent(KeyCode::BracketedPasteStart, None), - rustyline::Cmd::Noop, - ); - // Let's set the defaults up front and then override them later if the user indicates - // defaults taken from here https://github.com/kkawakam/rustyline/blob/2fe886c9576c1ea13ca0e5808053ad491a6fe049/src/config.rs#L150-L167 - rl.set_max_history_size(100); - rl.set_history_ignore_dups(true); - rl.set_history_ignore_space(false); - rl.set_completion_type(DEFAULT_COMPLETION_MODE); - rl.set_completion_prompt_limit(100); - rl.set_keyseq_timeout(-1); - rl.set_edit_mode(rustyline::config::EditMode::Emacs); - rl.set_auto_add_history(false); - rl.set_bell_style(rustyline::config::BellStyle::default()); - rl.set_color_mode(rustyline::ColorMode::Enabled); - rl.set_tab_stop(8); - - if let Err(e) = crate::keybinding::load_keybindings(&mut rl) { - println!("Error loading keybindings: {:?}", e); - } - - rl -} - -#[cfg(feature = "rustyline-support")] -pub fn configure_rustyline_editor( - rl: &mut Editor, - config: &dyn nu_data::config::Conf, -) -> Result<(), ShellError> { - #[cfg(windows)] - const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::Circular; - #[cfg(not(windows))] - const DEFAULT_COMPLETION_MODE: CompletionType = CompletionType::List; - - if let Some(line_editor_vars) = config.var("line_editor") { - for (idx, value) in line_editor_vars.row_entries() { - match idx.as_ref() { - "max_history_size" => { - if let Ok(max_history_size) = value.as_u64() { - rl.set_max_history_size(max_history_size as usize); - } - } - "history_duplicates" => { - // history_duplicates = match value.as_string() { - // Ok(s) if s.to_lowercase() == "alwaysadd" => { - // rustyline::config::HistoryDuplicates::AlwaysAdd - // } - // Ok(s) if s.to_lowercase() == "ignoreconsecutive" => { - // rustyline::config::HistoryDuplicates::IgnoreConsecutive - // } - // _ => rustyline::config::HistoryDuplicates::AlwaysAdd, - // }; - if let Ok(history_duplicates) = value.as_bool() { - rl.set_history_ignore_dups(history_duplicates); - } - } - "history_ignore_space" => { - if let Ok(history_ignore_space) = value.as_bool() { - rl.set_history_ignore_space(history_ignore_space); - } - } - "completion_type" => { - let completion_type = match value.as_string() { - Ok(s) if s.to_lowercase() == "circular" => { - rustyline::config::CompletionType::Circular - } - Ok(s) if s.to_lowercase() == "list" => { - rustyline::config::CompletionType::List - } - #[cfg(all(unix, feature = "with-fuzzy"))] - Ok(s) if s.to_lowercase() == "fuzzy" => { - rustyline::config::CompletionType::Fuzzy - } - _ => DEFAULT_COMPLETION_MODE, - }; - rl.set_completion_type(completion_type); - } - "completion_prompt_limit" => { - if let Ok(completion_prompt_limit) = value.as_u64() { - rl.set_completion_prompt_limit(completion_prompt_limit as usize); - } - } - "keyseq_timeout_ms" => { - if let Ok(keyseq_timeout_ms) = value.as_u64() { - rl.set_keyseq_timeout(keyseq_timeout_ms as i32); - } - } - "edit_mode" => { - let edit_mode = match value.as_string() { - Ok(s) if s.to_lowercase() == "vi" => rustyline::config::EditMode::Vi, - Ok(s) if s.to_lowercase() == "emacs" => rustyline::config::EditMode::Emacs, - _ => rustyline::config::EditMode::Emacs, - }; - rl.set_edit_mode(edit_mode); - // Note: When edit_mode is Emacs, the keyseq_timeout_ms is set to -1 - // no matter what you may have configured. This is so that key chords - // can be applied without having to do them in a given timeout. So, - // it essentially turns off the keyseq timeout. - } - "auto_add_history" => { - if let Ok(auto_add_history) = value.as_bool() { - rl.set_auto_add_history(auto_add_history); - } - } - "bell_style" => { - let bell_style = match value.as_string() { - Ok(s) if s.to_lowercase() == "audible" => { - rustyline::config::BellStyle::Audible - } - Ok(s) if s.to_lowercase() == "none" => rustyline::config::BellStyle::None, - Ok(s) if s.to_lowercase() == "visible" => { - rustyline::config::BellStyle::Visible - } - _ => rustyline::config::BellStyle::default(), - }; - rl.set_bell_style(bell_style); - } - "color_mode" => { - let color_mode = match value.as_string() { - Ok(s) if s.to_lowercase() == "enabled" => rustyline::ColorMode::Enabled, - Ok(s) if s.to_lowercase() == "forced" => rustyline::ColorMode::Forced, - Ok(s) if s.to_lowercase() == "disabled" => rustyline::ColorMode::Disabled, - _ => rustyline::ColorMode::Enabled, - }; - rl.set_color_mode(color_mode); - } - "tab_stop" => { - if let Ok(tab_stop) = value.as_u64() { - rl.set_tab_stop(tab_stop as usize); - } - } - _ => (), - } - } - } - - Ok(()) -} - -#[cfg(feature = "rustyline-support")] -pub fn nu_line_editor_helper( - context: &EvaluationContext, - config: &dyn nu_data::config::Conf, -) -> crate::shell::Helper { - let hinter = rustyline_hinter(config); - crate::shell::Helper::new(context.clone(), hinter) -} - -#[cfg(feature = "rustyline-support")] -pub fn rustyline_hinter( - config: &dyn nu_data::config::Conf, -) -> Option { - if let Some(line_editor_vars) = config.var("line_editor") { - for (idx, value) in line_editor_vars.row_entries() { - if idx == "show_hints" && value.as_bool() == Ok(false) { - return None; - } - } - } - - Some(rustyline::hint::HistoryHinter {}) -} - -pub fn configure_ctrl_c(_context: &EvaluationContext) -> Result<(), Box> { - #[cfg(feature = "ctrlc")] - { - let cc = _context.ctrl_c().clone(); - - ctrlc::set_handler(move || { - cc.store(true, Ordering::SeqCst); - })?; - - if _context.ctrl_c().load(Ordering::SeqCst) { - _context.ctrl_c().store(false, Ordering::SeqCst); - } - } - - Ok(()) -} diff --git a/old_nushell/crates/nu-cli/src/shell.rs b/old_nushell/crates/nu-cli/src/shell.rs deleted file mode 100644 index ce7ef7a3a..000000000 --- a/old_nushell/crates/nu-cli/src/shell.rs +++ /dev/null @@ -1,234 +0,0 @@ -use nu_ansi_term::Color; -use nu_completion::NuCompleter; -use nu_engine::{DefaultPalette, EvaluationContext, Painter}; -use nu_source::{Tag, Tagged}; -use std::borrow::Cow::{self, Owned}; - -pub struct Helper { - completer: NuCompleter, - hinter: Option, - context: EvaluationContext, - pub colored_prompt: String, - validator: NuValidator, -} - -impl Helper { - pub(crate) fn new( - context: EvaluationContext, - hinter: Option, - ) -> Helper { - Helper { - completer: NuCompleter {}, - hinter, - context, - colored_prompt: String::new(), - validator: NuValidator {}, - } - } -} - -use nu_protocol::{SignatureRegistry, VariableRegistry}; -struct CompletionContext<'a>(&'a EvaluationContext); - -impl<'a> nu_completion::CompletionContext for CompletionContext<'a> { - fn signature_registry(&self) -> &dyn SignatureRegistry { - &self.0.scope - } - - fn scope(&self) -> &dyn nu_parser::ParserScope { - &self.0.scope - } - - fn source(&self) -> &EvaluationContext { - self.as_ref() - } - - fn variable_registry(&self) -> &dyn VariableRegistry { - self.0 - } -} - -impl<'a> AsRef for CompletionContext<'a> { - fn as_ref(&self) -> &EvaluationContext { - self.0 - } -} - -pub struct CompletionSuggestion(nu_completion::Suggestion); - -impl rustyline::completion::Candidate for CompletionSuggestion { - fn display(&self) -> &str { - &self.0.display - } - - fn replacement(&self) -> &str { - &self.0.replacement - } -} - -impl rustyline::completion::Completer for Helper { - type Candidate = CompletionSuggestion; - - fn complete( - &self, - line: &str, - pos: usize, - _ctx: &rustyline::Context<'_>, - ) -> Result<(usize, Vec), rustyline::error::ReadlineError> { - let ctx = CompletionContext(&self.context); - let (position, suggestions) = self.completer.complete(line, pos, &ctx); - let suggestions = suggestions.into_iter().map(CompletionSuggestion).collect(); - Ok((position, suggestions)) - } - - fn update(&self, line: &mut rustyline::line_buffer::LineBuffer, start: usize, elected: &str) { - let end = line.pos(); - line.replace(start..end, elected) - } -} - -impl rustyline::hint::Hinter for Helper { - type Hint = String; - fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option { - match &self.hinter { - Some(the_hinter) => the_hinter.hint(line, pos, ctx), - None => Some("".to_string()), - } - } -} - -impl rustyline::highlight::Highlighter for Helper { - fn highlight_prompt<'b, 's: 'b, 'p: 'b>( - &'s self, - prompt: &'p str, - default: bool, - ) -> Cow<'b, str> { - use std::borrow::Cow::Borrowed; - - if default { - Borrowed(&self.colored_prompt) - } else { - Borrowed(prompt) - } - } - - fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { - Owned(Color::DarkGray.prefix().to_string() + hint + nu_ansi_term::ansi::RESET) - } - - fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> { - let cfg = &self.context.configs().lock(); - if let Some(palette) = &cfg.syntax_config { - Painter::paint_string(line, &self.context.scope, palette) - } else { - Painter::paint_string(line, &self.context.scope, &DefaultPalette {}) - } - } - - fn highlight_char(&self, _line: &str, _pos: usize) -> bool { - true - } -} - -impl rustyline::validate::Validator for Helper { - fn validate( - &self, - ctx: &mut rustyline::validate::ValidationContext, - ) -> rustyline::Result { - self.validator.validate(ctx) - } - - fn validate_while_typing(&self) -> bool { - self.validator.validate_while_typing() - } -} - -struct NuValidator {} - -impl rustyline::validate::Validator for NuValidator { - fn validate( - &self, - ctx: &mut rustyline::validate::ValidationContext, - ) -> rustyline::Result { - let src = ctx.input(); - - let (tokens, err) = nu_parser::lex(src, 0, nu_parser::NewlineMode::Normal); - if let Some(err) = err { - if let nu_errors::ParseErrorReason::Eof { .. } = err.reason() { - return Ok(rustyline::validate::ValidationResult::Incomplete); - } - } - - let (_, err) = nu_parser::parse_block(tokens); - - if let Some(err) = err { - if let nu_errors::ParseErrorReason::Eof { .. } = err.reason() { - return Ok(rustyline::validate::ValidationResult::Incomplete); - } - } - - Ok(rustyline::validate::ValidationResult::Valid(None)) - } -} - -#[allow(unused)] -fn vec_tag(input: Vec>) -> Option { - let mut iter = input.iter(); - let first = iter.next()?.tag.clone(); - let last = iter.last(); - - Some(match last { - None => first, - Some(last) => first.until(&last.tag), - }) -} - -impl rustyline::Helper for Helper {} - -#[cfg(test)] -mod tests { - use super::*; - use nu_engine::EvaluationContext; - use rustyline::completion::Completer; - use rustyline::line_buffer::LineBuffer; - - #[ignore] - #[test] - fn closing_quote_should_replaced() { - let text = "cd \"folder with spaces\\subdirectory\\\""; - let replacement = "\"folder with spaces\\subdirectory\\subsubdirectory\\\""; - - let mut buffer = LineBuffer::with_capacity(256); - buffer.insert_str(0, text); - buffer.set_pos(text.len() - 1); - - let helper = Helper::new(EvaluationContext::basic(), None); - - helper.update(&mut buffer, "cd ".len(), replacement); - - assert_eq!( - buffer.as_str(), - "cd \"folder with spaces\\subdirectory\\subsubdirectory\\\"" - ); - } - - #[ignore] - #[test] - fn replacement_with_cursor_in_text() { - let text = "cd \"folder with spaces\\subdirectory\\\""; - let replacement = "\"folder with spaces\\subdirectory\\subsubdirectory\\\""; - - let mut buffer = LineBuffer::with_capacity(256); - buffer.insert_str(0, text); - buffer.set_pos(text.len() - 30); - - let helper = Helper::new(EvaluationContext::basic(), None); - - helper.update(&mut buffer, "cd ".len(), replacement); - - assert_eq!( - buffer.as_str(), - "cd \"folder with spaces\\subdirectory\\subsubdirectory\\\"" - ); - } -} diff --git a/old_nushell/crates/nu-command/Cargo.toml b/old_nushell/crates/nu-command/Cargo.toml deleted file mode 100644 index 943bc4480..000000000 --- a/old_nushell/crates/nu-command/Cargo.toml +++ /dev/null @@ -1,122 +0,0 @@ -[package] -authors = ["The Nu Project Contributors"] -build = "build.rs" -description = "Commands for Nushell" -edition = "2018" -license = "MIT" -name = "nu-command" -version = "0.43.0" - -[lib] -doctest = false - -[dependencies] -nu-data = { version = "0.43.0", path="../nu-data" } -nu-engine = { version = "0.43.0", path="../nu-engine" } -nu-errors = { version = "0.43.0", path="../nu-errors" } -nu-json = { version = "0.43.0", path="../nu-json" } -nu-path = { version = "0.43.0", path="../nu-path" } -nu-parser = { version = "0.43.0", path="../nu-parser" } -nu-plugin = { version = "0.43.0", path="../nu-plugin" } -nu-protocol = { version = "0.43.0", path="../nu-protocol" } -nu-serde = { version = "0.43.0", path="../nu-serde" } -nu-source = { version = "0.43.0", path="../nu-source" } -nu-stream = { version = "0.43.0", path="../nu-stream" } -nu-table = { version = "0.43.0", path="../nu-table" } -nu-test-support = { version = "0.43.0", path="../nu-test-support" } -nu-value-ext = { version = "0.43.0", path="../nu-value-ext" } -nu-ansi-term = { version = "0.43.0", path="../nu-ansi-term" } -nu-pretty-hex = { version = "0.43.0", path="../nu-pretty-hex" } - -url = "2.2.1" -mime = "0.3.16" -heck = "0.4.0" -base64 = "0.13.0" -bigdecimal = { version = "0.3.0", features = ["serde"] } -calamine = "0.18.0" -chrono = { version="0.4.19", features=["serde"] } -chrono-tz = "0.5.3" -crossterm = { version="0.19.0", optional=true } -csv = "1.1.3" -ctrlc = { version="3.1.7", optional=true } -derive-new = "0.5.8" -dirs-next = "2.0.0" -dtparse = "1.2.0" -eml-parser = "0.1.0" -encoding_rs = "0.8.28" -filesize = "0.2.0" -futures = { version="0.3.12", features=["compat", "io-compat"] } -glob = "0.3.0" -htmlescape = "0.3.1" -ical = "0.7.0" -indexmap = { version="1.7", features=["serde-1"] } -itertools = "0.10.0" -lazy_static = "1.*" -log = "0.4.14" -md-5 = "0.9.1" -meval = "0.2.0" -num-bigint = { version="0.4.3", features=["serde"] } -num-format = { version="0.4.0", features=["with-num-bigint"] } -num-traits = "0.2.14" -parking_lot = "0.11.1" -quick-xml = "0.22" -rand = "0.8" -regex = "1.4.3" -reqwest = {version = "0.11", optional = true } -roxmltree = "0.14.0" -rust-embed = "5.9.0" -rustyline = { version="9.0.0", optional=true } -serde = { version="1.0.123", features=["derive"] } -serde_ini = "0.2.0" -serde_json = "1.0.61" -serde_urlencoded = "0.7.0" -serde_yaml = "0.8.16" -sha2 = "0.9.3" -strip-ansi-escapes = "0.1.0" -sysinfo = { version = "0.23.0", optional = true } -thiserror = "1.0.26" -term = { version="0.7.0", optional=true } -term_size = "0.3.2" -titlecase = "1.1.0" -tokio = { version = "1", features = ["rt-multi-thread"], optional = true } -toml = "0.5.8" -trash = { version = "2.0.2", optional = true } -unicode-segmentation = "1.8" -uuid_crate = { package="uuid", version="0.8.2", features=["v4"], optional=true } -which = { version="4.1.0", optional=true } -zip = { version="0.5.9", optional=true } -digest = "0.9.0" - -[dependencies.polars] -version = "0.17.0" -optional = true -default-features = false -features = ["docs", "zip_with", "csv-file", "temporal", "performant", "pretty_fmt", "dtype-slim", "parquet", "json", "random", "pivot", "strings", "is_in", "cum_agg", "rolling_window"] - -[target.'cfg(unix)'.dependencies] -umask = "1.0.0" -users = "0.11.0" - -# TODO this will be possible with new dependency resolver -# (currently on nightly behind -Zfeatures=itarget): -# https://github.com/rust-lang/cargo/issues/7914 -# [target.'cfg(not(windows))'.dependencies] -# num-format = { version = "0.4", features = ["with-system-locale"] } - -[build-dependencies] -shadow-rs = "0.8.1" - -[dev-dependencies] -quickcheck = "1.0.3" -quickcheck_macros = "1.0.0" -hamcrest2 = "0.3.0" - -[features] -rustyline-support = ["rustyline"] -stable = [] -trash-support = ["trash"] -dataframe = ["nu-protocol/dataframe", "polars"] -fetch = ["reqwest", "tokio"] -post = ["reqwest", "tokio"] -sys = ["sysinfo"] -ps = ["sysinfo"] diff --git a/old_nushell/crates/nu-command/README.md b/old_nushell/crates/nu-command/README.md deleted file mode 100644 index b9f0857cb..000000000 --- a/old_nushell/crates/nu-command/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# nu-command - -The Nu command crate contains the full set of internal commands, that is, the commands that can be form the set of built-in commands in a Nushell engine. - -The default set of commands that Nushell ships with can be found in the [default context](src/default_context.rs). - -The commands themselves live in the [commands module](src/commands/). diff --git a/old_nushell/crates/nu-command/assets/228_themes.zip b/old_nushell/crates/nu-command/assets/228_themes.zip deleted file mode 100644 index eca629d50..000000000 Binary files a/old_nushell/crates/nu-command/assets/228_themes.zip and /dev/null differ diff --git a/old_nushell/crates/nu-command/build.rs b/old_nushell/crates/nu-command/build.rs deleted file mode 100644 index 4a0dfc459..000000000 --- a/old_nushell/crates/nu-command/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() -> shadow_rs::SdResult<()> { - shadow_rs::new() -} diff --git a/old_nushell/crates/nu-command/src/args.rs b/old_nushell/crates/nu-command/src/args.rs deleted file mode 100644 index 2e6961888..000000000 --- a/old_nushell/crates/nu-command/src/args.rs +++ /dev/null @@ -1,10 +0,0 @@ -use nu_protocol::Value; - -#[derive(Debug)] -pub enum LogLevel {} - -#[derive(Debug)] -pub struct LogItem { - level: LogLevel, - value: Value, -} diff --git a/old_nushell/crates/nu-command/src/classified/external.rs b/old_nushell/crates/nu-command/src/classified/external.rs deleted file mode 100644 index 716d830a2..000000000 --- a/old_nushell/crates/nu-command/src/classified/external.rs +++ /dev/null @@ -1,725 +0,0 @@ -use crate::prelude::*; -use lazy_static::lazy_static; -use nu_engine::{evaluate_baseline_expr, BufCodecReader}; -use nu_engine::{MaybeTextCodec, StringOrBinary}; -use nu_test_support::NATIVE_PATH_ENV_VAR; -use parking_lot::Mutex; -use regex::Regex; - -#[allow(unused)] -use std::env; -use std::io::Write; -use std::path::PathBuf; -use std::process::{Command, Stdio}; -use std::sync::mpsc; -use std::{borrow::Cow, io::BufReader}; - -use log::trace; - -use nu_errors::ShellError; -use nu_protocol::hir::Expression; -use nu_protocol::hir::{ExternalCommand, ExternalRedirection}; -use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value}; -use nu_source::Tag; - -#[cfg(feature = "which")] -use which::which_in; - -pub(crate) fn run_external_command( - command: ExternalCommand, - context: &mut EvaluationContext, - input: InputStream, - external_redirection: ExternalRedirection, -) -> Result { - trace!(target: "nu::run::external", "-> {}", command.name); - - context.sync_path_to_env(); - if !context.host().lock().is_external_cmd(&command.name) { - return Err(ShellError::labeled_error( - "Command not found", - format!("command {} not found", &command.name), - &command.name_tag, - )); - } - - run_with_stdin(command, context, input, external_redirection) -} - -#[allow(unused)] -fn trim_enclosing_quotes(input: &str) -> String { - let mut chars = input.chars(); - - match (chars.next(), chars.next_back()) { - (Some('"'), Some('"')) => chars.collect(), - (Some('\''), Some('\'')) => chars.collect(), - _ => input.to_string(), - } -} - -fn run_with_stdin( - command: ExternalCommand, - context: &mut EvaluationContext, - input: InputStream, - external_redirection: ExternalRedirection, -) -> Result { - let path = context.shell_manager().path(); - - let mut command_args = vec![]; - for arg in command.args.iter() { - let is_literal = matches!(arg.expr, Expression::Literal(_)); - let value = evaluate_baseline_expr(arg, context)?; - - // Skip any arguments that don't really exist, treating them as optional - // FIXME: we may want to preserve the gap in the future, though it's hard to say - // what value we would put in its place. - if value.value.is_none() { - continue; - } - - // Do the cleanup that we need to do on any argument going out: - match &value.value { - UntaggedValue::Table(table) => { - for t in table { - match &t.value { - UntaggedValue::Primitive(_) => { - command_args.push(( - t.convert_to_string().trim_end_matches('\n').to_string(), - is_literal, - )); - } - _ => { - return Err(ShellError::labeled_error( - "Could not convert to positional arguments", - "could not convert to positional arguments", - value.tag(), - )); - } - } - } - } - _ => { - let trimmed_value_string = value.as_string()?.trim_end_matches('\n').to_string(); - //let trimmed_value_string = trim_quotes(&trimmed_value_string); - command_args.push((trimmed_value_string, is_literal)); - } - } - } - - let process_args = command_args - .iter() - .map(|(arg, _is_literal)| { - let arg = nu_path::expand_tilde(arg).to_string_lossy().to_string(); - - #[cfg(not(windows))] - { - if !_is_literal { - arg - } else { - trim_enclosing_quotes(&arg) - } - } - #[cfg(windows)] - { - if let Some(unquoted) = remove_quotes(&arg) { - unquoted.to_string() - } else { - arg - } - } - }) - .collect::>(); - - spawn( - &command, - &path, - &process_args[..], - input, - external_redirection, - &context.scope, - ) -} - -/// Spawn a direct exe -#[allow(unused)] -fn spawn_exe(full_path: PathBuf, args: &[String]) -> Command { - let mut process = Command::new(full_path); - for arg in args { - process.arg(&arg); - } - process -} - -/// Spawn a cmd command with `cmd /c args...` -fn spawn_cmd_command(command: &ExternalCommand, args: &[String]) -> Command { - let mut process = Command::new("cmd"); - process.arg("/c"); - process.arg(&command.name); - for arg in args { - // Clean the args before we use them: - // https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe - // cmd.exe needs to have a caret to escape a pipe - let arg = arg.replace("|", "^|"); - process.arg(&arg); - } - process -} - -fn has_unsafe_shell_characters(arg: &str) -> bool { - lazy_static! { - static ref RE: Regex = Regex::new(r"[^\w@%+=:,./-]").expect("regex to be valid"); - } - - RE.is_match(arg) -} - -fn shell_arg_escape(arg: &str) -> String { - match arg { - "" => String::from("''"), - s if !has_unsafe_shell_characters(s) => String::from(s), - _ => { - let single_quotes_escaped = arg.split('\'').join("'\"'\"'"); - format!("'{}'", single_quotes_escaped) - } - } -} - -/// Spawn a sh command with `sh -c args...` -fn spawn_sh_command(command: &ExternalCommand, args: &[String]) -> Command { - let joined_and_escaped_arguments = args.iter().map(|arg| shell_arg_escape(arg)).join(" "); - let cmd_with_args = vec![command.name.clone(), joined_and_escaped_arguments].join(" "); - let mut process = Command::new("sh"); - process.arg("-c").arg(cmd_with_args); - process -} - -/// a function to spawn any external command -#[allow(unused)] // for minimal builds cwd is unused -fn spawn_any(command: &ExternalCommand, args: &[String], cwd: &str) -> Command { - // resolve the executable name if it is spawnable directly - #[cfg(feature = "which")] - // TODO add more available paths to `env::var_os("PATH")`? - if let Result::Ok(full_path) = which_in(&command.name, env::var_os("PATH"), cwd) { - if let Some(extension) = full_path.extension() { - #[cfg(windows)] - if extension.eq_ignore_ascii_case("exe") { - // if exe spawn it directly - return spawn_exe(full_path, args); - } else { - // TODO implement special care for various executable types such as .bat, .ps1, .cmd, etc - // https://github.com/mklement0/Native/blob/e0e0b8785cad39a73053e35084d1f60d87fbac58/Native.psm1#L749 - // otherwise shell out to cmd - return spawn_cmd_command(command, args); - } - #[cfg(not(windows))] - if !["sh", "bash"] - .iter() - .any(|ext| extension.eq_ignore_ascii_case(ext)) - { - // if exe spawn it directly - return spawn_exe(full_path, args); - } else { - // otherwise shell out to sh - return spawn_sh_command(command, args); - } - } - } - // in all the other cases shell out - if cfg!(windows) { - spawn_cmd_command(command, args) - } else { - // TODO what happens if that os doesn't support spawning sh? - spawn_sh_command(command, args) - } -} - -fn spawn( - command: &ExternalCommand, - path: &str, - args: &[String], - input: InputStream, - external_redirection: ExternalRedirection, - scope: &Scope, -) -> Result { - let command = command.clone(); - - let mut process = spawn_any(&command, args, path); - process.current_dir(path); - trace!(target: "nu::run::external", "cwd = {:?}", &path); - - process.env_clear(); - process.envs(scope.get_env_vars()); - - // We want stdout regardless of what - // we are doing ($it case or pipe stdin) - match external_redirection { - ExternalRedirection::Stdout => { - process.stdout(Stdio::piped()); - trace!(target: "nu::run::external", "set up stdout pipe"); - } - ExternalRedirection::Stderr => { - process.stderr(Stdio::piped()); - trace!(target: "nu::run::external", "set up stderr pipe"); - } - ExternalRedirection::StdoutAndStderr => { - process.stdout(Stdio::piped()); - trace!(target: "nu::run::external", "set up stdout pipe"); - process.stderr(Stdio::piped()); - trace!(target: "nu::run::external", "set up stderr pipe"); - } - _ => {} - } - - // open since we have some contents for stdin - if !input.is_empty() { - process.stdin(Stdio::piped()); - trace!(target: "nu::run::external", "set up stdin pipe"); - } - - trace!(target: "nu::run::external", "built command {:?}", process); - - // TODO Switch to async_std::process once it's stabilized - match process.spawn() { - Ok(mut child) => { - let (tx, rx) = mpsc::sync_channel(0); - - let mut stdin = child.stdin.take(); - - let stdin_write_tx = tx.clone(); - let stdout_read_tx = tx; - let stdin_name_tag = command.name_tag.clone(); - let stdout_name_tag = command.name_tag; - - std::thread::spawn(move || { - if !input.is_empty() { - let mut stdin_write = stdin - .take() - .expect("Internal error: could not get stdin pipe for external command"); - - for value in input { - match &value.value { - UntaggedValue::Primitive(Primitive::Nothing) => continue, - UntaggedValue::Primitive(Primitive::String(s)) => { - if stdin_write.write(s.as_bytes()).is_err() { - // Other side has closed, so exit - return Ok(()); - } - } - UntaggedValue::Primitive(Primitive::Binary(b)) => { - if stdin_write.write(b).is_err() { - // Other side has closed, so exit - return Ok(()); - } - } - unsupported => { - println!("Unsupported: {:?}", unsupported); - let _ = stdin_write_tx.send(Ok(Value { - value: UntaggedValue::Error(ShellError::labeled_error( - format!( - "Received unexpected type from pipeline ({})", - unsupported.type_name() - ), - format!( - "expected a string, got {} as input", - unsupported.type_name() - ), - stdin_name_tag.clone(), - )), - tag: stdin_name_tag, - })); - return Err(()); - } - }; - } - } - - Ok(()) - }); - - std::thread::spawn(move || { - if external_redirection == ExternalRedirection::Stdout - || external_redirection == ExternalRedirection::StdoutAndStderr - { - let stdout = if let Some(stdout) = child.stdout.take() { - stdout - } else { - let _ = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Error(ShellError::labeled_error( - "Can't redirect the stdout for external command", - "can't redirect stdout", - &stdout_name_tag, - )), - tag: stdout_name_tag, - })); - return Err(()); - }; - - // let file = futures::io::AllowStdIo::new(stdout); - // let stream = FramedRead::new(file, MaybeTextCodec::default()); - let buf_read = BufReader::new(stdout); - let buf_codec = BufCodecReader::new(buf_read, MaybeTextCodec::default()); - - for line in buf_codec { - match line { - Ok(line) => match line { - StringOrBinary::String(s) => { - let result = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Primitive(Primitive::String( - s.clone(), - )), - tag: stdout_name_tag.clone(), - })); - - if result.is_err() { - break; - } - } - StringOrBinary::Binary(b) => { - let result = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Primitive(Primitive::Binary( - b.into_iter().collect(), - )), - tag: stdout_name_tag.clone(), - })); - - if result.is_err() { - break; - } - } - }, - Err(e) => { - // If there's an exit status, it makes sense that we may error when - // trying to read from its stdout pipe (likely been closed). In that - // case, don't emit an error. - let should_error = match child.wait() { - Ok(exit_status) => !exit_status.success(), - Err(_) => true, - }; - - if should_error { - let _ = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Error(ShellError::labeled_error( - format!("Unable to read from stdout ({})", e), - "unable to read from stdout", - &stdout_name_tag, - )), - tag: stdout_name_tag.clone(), - })); - } - - return Ok(()); - } - } - } - } - if external_redirection == ExternalRedirection::Stderr - || external_redirection == ExternalRedirection::StdoutAndStderr - { - let stderr = if let Some(stderr) = child.stderr.take() { - stderr - } else { - let _ = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Error(ShellError::labeled_error( - "Can't redirect the stderr for external command", - "can't redirect stderr", - &stdout_name_tag, - )), - tag: stdout_name_tag, - })); - return Err(()); - }; - - // let file = futures::io::AllowStdIo::new(stderr); - // let stream = FramedRead::new(file, MaybeTextCodec::default()); - let buf_reader = BufReader::new(stderr); - let buf_codec = BufCodecReader::new(buf_reader, MaybeTextCodec::default()); - - for line in buf_codec { - match line { - Ok(line) => match line { - StringOrBinary::String(s) => { - let result = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Error( - ShellError::untagged_runtime_error(s), - ), - tag: stdout_name_tag.clone(), - })); - - if result.is_err() { - break; - } - } - StringOrBinary::Binary(_) => { - let result = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Error( - ShellError::untagged_runtime_error(""), - ), - tag: stdout_name_tag.clone(), - })); - - if result.is_err() { - break; - } - } - }, - Err(e) => { - // If there's an exit status, it makes sense that we may error when - // trying to read from its stdout pipe (likely been closed). In that - // case, don't emit an error. - let should_error = match child.wait() { - Ok(exit_status) => !exit_status.success(), - Err(_) => true, - }; - - if should_error { - let _ = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Error(ShellError::labeled_error( - format!("Unable to read from stdout ({})", e), - "unable to read from stdout", - &stdout_name_tag, - )), - tag: stdout_name_tag.clone(), - })); - } - - return Ok(()); - } - } - } - } - - // We can give an error when we see a non-zero exit code, but this is different - // than what other shells will do. - let external_failed = match child.wait() { - Err(_) => true, - Ok(exit_status) => !exit_status.success(), - }; - - if external_failed { - let cfg = nu_data::config::config(Tag::unknown()); - if let Ok(cfg) = cfg { - if cfg.contains_key("nonzero_exit_errors") { - let _ = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::Error(ShellError::labeled_error( - "External command failed", - "command failed", - &stdout_name_tag, - )), - tag: stdout_name_tag.clone(), - })); - } - } - let _ = stdout_read_tx.send(Ok(Value { - value: UntaggedValue::nothing(), - tag: stdout_name_tag, - })); - } - - Ok(()) - }); - - let stream = ChannelReceiver::new(rx); - Ok(stream.into_input_stream()) - } - Err(e) => Err(ShellError::labeled_error( - e.to_string(), - "failed to spawn", - &command.name_tag, - )), - } -} - -struct ChannelReceiver { - rx: Arc>>>, -} - -impl ChannelReceiver { - pub fn new(rx: mpsc::Receiver>) -> Self { - Self { - rx: Arc::new(Mutex::new(rx)), - } - } -} - -impl Iterator for ChannelReceiver { - type Item = Result; - - fn next(&mut self) -> Option { - let rx = self.rx.lock(); - match rx.recv() { - Ok(v) => Some(v), - Err(_) => None, - } - } -} - -fn argument_is_quoted(argument: &str) -> bool { - if argument.len() < 2 { - return false; - } - - (argument.starts_with('"') && argument.ends_with('"')) - || (argument.starts_with('\'') && argument.ends_with('\'')) -} - -#[allow(unused)] -fn add_double_quotes(argument: &str) -> String { - format!("\"{}\"", argument) -} - -#[allow(unused)] -fn escape_double_quotes(argument: &str) -> Cow<'_, str> { - // allocate new string only if required - if argument.contains('"') { - Cow::Owned(argument.replace('"', r#"\""#)) - } else { - Cow::Borrowed(argument) - } -} - -#[allow(unused)] -fn remove_quotes(argument: &str) -> Option<&str> { - if !argument_is_quoted(argument) { - return None; - } - - let size = argument.len(); - - Some(&argument[1..size - 1]) -} - -#[allow(unused)] -fn shell_os_paths() -> Vec { - let mut original_paths = vec![]; - - if let Some(paths) = std::env::var_os(NATIVE_PATH_ENV_VAR) { - original_paths = std::env::split_paths(&paths).collect::>(); - } - - original_paths -} - -#[cfg(test)] -mod tests { - use super::{add_double_quotes, argument_is_quoted, escape_double_quotes, remove_quotes}; - #[cfg(feature = "which")] - use super::{run_external_command, InputStream}; - - #[cfg(feature = "which")] - use nu_engine::EvaluationContext; - - #[cfg(feature = "which")] - use nu_test_support::commands::ExternalBuilder; - // fn read(mut stream: OutputStream) -> Option { - // match stream.try_next() { - // Ok(val) => { - // if let Some(val) = val { - // val.raw_value() - // } else { - // None - // } - // } - // Err(_) => None, - // } - // } - - #[cfg(feature = "which")] - fn non_existent_run() { - use nu_protocol::hir::ExternalRedirection; - let cmd = ExternalBuilder::for_name("i_dont_exist.exe").build(); - - let input = InputStream::empty(); - let mut ctx = EvaluationContext::basic(); - - assert!(run_external_command(cmd, &mut ctx, input, ExternalRedirection::Stdout).is_err()); - } - - // fn failure_run() -> Result<(), ShellError> { - // let cmd = ExternalBuilder::for_name("fail").build(); - - // let mut ctx = crate::cli::EvaluationContext::basic().expect("There was a problem creating a basic context."); - // let stream = run_external_command(cmd, &mut ctx, None, false) - // ? - // .expect("There was a problem running the external command."); - - // match read(stream.into()) { - // Some(Value { - // value: UntaggedValue::Error(_), - // .. - // }) => {} - // None | _ => panic!("Command didn't fail."), - // } - - // Ok(()) - // } - - // #[test] - // fn identifies_command_failed() -> Result<(), ShellError> { - // block_on(failure_run()) - // } - - #[cfg(feature = "which")] - #[test] - fn identifies_command_not_found() { - non_existent_run() - } - - #[test] - fn checks_escape_double_quotes() { - assert_eq!(escape_double_quotes("andrés"), "andrés"); - assert_eq!(escape_double_quotes(r#"an"drés"#), r#"an\"drés"#); - assert_eq!(escape_double_quotes(r#""an"drés""#), r#"\"an\"drés\""#); - } - - #[test] - fn checks_quotes_from_argument_to_be_passed_in() { - assert!(!argument_is_quoted("")); - - assert!(!argument_is_quoted("'")); - assert!(!argument_is_quoted("'a")); - assert!(!argument_is_quoted("a")); - assert!(!argument_is_quoted("a'")); - assert!(argument_is_quoted("''")); - - assert!(!argument_is_quoted(r#"""#)); - assert!(!argument_is_quoted(r#""a"#)); - assert!(!argument_is_quoted(r#"a"#)); - assert!(!argument_is_quoted(r#"a""#)); - assert!(argument_is_quoted(r#""""#)); - - assert!(!argument_is_quoted("'andrés")); - assert!(!argument_is_quoted("andrés'")); - assert!(!argument_is_quoted(r#""andrés"#)); - assert!(!argument_is_quoted(r#"andrés""#)); - assert!(argument_is_quoted("'andrés'")); - assert!(argument_is_quoted(r#""andrés""#)); - } - - #[test] - fn adds_double_quotes_to_argument_to_be_passed_in() { - assert_eq!(add_double_quotes("andrés"), "\"andrés\""); - } - - #[test] - fn strips_quotes_from_argument_to_be_passed_in() { - assert_eq!(remove_quotes(""), None); - - assert_eq!(remove_quotes("'"), None); - assert_eq!(remove_quotes("'a"), None); - assert_eq!(remove_quotes("a"), None); - assert_eq!(remove_quotes("a'"), None); - assert_eq!(remove_quotes("''"), Some("")); - - assert_eq!(remove_quotes(r#"""#), None); - assert_eq!(remove_quotes(r#""a"#), None); - assert_eq!(remove_quotes(r#"a"#), None); - assert_eq!(remove_quotes(r#"a""#), None); - assert_eq!(remove_quotes(r#""""#), Some("")); - - assert_eq!(remove_quotes("'andrés"), None); - assert_eq!(remove_quotes("andrés'"), None); - assert_eq!(remove_quotes(r#""andrés"#), None); - assert_eq!(remove_quotes(r#"andrés""#), None); - assert_eq!(remove_quotes("'andrés'"), Some("andrés")); - assert_eq!(remove_quotes(r#""andrés""#), Some("andrés")); - } -} diff --git a/old_nushell/crates/nu-command/src/classified/mod.rs b/old_nushell/crates/nu-command/src/classified/mod.rs deleted file mode 100644 index 04016e9e7..000000000 --- a/old_nushell/crates/nu-command/src/classified/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod external; diff --git a/old_nushell/crates/nu-command/src/commands/charting/chart.rs b/old_nushell/crates/nu-command/src/commands/charting/chart.rs deleted file mode 100644 index edc6f59f5..000000000 --- a/old_nushell/crates/nu-command/src/commands/charting/chart.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; - -#[derive(Clone)] -pub struct Chart; - -impl WholeStreamCommand for Chart { - fn name(&self) -> &str { - "chart" - } - - fn signature(&self) -> Signature { - Signature::build("chart") - } - - fn usage(&self) -> &str { - "Displays charts." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - if args.scope().get_command("chart bar").is_none() { - return Err(ShellError::untagged_runtime_error( - "nu_plugin_chart not installed.", - )); - } - - Ok(ActionStream::one(Ok(ReturnSuccess::Value( - UntaggedValue::string(get_full_help(&Chart, args.scope())).into_value(Tag::unknown()), - )))) - } -} - -#[cfg(test)] -mod tests { - use super::Chart; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Chart {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/charting/histogram.rs b/old_nushell/crates/nu-command/src/commands/charting/histogram.rs deleted file mode 100644 index 4fcf6aa57..000000000 --- a/old_nushell/crates/nu-command/src/commands/charting/histogram.rs +++ /dev/null @@ -1,220 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - ColumnPath, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, -}; -use nu_source::Tagged; - -pub struct Histogram; - -impl WholeStreamCommand for Histogram { - fn name(&self) -> &str { - "histogram" - } - - fn signature(&self) -> Signature { - Signature::build("histogram") - .named( - "use", - SyntaxShape::ColumnPath, - "Use data at the column path given as valuator", - None, - ) - .rest( - "rest", - SyntaxShape::ColumnPath, - "column name to give the histogram's frequency column", - ) - } - - fn usage(&self) -> &str { - "Creates a new table with a histogram based on the column name passed in." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - histogram(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get a histogram for the types of files", - example: "ls | histogram type", - result: None, - }, - Example { - description: - "Get a histogram for the types of files, with frequency column named percentage", - example: "ls | histogram type percentage", - result: None, - }, - Example { - description: "Get a histogram for a list of numbers", - example: "echo [1 2 3 1 1 1 2 2 1 1] | histogram", - result: None, - }, - ] - } -} - -pub fn histogram(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let mut columns = args.rest::(0)?; - let evaluate_with = args.get_flag::("use")?.map(evaluator); - let values: Vec = args.input.collect(); - - let column_grouper = if !columns.is_empty() { - columns - .remove(0) - .split_last() - .map(|(key, _)| key.as_string().tagged(&name)) - } else { - None - }; - - let frequency_column_name = if columns.is_empty() { - "frequency".to_string() - } else if let Some((key, _)) = columns[0].split_last() { - key.as_string() - } else { - "frequency".to_string() - }; - - let column = if let Some(ref column) = column_grouper { - column.clone() - } else { - "value".to_string().tagged(&name) - }; - - let results = nu_data::utils::report( - &UntaggedValue::table(&values).into_value(&name), - nu_data::utils::Operation { - grouper: Some(Box::new(move |_, _| Ok(String::from("frequencies")))), - splitter: Some(splitter(column_grouper)), - format: &None, - eval: &evaluate_with, - reduction: &nu_data::utils::Reduction::Count, - }, - &name, - )?; - - let labels = results.labels.y.clone(); - let mut idx = 0; - - Ok(results - .data - .table_entries() - .cloned() - .collect::>() - .into_iter() - .zip( - results - .percentages - .table_entries() - .cloned() - .collect::>() - .into_iter(), - ) - .map(move |(counts, percentages)| { - let percentage = percentages - .table_entries() - .cloned() - .last() - .unwrap_or_else(|| { - UntaggedValue::decimal_from_float(0.0, name.span).into_value(&name) - }); - let value = counts - .table_entries() - .cloned() - .last() - .unwrap_or_else(|| UntaggedValue::int(0).into_value(&name)); - - let mut fact = TaggedDictBuilder::new(&name); - let column_value = labels - .get(idx) - .ok_or_else(|| { - ShellError::labeled_error( - "Unable to load group labels", - "unable to load group labels", - &name, - ) - })? - .clone(); - - fact.insert_value(&column.item, column_value); - fact.insert_untagged("count", value); - - let fmt_percentage = format!( - "{}%", - // Some(2) < the number of digits - // true < group the digits - crate::commands::conversions::into::string::action( - &percentage, - &name, - Some(2), - true - )? - .as_string()? - ); - fact.insert_untagged("percentage", UntaggedValue::string(fmt_percentage)); - - let string = "*".repeat(percentage.as_u64().map_err(|_| { - ShellError::labeled_error("expected a number", "expected a number", &name) - })? as usize); - - fact.insert_untagged(&frequency_column_name, UntaggedValue::string(string)); - - idx += 1; - - ReturnSuccess::value(fact.into_value()) - }) - .into_action_stream()) -} - -fn evaluator(by: ColumnPath) -> Box Result + Send> { - Box::new(move |_: usize, value: &Value| { - let path = by.clone(); - - let eval = nu_value_ext::get_data_by_column_path(value, &path, move |_, _, error| error); - - match eval { - Ok(with_value) => Ok(with_value), - Err(reason) => Err(reason), - } - }) -} - -fn splitter( - by: Option>, -) -> Box Result + Send> { - match by { - Some(column) => Box::new(move |_, row: &Value| { - let key = &column; - - match row.get_data_by_key(key.borrow_spanned()) { - Some(key) => nu_value_ext::as_string(&key), - None => Err(ShellError::labeled_error( - "unknown column", - "unknown column", - key.tag(), - )), - } - }), - None => Box::new(move |_, row: &Value| nu_value_ext::as_string(row)), - } -} - -#[cfg(test)] -mod tests { - use super::Histogram; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Histogram {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/charting/mod.rs b/old_nushell/crates/nu-command/src/commands/charting/mod.rs deleted file mode 100644 index a69047517..000000000 --- a/old_nushell/crates/nu-command/src/commands/charting/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod chart; -mod histogram; - -pub use chart::Chart; -pub use histogram::Histogram; diff --git a/old_nushell/crates/nu-command/src/commands/config/clear.rs b/old_nushell/crates/nu-command/src/commands/config/clear.rs deleted file mode 100644 index 0aa8593df..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/clear.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "config clear" - } - - fn signature(&self) -> Signature { - Signature::build("config clear") - } - - fn usage(&self) -> &str { - "clear the config" - } - - fn run(&self, args: CommandArgs) -> Result { - clear(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Clear the config (be careful!)", - example: "config clear", - result: None, - }] - } -} - -pub fn clear(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let result = if let Some(global_cfg) = &mut args.configs().lock().global_config { - global_cfg.vars.clear(); - global_cfg.write()?; - ctx.reload_config(global_cfg)?; - - let value = UntaggedValue::Row(global_cfg.vars.clone().into()).into_value(name); - Ok(OutputStream::one(value)) - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - }; - - result -} diff --git a/old_nushell/crates/nu-command/src/commands/config/command.rs b/old_nushell/crates/nu-command/src/commands/config/command.rs deleted file mode 100644 index f0faea14b..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/command.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::prelude::*; -use nu_engine::CommandArgs; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "config" - } - - fn signature(&self) -> Signature { - Signature::build("config") - } - - fn usage(&self) -> &str { - "Configuration management." - } - - fn run(&self, args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - if let Some(global_cfg) = &args.configs().lock().global_config { - let result = global_cfg.vars.clone(); - let value = UntaggedValue::Row(result.into()).into_value(name); - - Ok(OutputStream::one(value)) - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/config/get.rs b/old_nushell/crates/nu-command/src/commands/config/get.rs deleted file mode 100644 index fac8e110e..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/get.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "config get" - } - - fn signature(&self) -> Signature { - Signature::build("config get").required( - "get", - SyntaxShape::ColumnPath, - "value to get from the config", - ) - } - - fn usage(&self) -> &str { - "Gets a value from the config" - } - - fn run(&self, args: CommandArgs) -> Result { - get(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get the current startup commands", - example: "config get startup", - result: None, - }] - } -} - -pub fn get(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let column_path = args.req(0)?; - - let result = if let Some(global_cfg) = &ctx.configs().lock().global_config { - let result = UntaggedValue::row(global_cfg.vars.clone()).into_value(&name); - let value = crate::commands::filters::get::get_column_path(&column_path, &result)?; - Ok(match value { - Value { - value: UntaggedValue::Table(list), - .. - } => OutputStream::from_stream(list.into_iter()), - x => OutputStream::one(x), - }) - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - }; - - result -} diff --git a/old_nushell/crates/nu-command/src/commands/config/mod.rs b/old_nushell/crates/nu-command/src/commands/config/mod.rs deleted file mode 100644 index 62f626cf8..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -pub mod clear; -pub mod command; -pub mod get; -pub mod path; -pub mod remove; -pub mod set; -pub mod set_into; - -pub use clear::SubCommand as ConfigClear; -pub use command::Command as Config; -pub use get::SubCommand as ConfigGet; -pub use path::SubCommand as ConfigPath; -pub use remove::SubCommand as ConfigRemove; -pub use set::SubCommand as ConfigSet; -pub use set_into::SubCommand as ConfigSetInto; - -use nu_errors::ShellError; - -pub fn err_no_global_cfg_present() -> ShellError { - ShellError::untagged_runtime_error("No global config found!") -} diff --git a/old_nushell/crates/nu-command/src/commands/config/path.rs b/old_nushell/crates/nu-command/src/commands/config/path.rs deleted file mode 100644 index 4e32596cc..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/path.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, UntaggedValue}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "config path" - } - - fn signature(&self) -> Signature { - Signature::build("config path") - } - - fn usage(&self) -> &str { - "return the path to the config file" - } - - fn run(&self, args: CommandArgs) -> Result { - path(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get the path to the current config file", - example: "config path", - result: None, - }] - } -} - -pub fn path(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - if let Some(global_cfg) = &mut args.configs().lock().global_config { - let value = UntaggedValue::Primitive(Primitive::FilePath(global_cfg.file_path.clone())) - .into_value(name); - - Ok(OutputStream::one(value)) - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/config/remove.rs b/old_nushell/crates/nu-command/src/commands/config/remove.rs deleted file mode 100644 index d71ecc5c1..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/remove.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "config remove" - } - - fn signature(&self) -> Signature { - Signature::build("config remove").required( - "remove", - SyntaxShape::Any, - "remove a value from the config", - ) - } - - fn usage(&self) -> &str { - "Removes a value from the config" - } - - fn run(&self, args: CommandArgs) -> Result { - remove(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Remove the startup commands", - example: "config remove startup", - result: None, - }] - } -} - -pub fn remove(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctx = &args.context; - let remove: Tagged = args.req(0)?; - - let key = remove.to_string(); - - let result = if let Some(global_cfg) = &mut ctx.configs().lock().global_config { - if global_cfg.vars.contains_key(&key) { - global_cfg.vars.swap_remove(&key); - global_cfg.write()?; - ctx.reload_config(global_cfg)?; - - let value: Value = UntaggedValue::row(global_cfg.vars.clone()).into_value(remove.tag); - - Ok(OutputStream::one(value)) - } else { - Err(ShellError::labeled_error( - "Key does not exist in config", - "key", - remove.tag(), - )) - } - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - }; - - result -} diff --git a/old_nushell/crates/nu-command/src/commands/config/set.rs b/old_nushell/crates/nu-command/src/commands/config/set.rs deleted file mode 100644 index b6bd986e4..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/set.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "config set" - } - - fn signature(&self) -> Signature { - Signature::build("config set") - .required("key", SyntaxShape::ColumnPath, "variable name to set") - .required("value", SyntaxShape::Any, "value to use") - } - - fn usage(&self) -> &str { - "Sets a value in the config" - } - - fn run(&self, args: CommandArgs) -> Result { - set(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Set auto pivoting", - example: "config set pivot_mode always", - result: None, - }, - Example { - description: "Set line editor options", - example: "config set line_editor [[edit_mode, completion_type]; [emacs circular]]", - result: None, - }, - Example { - description: "Set coloring options", - example: "config set color_config [[header_align header_color]; [left white_bold]]", - result: None, - }, - Example { - description: "Set nested options", - example: "config set color_config.header_color white", - result: None, - }, - ] - } -} - -pub fn set(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let column_path = args.req(0)?; - let mut value: Value = args.req(1)?; - - let result = if let Some(global_cfg) = &mut ctx.configs().lock().global_config { - let configuration = UntaggedValue::row(global_cfg.vars.clone()).into_value(&name); - - if let UntaggedValue::Table(rows) = &value.value { - if rows.len() == 1 && rows[0].is_row() { - value = rows[0].clone(); - } - } - - match configuration.forgiving_insert_data_at_column_path(&column_path, value) { - Ok(Value { - value: UntaggedValue::Row(changes), - .. - }) => { - global_cfg.vars = changes.entries; - global_cfg.write()?; - ctx.reload_config(global_cfg)?; - - let value = UntaggedValue::row(global_cfg.vars.clone()).into_value(name); - Ok(OutputStream::one(value)) - } - Ok(_) => Ok(OutputStream::empty()), - Err(reason) => Err(reason), - } - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - }; - - result -} diff --git a/old_nushell/crates/nu-command/src/commands/config/set_into.rs b/old_nushell/crates/nu-command/src/commands/config/set_into.rs deleted file mode 100644 index f49ae71ab..000000000 --- a/old_nushell/crates/nu-command/src/commands/config/set_into.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "config set_into" - } - - fn signature(&self) -> Signature { - Signature::build("config set_into").required( - "set_into", - SyntaxShape::String, - "sets a variable from values in the pipeline", - ) - } - - fn usage(&self) -> &str { - "Sets a value in the config" - } - - fn run(&self, args: CommandArgs) -> Result { - set_into(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Store the contents of the pipeline as a path", - example: "echo ['/usr/bin' '/bin'] | config set_into path", - result: None, - }] - } -} - -pub fn set_into(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let set_into: Tagged = args.req(0)?; - - let rows: Vec = args.input.collect(); - let key = set_into.to_string(); - - let result = if let Some(global_cfg) = &mut ctx.configs().lock().global_config { - if rows.is_empty() { - return Err(ShellError::labeled_error( - "No values given for set_into", - "needs value(s) from pipeline", - set_into.tag(), - )); - } else if rows.len() == 1 { - // A single value - let value = &rows[0]; - - global_cfg.vars.insert(key, value.clone()); - } else { - // Take in the pipeline as a table - let value = UntaggedValue::Table(rows).into_value(name.clone()); - - global_cfg.vars.insert(key, value); - } - - global_cfg.write()?; - ctx.reload_config(global_cfg)?; - - let value = UntaggedValue::row(global_cfg.vars.clone()).into_value(name); - - Ok(OutputStream::one(value)) - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - }; - - result -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/binary.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/binary.rs deleted file mode 100644 index 59aa35bbd..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/binary.rs +++ /dev/null @@ -1,185 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use num_bigint::{BigInt, ToBigInt}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "into binary" - } - - fn signature(&self) -> Signature { - Signature::build("into binary").rest( - "rest", - SyntaxShape::ColumnPath, - "column paths to convert to binary (for table input)", - ) - } - - fn usage(&self) -> &str { - "Convert value to a binary primitive" - } - - fn run(&self, args: CommandArgs) -> Result { - into_binary(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "convert string to a nushell binary primitive", - example: - "echo 'This is a string that is exactly 52 characters long.' | into binary", - result: Some(vec![UntaggedValue::binary( - "This is a string that is exactly 52 characters long." - .to_string() - .as_bytes() - .to_vec(), - ) - .into()]), - }, - Example { - description: "convert a number to a nushell binary primitive", - example: "echo 1 | into binary", - result: Some(vec![UntaggedValue::binary( - i64::from(1).to_le_bytes().to_vec(), - ) - .into()]), - }, - Example { - description: "convert a boolean to a nushell binary primitive", - example: "echo $true | into binary", - result: Some(vec![UntaggedValue::binary( - i64::from(1).to_le_bytes().to_vec(), - ) - .into()]), - }, - Example { - description: "convert a filesize to a nushell binary primitive", - example: "ls | where name == LICENSE | get size | into binary", - result: None, - }, - Example { - description: "convert a filepath to a nushell binary primitive", - example: "ls | where name == LICENSE | get name | path expand | into binary", - result: None, - }, - Example { - description: "convert a decimal to a nushell binary primitive", - example: "echo 1.234 | into binary", - result: Some(vec![ - UntaggedValue::binary(BigInt::from(1).to_bytes_le().1).into() - ]), - }, - ] - } -} - -fn into_binary(args: CommandArgs) -> Result { - let column_paths: Vec = args.rest(0)?; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag()) - } else { - let mut ret = v; - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -fn int_to_endian(n: i64) -> Vec { - if cfg!(target_endian = "little") { - n.to_le_bytes().to_vec() - } else { - n.to_be_bytes().to_vec() - } -} - -fn bigint_to_endian(n: &BigInt) -> Vec { - if cfg!(target_endian = "little") { - n.to_bytes_le().1 - } else { - n.to_bytes_be().1 - } -} - -pub fn action(input: &Value, tag: impl Into) -> Result { - let tag = tag.into(); - - match &input.value { - UntaggedValue::Primitive(prim) => Ok(UntaggedValue::binary(match prim { - Primitive::Binary(b) => b.to_vec(), - Primitive::Int(n_ref) => int_to_endian(*n_ref), - Primitive::BigInt(n_ref) => bigint_to_endian(n_ref), - Primitive::Decimal(dec) => match dec.to_bigint() { - Some(n) => bigint_to_endian(&n), - None => { - return Err(ShellError::unimplemented( - "failed to convert decimal to int", - )); - } - }, - Primitive::Filesize(a_filesize) => match a_filesize.to_bigint() { - Some(n) => bigint_to_endian(&n), - None => { - return Err(ShellError::unimplemented( - "failed to convert filesize to bigint", - )); - } - }, - Primitive::String(a_string) => a_string.as_bytes().to_vec(), - Primitive::Boolean(a_bool) => match a_bool { - false => int_to_endian(0), - true => int_to_endian(1), - }, - Primitive::Date(a_date) => a_date.format("%c").to_string().as_bytes().to_vec(), - Primitive::FilePath(a_filepath) => a_filepath - .as_path() - .display() - .to_string() - .as_bytes() - .to_vec(), - _ => { - return Err(ShellError::unimplemented( - "'into binary' for non-numeric primitives", - )) - } - }) - .into_value(&tag)), - UntaggedValue::Row(_) => Err(ShellError::labeled_error( - "specify column name to use, with 'into binary COLUMN'", - "found table", - tag, - )), - _ => Err(ShellError::unimplemented( - "'into binary' for unsupported type", - )), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/column_path.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/column_path.rs deleted file mode 100644 index 141bb68c4..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/column_path.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "into column-path" - } - - fn signature(&self) -> Signature { - Signature::build("into column-path").rest( - "rest", - SyntaxShape::ColumnPath, - "values to convert to column path", - ) - } - - fn usage(&self) -> &str { - "Convert value to column path" - } - - fn run(&self, args: CommandArgs) -> Result { - into_filepath(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert string to column path in table", - example: "echo [[name]; ['/dev/null'] ['C:\\Program Files'] ['../../Cargo.toml']] | into column-path name", - result: Some(vec![ - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::column_path("/dev/null", Span::unknown()).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::column_path("C:\\Program Files", Span::unknown()).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::column_path("../../Cargo.toml", Span::unknown()).into(), - }) - .into(), - ]), - }, - Example { - description: "Convert string to column path", - example: "echo 'Cargo.toml' | into column-path", - result: Some(vec![UntaggedValue::column_path("Cargo.toml", Span::unknown()).into()]), - }, - ] - } -} - -fn into_filepath(args: CommandArgs) -> Result { - let column_paths: Vec = args.rest(0)?; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag()) - } else { - let mut ret = v; - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -pub fn action(input: &Value, tag: impl Into) -> Result { - let tag = tag.into(); - match &input.value { - UntaggedValue::Primitive(prim) => Ok(UntaggedValue::column_path( - match prim { - Primitive::String(a_string) => a_string, - _ => { - return Err(ShellError::unimplemented( - "'into column-path' for non-string primitives", - )) - } - }, - Span::unknown(), - ) - .into_value(&tag)), - UntaggedValue::Row(_) => Err(ShellError::labeled_error( - "specify column name to use, with 'into column-path COLUMN'", - "found table", - tag, - )), - _ => Err(ShellError::unimplemented( - "'into column-path' for unsupported type", - )), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/command.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/command.rs deleted file mode 100644 index 3ae2ff897..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/command.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "into" - } - - fn signature(&self) -> Signature { - Signature::build("into") - } - - fn usage(&self) -> &str { - "Apply into function." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&Command, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/filepath.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/filepath.rs deleted file mode 100644 index 08e7fff1c..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/filepath.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::path::PathBuf; - -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "into path" - } - - fn signature(&self) -> Signature { - Signature::build("into path").rest( - "rest", - SyntaxShape::ColumnPath, - "column paths to convert to filepath (for table input)", - ) - } - - fn usage(&self) -> &str { - "Convert value to filepath" - } - - fn run(&self, args: CommandArgs) -> Result { - into_filepath(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert string to filepath in table", - example: "echo [[name]; ['/dev/null'] ['C:\\Program Files'] ['../../Cargo.toml']] | into path name", - result: Some(vec![ - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::filepath("/dev/null").into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::filepath("C:\\Program Files").into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::filepath("../../Cargo.toml").into(), - }) - .into(), - ]), - }, - Example { - description: "Convert string to filepath", - example: "echo 'Cargo.toml' | into path", - result: Some(vec![UntaggedValue::filepath("Cargo.toml").into()]), - }, - ] - } -} - -fn into_filepath(args: CommandArgs) -> Result { - let column_paths: Vec = args.rest(0)?; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag()) - } else { - let mut ret = v; - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -pub fn action(input: &Value, tag: impl Into) -> Result { - let tag = tag.into(); - match &input.value { - UntaggedValue::Primitive(prim) => Ok(UntaggedValue::filepath(match prim { - Primitive::String(a_string) => match filepath_from_string(a_string, &tag) { - Ok(n) => n, - Err(e) => { - return Err(e); - } - }, - Primitive::FilePath(a_filepath) => a_filepath.clone(), - _ => { - return Err(ShellError::unimplemented( - "'into path' for non-string primitives", - )) - } - }) - .into_value(&tag)), - UntaggedValue::Row(_) => Err(ShellError::labeled_error( - "specify column name to use, with 'into path COLUMN'", - "found table", - tag, - )), - _ => Err(ShellError::unimplemented( - "'into path' for unsupported type", - )), - } -} - -fn filepath_from_string(a_string: &str, _tag: &Tag) -> Result { - Ok(PathBuf::from(a_string)) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/filesize.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/filesize.rs deleted file mode 100644 index 7a3a64834..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/filesize.rs +++ /dev/null @@ -1,182 +0,0 @@ -use std::convert::TryInto; - -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use num_bigint::ToBigInt; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "into filesize" - } - - fn signature(&self) -> Signature { - Signature::build("into filesize").rest( - "rest", - SyntaxShape::ColumnPath, - "column paths to convert to filesize (for table input)", - ) - } - - fn usage(&self) -> &str { - "Convert value to filesize" - } - - fn run(&self, args: CommandArgs) -> Result { - into_filesize(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert string to filesize in table", - example: "echo [[bytes]; ['5'] [3.2] [4] [2kb]] | into filesize bytes", - result: Some(vec![ - UntaggedValue::row(indexmap! { - "bytes".to_string() => UntaggedValue::filesize(5).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "bytes".to_string() => UntaggedValue::filesize(3).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "bytes".to_string() => UntaggedValue::filesize(4).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "bytes".to_string() => UntaggedValue::filesize(2000).into(), - }) - .into(), - ]), - }, - Example { - description: "Convert string to filesize", - example: "echo '2' | into filesize", - result: Some(vec![UntaggedValue::filesize(2).into()]), - }, - Example { - description: "Convert decimal to filesize", - example: "echo 8.3 | into filesize", - result: Some(vec![UntaggedValue::filesize(8).into()]), - }, - Example { - description: "Convert int to filesize", - example: "echo 5 | into filesize", - result: Some(vec![UntaggedValue::filesize(5).into()]), - }, - Example { - description: "Convert file size to filesize", - example: "echo 4KB | into filesize", - result: Some(vec![UntaggedValue::filesize(4000).into()]), - }, - ] - } -} - -fn into_filesize(args: CommandArgs) -> Result { - let column_paths: Vec = args.rest(0)?; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag()) - } else { - let mut ret = v; - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -pub fn action(input: &Value, tag: impl Into) -> Result { - let tag = tag.into(); - match &input.value { - UntaggedValue::Primitive(prim) => Ok(UntaggedValue::filesize(match prim { - Primitive::String(a_string) => match int_from_string(a_string.trim(), &tag) { - Ok(n) => n, - Err(e) => { - return Err(e); - } - }, - Primitive::Decimal(dec) => match dec.to_bigint() { - Some(n) => match n.to_u64() { - Some(i) => i, - None => { - return Err(ShellError::unimplemented( - "failed to convert decimal to filesize", - )); - } - }, - None => { - return Err(ShellError::unimplemented( - "failed to convert decimal to filesize", - )); - } - }, - Primitive::Int(n_ref) => (*n_ref).try_into().map_err(|_| { - ShellError::unimplemented("cannot convert negative integer to filesize") - })?, - Primitive::Filesize(a_filesize) => *a_filesize, - _ => { - return Err(ShellError::unimplemented( - "'into filesize' for non-numeric primitives", - )) - } - }) - .into_value(&tag)), - UntaggedValue::Row(_) => Err(ShellError::labeled_error( - "specify column name to use, with 'into filesize COLUMN'", - "found table", - tag, - )), - _ => Err(ShellError::unimplemented( - "'into filesize' for unsupported type", - )), - } -} - -fn int_from_string(a_string: &str, tag: &Tag) -> Result { - match a_string.parse::() { - Ok(n) => Ok(n), - Err(_) => match a_string.parse::() { - Ok(f) => match f.to_u64() { - Some(i) => Ok(i), - None => Err(ShellError::labeled_error( - "Could not convert string value to filesize", - "original value", - tag.clone(), - )), - }, - Err(_) => Err(ShellError::labeled_error( - "Could not convert string value to filesize", - "original value", - tag.clone(), - )), - }, - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/int.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/int.rs deleted file mode 100644 index afa2a04fe..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/int.rs +++ /dev/null @@ -1,198 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use num_bigint::ToBigInt; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "into int" - } - - fn signature(&self) -> Signature { - Signature::build("into int").rest( - "rest", - SyntaxShape::ColumnPath, - "column paths to convert to int (for table input)", - ) - } - - fn usage(&self) -> &str { - "Convert value to integer" - } - - fn run(&self, args: CommandArgs) -> Result { - into_int(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert string to integer in table", - example: "echo [[num]; ['-5'] [4] [1.5]] | into int num", - result: Some(vec![ - UntaggedValue::row(indexmap! { - "num".to_string() => UntaggedValue::int(-5).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "num".to_string() => UntaggedValue::int(4).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "num".to_string() => UntaggedValue::int(1).into(), - }) - .into(), - ]), - }, - Example { - description: "Convert string to integer", - example: "echo '2' | into int", - result: Some(vec![UntaggedValue::int(2).into()]), - }, - Example { - description: "Convert decimal to integer", - example: "echo 5.9 | into int", - result: Some(vec![UntaggedValue::int(5).into()]), - }, - Example { - description: "Convert decimal string to integer", - example: "echo '5.9' | into int", - result: Some(vec![UntaggedValue::int(5).into()]), - }, - Example { - description: "Convert file size to integer", - example: "echo 4KB | into int", - result: Some(vec![UntaggedValue::int(4000).into()]), - }, - Example { - description: "Convert bool to integer", - example: "echo $false $true | into int", - result: Some(vec![ - UntaggedValue::int(0).into(), - UntaggedValue::int(1).into(), - ]), - }, - ] - } -} - -fn into_int(args: CommandArgs) -> Result { - let column_paths: Vec = args.rest(0)?; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag()) - } else { - let mut ret = v; - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -pub fn action(input: &Value, tag: impl Into) -> Result { - let tag = tag.into(); - match &input.value { - UntaggedValue::Primitive(prim) => Ok(UntaggedValue::int(match prim { - Primitive::String(a_string) => match int_from_string(a_string, &tag) { - Ok(n) => n, - Err(e) => { - return Err(e); - } - }, - Primitive::Decimal(dec) => match dec.to_bigint() { - Some(n) => match n.to_i64() { - Some(i) => i, - None => { - return Err(ShellError::unimplemented( - "failed to convert decimal to int", - )); - } - }, - None => { - return Err(ShellError::unimplemented( - "failed to convert decimal to int", - )); - } - }, - Primitive::Int(n_ref) => *n_ref, - Primitive::Boolean(a_bool) => match a_bool { - false => 0, - true => 1, - }, - Primitive::Filesize(a_filesize) => match a_filesize.to_bigint() { - Some(n) => match n.to_i64() { - Some(i) => i, - None => { - return Err(ShellError::unimplemented( - "failed to convert filesize to bigint", - )); - } - }, - None => { - return Err(ShellError::unimplemented( - "failed to convert filesize to bigint", - )); - } - }, - _ => { - return Err(ShellError::unimplemented( - "'into int' for non-numeric primitives", - )) - } - }) - .into_value(&tag)), - UntaggedValue::Row(_) => Err(ShellError::labeled_error( - "specify column name to use, with 'into int COLUMN'", - "found table", - tag, - )), - _ => Err(ShellError::unimplemented("'into int' for unsupported type")), - } -} - -fn int_from_string(a_string: &str, tag: &Tag) -> Result { - match a_string.parse::() { - Ok(n) => Ok(n), - Err(_) => match a_string.parse::() { - Ok(f) => match f.to_i64() { - Some(i) => Ok(i), - None => Err(ShellError::labeled_error( - "Could not convert string value to int", - "original value", - tag.clone(), - )), - }, - Err(_) => Err(ShellError::labeled_error( - "Could not convert string value to int", - "original value", - tag.clone(), - )), - }, - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/mod.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/mod.rs deleted file mode 100644 index ae029d887..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -mod binary; -mod column_path; -mod command; -mod filepath; -mod filesize; -mod int; -pub mod string; - -pub use self::filesize::SubCommand as IntoFilesize; -pub use binary::SubCommand as IntoBinary; -pub use column_path::SubCommand as IntoColumnPath; -pub use command::Command as Into; -pub use filepath::SubCommand as IntoFilepath; -pub use int::SubCommand as IntoInt; -pub use string::SubCommand as IntoString; diff --git a/old_nushell/crates/nu-command/src/commands/conversions/into/string.rs b/old_nushell/crates/nu-command/src/commands/conversions/into/string.rs deleted file mode 100644 index 70f19fe66..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/into/string.rs +++ /dev/null @@ -1,279 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use num_bigint::{BigInt, BigUint, ToBigInt}; -// TODO num_format::SystemLocale once platform-specific dependencies are stable (see Cargo.toml) -use nu_data::base::shape::InlineShape; -use num_format::Locale; -use num_traits::{Pow, Signed}; -use std::iter; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "into string" - } - - fn signature(&self) -> Signature { - Signature::build("into string") - .rest( - "rest", - SyntaxShape::ColumnPath, - "column paths to convert to string (for table input)", - ) - .named( - "decimals", - SyntaxShape::Int, - "decimal digits to which to round", - Some('d'), - ) - } - - fn usage(&self) -> &str { - "Convert value to string" - } - - fn run(&self, args: CommandArgs) -> Result { - into_string(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "convert decimal to string and round to nearest integer", - example: "echo 1.7 | into string -d 0", - result: Some(vec![UntaggedValue::string("2").into_untagged_value()]), - }, - Example { - description: "convert decimal to string", - example: "echo 4.3 | into string", - result: Some(vec![UntaggedValue::string("4.3").into_untagged_value()]), - }, - Example { - description: "convert string to string", - example: "echo '1234' | into string", - result: Some(vec![UntaggedValue::string("1234").into_untagged_value()]), - }, - Example { - description: "convert boolean to string", - example: "echo $true | into string", - result: Some(vec![UntaggedValue::string("true").into_untagged_value()]), - }, - Example { - description: "convert date to string", - example: "date now | into string", - result: None, - }, - Example { - description: "convert filepath to string", - example: "ls Cargo.toml | get name | into string", - result: None, - }, - Example { - description: "convert filesize to string", - example: "ls Cargo.toml | get size | into string", - result: None, - }, - ] - } -} - -fn into_string(args: CommandArgs) -> Result { - let decimals: Option> = args.get_flag("decimals")?; - let column_paths: Vec = args.rest(0)?; - - let digits = decimals.as_ref().map(|tagged| tagged.item); - let group_digits = false; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag(), digits, group_digits) - } else { - let mut ret = v; - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag(), digits, group_digits)), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -pub fn action( - input: &Value, - tag: impl Into, - digits: Option, - group_digits: bool, -) -> Result { - match &input.value { - UntaggedValue::Primitive(prim) => Ok(UntaggedValue::string(match prim { - Primitive::Int(int) => { - if group_digits { - format_int(*int) // int.to_formatted_string(*locale) - } else { - int.to_string() - } - } - Primitive::BigInt(int) => { - if group_digits { - format_bigint(int) // int.to_formatted_string(*locale) - } else { - int.to_string() - } - } - Primitive::Decimal(dec) => format_decimal(dec.clone(), digits, group_digits), - Primitive::String(a_string) => a_string.to_string(), - Primitive::Boolean(a_bool) => a_bool.to_string(), - Primitive::Date(a_date) => a_date.format("%c").to_string(), - Primitive::FilePath(a_filepath) => a_filepath.as_path().display().to_string(), - Primitive::Filesize(a_filesize) => { - let byte_string = InlineShape::format_bytes(*a_filesize, None); - byte_string.1 - } - Primitive::Nothing => "nothing".to_string(), - _ => { - return Err(ShellError::unimplemented(&format!( - "into string for primitive: {:?}", - prim - ))) - } - }) - .into_value(tag)), - UntaggedValue::Row(_) => Err(ShellError::labeled_error( - "specify column to use 'into string'", - "found table", - input.tag.clone(), - )), - UntaggedValue::Table(_) => Err(ShellError::unimplemented("into string for table")), - _ => Err(ShellError::unimplemented("into string for non-primitive")), - } -} - -fn format_int(int: i64) -> String { - int.to_string() - - // TODO once platform-specific dependencies are stable (see Cargo.toml) - // #[cfg(windows)] - // { - // int.to_formatted_string(&Locale::en) - // } - // #[cfg(not(windows))] - // { - // match SystemLocale::default() { - // Ok(locale) => int.to_formatted_string(&locale), - // Err(_) => int.to_formatted_string(&Locale::en), - // } - // } -} - -fn format_bigint(int: &BigInt) -> String { - int.to_string() - - // TODO once platform-specific dependencies are stable (see Cargo.toml) - // #[cfg(windows)] - // { - // int.to_formatted_string(&Locale::en) - // } - // #[cfg(not(windows))] - // { - // match SystemLocale::default() { - // Ok(locale) => int.to_formatted_string(&locale), - // Err(_) => int.to_formatted_string(&Locale::en), - // } - // } -} - -fn format_decimal(mut decimal: BigDecimal, digits: Option, group_digits: bool) -> String { - if let Some(n) = digits { - decimal = round_decimal(&decimal, n) - } - - if decimal.is_integer() && (digits.is_none() || digits == Some(0)) { - let int = decimal - .to_bigint() - .expect("integer BigDecimal should convert to BigInt"); - return if group_digits { - int.to_string() - } else { - format_bigint(&int) - }; - } - - let (int, exp) = decimal.as_bigint_and_exponent(); - let factor = BigInt::from(10).pow(BigUint::from(exp as u64)); // exp > 0 for non-int decimal - let int_part = &int / &factor; - let dec_part = (&int % &factor) - .abs() - .to_biguint() - .expect("BigInt::abs should always produce positive signed BigInt and thus BigUInt") - .to_str_radix(10); - - let dec_str = if let Some(n) = digits { - dec_part - .chars() - .chain(iter::repeat('0')) - .take(n as usize) - .collect() - } else { - String::from(dec_part.trim_end_matches('0')) - }; - - let format_default_loc = |int_part: BigInt| { - let loc = Locale::en; - //TODO: when num_format is available for recent bigint, replace this with the locale-based format - let (int_str, sep) = (int_part.to_string(), String::from(loc.decimal())); - - format!("{}{}{}", int_str, sep, dec_str) - }; - - format_default_loc(int_part) - - // TODO once platform-specific dependencies are stable (see Cargo.toml) - // #[cfg(windows)] - // { - // format_default_loc(int_part) - // } - // #[cfg(not(windows))] - // { - // match SystemLocale::default() { - // Ok(sys_loc) => { - // let int_str = int_part.to_formatted_string(&sys_loc); - // let sep = String::from(sys_loc.decimal()); - // format!("{}{}{}", int_str, sep, dec_str) - // } - // Err(_) => format_default_loc(int_part), - // } - // } -} - -fn round_decimal(decimal: &BigDecimal, mut digits: u64) -> BigDecimal { - let mut mag = decimal.clone(); - while mag >= BigDecimal::from(1) { - mag = mag / 10; - digits += 1; - } - - decimal.with_prec(digits) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/conversions/mod.rs b/old_nushell/crates/nu-command/src/commands/conversions/mod.rs deleted file mode 100644 index 70608f782..000000000 --- a/old_nushell/crates/nu-command/src/commands/conversions/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) mod into; - -pub use into::*; diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/alias.rs b/old_nushell/crates/nu-command/src/commands/core_commands/alias.rs deleted file mode 100644 index 4ce2a426d..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/alias.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; - -pub struct Alias; - -impl WholeStreamCommand for Alias { - fn name(&self) -> &str { - "alias" - } - - fn signature(&self) -> Signature { - Signature::build("alias") - .required("name", SyntaxShape::String, "the name of the alias") - .required("equals", SyntaxShape::String, "the equals sign") - .rest("rest", SyntaxShape::Any, "the expansion for the alias") - } - - fn usage(&self) -> &str { - "Alias a command to an expansion." - } - - fn run(&self, args: CommandArgs) -> Result { - alias(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Alias ll to ls -l", - example: "alias ll = ls -l", - result: None, - }] - } -} - -pub fn alias(args: CommandArgs) -> Result { - // TODO: is there a better way of checking whether no arguments were passed? - if args.nth(0).is_none() { - let aliases = UntaggedValue::string( - &args - .scope() - .get_aliases() - .iter() - .map(|val| format!("{} = '{}'", val.0, val.1.iter().map(|x| &x.item).join(" "))) - .join("\n"), - ); - return Ok(OutputStream::one(aliases)); - } - Ok(OutputStream::empty()) -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/debug.rs b/old_nushell/crates/nu-command/src/commands/core_commands/debug.rs deleted file mode 100644 index d92380e0d..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/debug.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; - -pub struct Debug; - -impl WholeStreamCommand for Debug { - fn name(&self) -> &str { - "debug" - } - - fn signature(&self) -> Signature { - Signature::build("debug").switch("raw", "Prints the raw value representation.", Some('r')) - } - - fn usage(&self) -> &str { - "Print the Rust debug representation of the values." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - debug_value(args) - } -} - -fn debug_value(args: CommandArgs) -> Result { - let raw = args.has_flag("raw"); - let input = args.input; - - Ok(input - .map(move |v| { - if raw { - ReturnSuccess::value( - UntaggedValue::string(format!("{:#?}", v)).into_untagged_value(), - ) - } else { - ReturnSuccess::debug_value(v) - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Debug; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Debug {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/def.rs b/old_nushell/crates/nu-command/src/commands/core_commands/def.rs deleted file mode 100644 index f247bd7a1..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/def.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{hir::CapturedBlock, Signature, SyntaxShape, Value}; -use nu_source::Tagged; - -pub struct Def; - -#[derive(Deserialize)] -pub struct DefArgs { - pub name: Tagged, - pub args: Tagged>, - pub block: CapturedBlock, -} - -impl WholeStreamCommand for Def { - fn name(&self) -> &str { - "def" - } - - fn signature(&self) -> Signature { - Signature::build("def") - .required("name", SyntaxShape::String, "the name of the command") - .required( - "params", - SyntaxShape::Table, - "the parameters of the command", - ) - .required("block", SyntaxShape::Block, "the body of the command") - } - - fn usage(&self) -> &str { - "Create a command and set it to a definition." - } - - fn run_with_actions(&self, _args: CommandArgs) -> Result { - // Currently, we don't do anything here because we should have already - // installed the definition as we entered the scope - // We just create a command so that we can get proper coloring - Ok(ActionStream::empty()) - } - - fn examples(&self) -> Vec { - vec![] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/describe.rs b/old_nushell/crates/nu-command/src/commands/core_commands/describe.rs deleted file mode 100644 index fa48a9ee9..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/describe.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; - -pub struct Describe; - -#[derive(Deserialize)] -pub struct DescribeArgs {} - -impl WholeStreamCommand for Describe { - fn name(&self) -> &str { - "describe" - } - - fn signature(&self) -> Signature { - Signature::build("describe") - } - - fn usage(&self) -> &str { - "Describes the objects in the stream." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - describe(args) - } -} - -pub fn describe(args: CommandArgs) -> Result { - Ok(args - .input - .map(|row| { - let name = value::plain_type(&row, 100); - ReturnSuccess::value( - UntaggedValue::string(name).into_value(Tag::unknown_anchor(row.tag.span)), - ) - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Describe; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Describe {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/do_.rs b/old_nushell/crates/nu-command/src/commands/core_commands/do_.rs deleted file mode 100644 index 413a9ab37..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/do_.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, hir::ExternalRedirection, Signature, SyntaxShape, UntaggedValue, Value, -}; - -pub struct Do; - -struct DoArgs { - block: CapturedBlock, - ignore_errors: bool, - rest: Vec, -} - -impl WholeStreamCommand for Do { - fn name(&self) -> &str { - "do" - } - - fn signature(&self) -> Signature { - Signature::build("do") - .required("block", SyntaxShape::Block, "the block to run ") - .switch( - "ignore-errors", - "ignore errors as the block runs", - Some('i'), - ) - .rest("rest", SyntaxShape::Any, "the parameter(s) for the block") - } - - fn usage(&self) -> &str { - "Runs a block, optionally ignoring errors." - } - - fn run(&self, args: CommandArgs) -> Result { - do_(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Run the block", - example: r#"do { echo hello }"#, - result: Some(vec![Value::from("hello")]), - }, - Example { - description: "Run the block and ignore errors", - example: r#"do -i { thisisnotarealcommand }"#, - result: Some(vec![]), - }, - Example { - description: "Run the block with a parameter", - example: r#"do { |x| $x + 100 } 55"#, - result: Some(vec![UntaggedValue::int(155).into()]), - }, - ] - } -} - -fn do_(args: CommandArgs) -> Result { - let external_redirection = args.call_info.args.external_redirection; - - let context = args.context().clone(); - let do_args = DoArgs { - block: args.req(0)?, - ignore_errors: args.has_flag("ignore-errors"), - rest: args.rest(1)?, - }; - - let block_redirection = match external_redirection { - ExternalRedirection::None => { - if do_args.ignore_errors { - ExternalRedirection::Stderr - } else { - ExternalRedirection::None - } - } - ExternalRedirection::Stdout => { - if do_args.ignore_errors { - ExternalRedirection::StdoutAndStderr - } else { - ExternalRedirection::Stdout - } - } - x => x, - }; - - context.scope.enter_scope(); - - context.scope.add_vars(&do_args.block.captured.entries); - - for (param, value) in do_args - .block - .block - .params - .positional - .iter() - .zip(do_args.rest) - { - context.scope.add_var(param.0.name(), value.clone()); - } - - let result = run_block( - &do_args.block.block, - &context, - args.input, - block_redirection, - ); - context.scope.exit_scope(); - - if do_args.ignore_errors { - // To properly ignore errors we need to redirect stderr, consume it, and remove - // any errors we see in the process. - - match result { - Ok(mut stream) => { - let output = stream.drain_vec(); - context.clear_errors(); - Ok(output.into_iter().into_output_stream()) - } - Err(_) => Ok(OutputStream::empty()), - } - } else { - result.map(|x| x.into_output_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::Do; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Do {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/echo.rs b/old_nushell/crates/nu-command/src/commands/core_commands/echo.rs deleted file mode 100644 index cddd5081a..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/echo.rs +++ /dev/null @@ -1,207 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::hir::Operator; -use nu_protocol::{Primitive, Range, RangeInclusion, Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct Echo; - -impl WholeStreamCommand for Echo { - fn name(&self) -> &str { - "echo" - } - - fn signature(&self) -> Signature { - Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo") - } - - fn usage(&self) -> &str { - "Echo the arguments back to the user." - } - - fn run(&self, args: CommandArgs) -> Result { - echo(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Put a hello message in the pipeline", - example: "echo 'hello'", - result: Some(vec![Value::from("hello")]), - }, - Example { - description: "Print the value of the special '$nu' variable", - example: "echo $nu", - result: None, - }, - ] - } -} - -pub fn expand_value_to_stream(v: Value) -> InputStream { - match v { - Value { - value: UntaggedValue::Table(table), - .. - } => InputStream::from_stream(table.into_iter()), - Value { - value: UntaggedValue::Primitive(Primitive::Range(range)), - tag, - } => InputStream::from_stream(RangeIterator::new(*range, tag)), - x => InputStream::one(x), - } -} - -fn echo(args: CommandArgs) -> Result { - let rest: Vec = args.rest(0)?; - - let stream = rest.into_iter().map(|i| match i.as_string() { - Ok(s) => InputStream::one(UntaggedValue::string(s).into_value(i.tag)), - _ => expand_value_to_stream(i), - }); - - Ok(InputStream::from_stream(stream.flatten())) -} - -struct RangeIterator { - curr: UntaggedValue, - end: UntaggedValue, - tag: Tag, - is_end_inclusive: bool, - moves_up: bool, - one: UntaggedValue, - negative_one: UntaggedValue, - done: bool, -} - -impl RangeIterator { - pub fn new(range: Range, tag: Tag) -> RangeIterator { - let start = match range.from.0.item { - Primitive::Nothing => Primitive::Int(0.into()), - x => x, - }; - - let end = match range.to.0.item { - Primitive::Nothing => Primitive::Int(i64::MAX), - x => x, - }; - - RangeIterator { - moves_up: start <= end, - curr: UntaggedValue::Primitive(start), - end: UntaggedValue::Primitive(end), - tag, - is_end_inclusive: matches!(range.to.1, RangeInclusion::Inclusive), - one: UntaggedValue::int(1), - negative_one: UntaggedValue::int(-1), - done: false, - } - } -} - -impl Iterator for RangeIterator { - type Item = Value; - fn next(&mut self) -> Option { - use std::cmp::Ordering; - if self.done { - return None; - } - - let ordering = if self.end == UntaggedValue::Primitive(Primitive::Nothing) { - Ordering::Less - } else { - match (&self.curr, &self.end) { - ( - UntaggedValue::Primitive(Primitive::Int(x)), - UntaggedValue::Primitive(Primitive::Int(y)), - ) => x.cmp(y), - ( - UntaggedValue::Primitive(Primitive::Decimal(x)), - UntaggedValue::Primitive(Primitive::Decimal(y)), - ) => x.cmp(y), - ( - UntaggedValue::Primitive(Primitive::Decimal(x)), - UntaggedValue::Primitive(Primitive::Int(y)), - ) => x.cmp(&(BigDecimal::from(*y))), - ( - UntaggedValue::Primitive(Primitive::Int(x)), - UntaggedValue::Primitive(Primitive::Decimal(y)), - ) => (BigDecimal::from(*x)).cmp(y), - _ => { - self.done = true; - return Some( - UntaggedValue::Error(ShellError::labeled_error( - "Cannot create range", - "unsupported range", - self.tag.span, - )) - .into_untagged_value(), - ); - } - } - }; - - if self.moves_up - && (ordering == Ordering::Less || self.is_end_inclusive && ordering == Ordering::Equal) - { - let next_value = nu_data::value::compute_values(Operator::Plus, &self.curr, &self.one); - - let mut next = match next_value { - Ok(result) => result, - - Err((left_type, right_type)) => { - self.done = true; - return Some( - UntaggedValue::Error(ShellError::coerce_error( - left_type.spanned(self.tag.span), - right_type.spanned(self.tag.span), - )) - .into_untagged_value(), - ); - } - }; - std::mem::swap(&mut self.curr, &mut next); - - Some(next.into_value(self.tag.clone())) - } else if !self.moves_up - && (ordering == Ordering::Greater - || self.is_end_inclusive && ordering == Ordering::Equal) - { - let next_value = - nu_data::value::compute_values(Operator::Plus, &self.curr, &self.negative_one); - - let mut next = match next_value { - Ok(result) => result, - Err((left_type, right_type)) => { - self.done = true; - return Some( - UntaggedValue::Error(ShellError::coerce_error( - left_type.spanned(self.tag.span), - right_type.spanned(self.tag.span), - )) - .into_untagged_value(), - ); - } - }; - std::mem::swap(&mut self.curr, &mut next); - - Some(next.into_value(self.tag.clone())) - } else { - None - } - } -} - -#[cfg(test)] -mod tests { - use super::Echo; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Echo {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/error/make.rs b/old_nushell/crates/nu-command/src/commands/core_commands/error/make.rs deleted file mode 100644 index 0d3ca69fe..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/error/make.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "error make" - } - - fn signature(&self) -> Signature { - Signature::build("error make") - } - - fn usage(&self) -> &str { - "Create an error." - } - - fn run(&self, args: CommandArgs) -> Result { - let input = args.input; - - Ok(input - .map(|value| { - make_error(&value) - .map(|err| UntaggedValue::Error(err).into_value(value.tag())) - .unwrap_or_else(|| { - UntaggedValue::Error(ShellError::untagged_runtime_error( - "Creating error value not supported.", - )) - .into_value(value.tag()) - }) - }) - .into_output_stream()) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Creates a labeled error", - example: r#"[ - [ msg, labels, span]; - ["The message", "Helpful message here", ([[start, end]; [0, 141]])] -] | error make"#, - result: None, - }] - } -} - -fn make_error(value: &Value) -> Option { - if let Value { - value: UntaggedValue::Row(dict), - .. - } = value - { - let msg = dict.get_data_by_key("msg".spanned_unknown()); - - let labels = - dict.get_data_by_key("labels".spanned_unknown()) - .and_then(|table| match &table.value { - UntaggedValue::Table(_) => table - .table_entries() - .map(|value| value.as_string().ok()) - .collect(), - UntaggedValue::Primitive(Primitive::String(label)) => { - Some(vec![label.to_string()]) - } - _ => None, - }); - - let _anchor = dict.get_data_by_key("tag".spanned_unknown()); - let span = dict.get_data_by_key("span".spanned_unknown()); - - if msg.is_none() || labels.is_none() || span.is_none() { - return None; - } - - let msg = msg.and_then(|msg| msg.as_string().ok()); - - if let Some(labels) = labels { - if labels.is_empty() { - return None; - } - - return Some(ShellError::labeled_error( - msg.expect("Message will always be present."), - &labels[0], - span.map(|data| match data { - Value { - value: UntaggedValue::Row(vals), - .. - } => match (vals.entries.get("start"), vals.entries.get("end")) { - (Some(start), Some(end)) => { - let start = start.as_usize().ok().unwrap_or(0); - let end = end.as_usize().ok().unwrap_or(0); - - Span::new(start, end) - } - (_, _) => Span::unknown(), - }, - _ => Span::unknown(), - }) - .unwrap_or_else(Span::unknown), - )); - } - } - - None -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/error/mod.rs b/old_nushell/crates/nu-command/src/commands/core_commands/error/mod.rs deleted file mode 100644 index 4a2ff564f..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/error/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod make; - -pub use make::SubCommand as ErrorMake; diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/find.rs b/old_nushell/crates/nu-command/src/commands/core_commands/find.rs deleted file mode 100644 index 559f9fa3b..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/find.rs +++ /dev/null @@ -1,110 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct Find; - -impl WholeStreamCommand for Find { - fn name(&self) -> &str { - "find" - } - - fn signature(&self) -> Signature { - Signature::build("find").rest("rest", SyntaxShape::String, "search term") - } - - fn usage(&self) -> &str { - "Find text in the output of a previous command" - } - - fn run(&self, args: CommandArgs) -> Result { - find(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Search pipeline output for multiple terms", - example: r#"ls | find toml md sh"#, - result: None, - }, - Example { - description: "Search strings for term(s)", - example: r#"echo Cargo.toml | find toml"#, - result: Some(vec![Value::from("Cargo.toml")]), - }, - Example { - description: "Search a number list for term(s)", - example: r#"[1 2 3 4 5] | find 5"#, - result: Some(vec![UntaggedValue::int(5).into()]), - }, - Example { - description: "Search string list for term(s)", - example: r#"[moe larry curly] | find l"#, - result: Some(vec![Value::from("larry"), Value::from("curly")]), - }, - ] - } -} - -fn row_contains(row: &Dictionary, search_terms: Vec) -> bool { - for term in search_terms { - for (k, v) in &row.entries { - let key = k.to_string().trim().to_lowercase(); - let value = v.convert_to_string().trim().to_lowercase(); - if key.contains(&term) || value.contains(&term) { - return true; - } - } - } - - false -} - -fn find(args: CommandArgs) -> Result { - let rest: Vec = args.rest(0)?; - - Ok(args - .input - .filter(move |row| match &row.value { - UntaggedValue::Row(row) => { - let sterms: Vec = rest - .iter() - .map(|t| t.convert_to_string().trim().to_lowercase()) - .collect(); - row_contains(row, sterms) - } - UntaggedValue::Primitive(_p) => { - // eprint!("prim {}", p.type_name()); - let sterms: Vec = rest - .iter() - .map(|t| t.convert_to_string().trim().to_lowercase()) - .collect(); - - let prim_string = &row.convert_to_string().trim().to_lowercase(); - for term in sterms { - if prim_string.contains(&term) { - return true; - } - } - - false - } - _ => false, - }) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Find; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Find {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/help.rs b/old_nushell/crates/nu-command/src/commands/core_commands/help.rs deleted file mode 100644 index 08a74bffa..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/help.rs +++ /dev/null @@ -1,353 +0,0 @@ -use crate::prelude::*; -use crate::TaggedListBuilder; -use nu_engine::{documentation::generate_docs, Command, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{ - Dictionary, NamedType, PositionalType, ReturnSuccess, Signature, SyntaxShape, - TaggedDictBuilder, UntaggedValue, Value, -}; -use nu_source::{SpannedItem, Tag, Tagged}; -use nu_value_ext::ValueExt; - -pub struct Help; - -impl WholeStreamCommand for Help { - fn name(&self) -> &str { - "help" - } - - fn signature(&self) -> Signature { - Signature::build("help") - .rest( - "rest", - SyntaxShape::String, - "the name of command to get help on", - ) - .named( - "find", - SyntaxShape::String, - "string to find in command usage", - Some('f'), - ) - } - - fn usage(&self) -> &str { - "Display help information about commands." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - help(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "show all commands and sub-commands", - example: "help commands", - result: None, - }, - Example { - description: "generate documentation", - example: "help generate_docs", - result: None, - }, - Example { - description: "show help for single command", - example: "help match", - result: None, - }, - Example { - description: "show help for single sub-command", - example: "help str lpad", - result: None, - }, - Example { - description: "search for string in command usage", - example: "help --find char", - result: None, - }, - ] - } -} - -fn help(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let scope = args.scope().clone(); - let find: Option> = args.get_flag("find")?; - let rest: Vec> = args.rest(0)?; - - if let Some(f) = find { - let search_string = f.item; - let full_commands = scope.get_commands_info(); - let mut found_cmds_vec = Vec::new(); - - for (key, cmd) in full_commands { - let mut indexmap = IndexMap::new(); - - let c = cmd.usage().to_string(); - let e = cmd.extra_usage().to_string(); - if key.to_lowercase().contains(&search_string) - || c.to_lowercase().contains(&search_string) - || e.to_lowercase().contains(&search_string) - { - indexmap.insert( - "name".to_string(), - UntaggedValue::string(key).into_value(&name), - ); - - indexmap.insert( - "usage".to_string(), - UntaggedValue::string(cmd.usage().to_string()).into_value(&name), - ); - - indexmap.insert( - "extra_usage".to_string(), - UntaggedValue::string(cmd.extra_usage().to_string()).into_value(&name), - ); - - found_cmds_vec - .push(UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&name)); - } - } - - return Ok(found_cmds_vec.into_iter().into_action_stream()); - } - - if !rest.is_empty() { - if rest[0].item == "commands" { - let mut sorted_names = scope.get_command_names(); - sorted_names.sort(); - - let (mut subcommand_names, command_names) = sorted_names - .into_iter() - // private only commands shouldn't be displayed - .filter(|cmd_name| { - scope - .get_command(cmd_name) - .filter(|command| !command.is_private()) - .is_some() - }) - .partition::, _>(|cmd_name| cmd_name.contains(' ')); - - fn process_name( - dict: &mut TaggedDictBuilder, - cmd_name: &str, - scope: Scope, - rest: Vec>, - name: Tag, - ) -> Result<(), ShellError> { - let document_tag = rest[0].tag.clone(); - let value = command_dict( - scope.get_command(cmd_name).ok_or_else(|| { - ShellError::labeled_error( - format!("Could not load {}", cmd_name), - "could not load command", - document_tag, - ) - })?, - name, - ); - - dict.insert_untagged("name", cmd_name); - dict.insert_untagged( - "description", - value - .get_data_by_key("usage".spanned_unknown()) - .ok_or_else(|| { - ShellError::labeled_error( - "Expected a usage key", - "expected a 'usage' key", - &value.tag, - ) - })? - .as_string()?, - ); - - Ok(()) - } - - fn make_subcommands_table( - subcommand_names: &mut Vec, - cmd_name: &str, - scope: Scope, - rest: Vec>, - name: Tag, - ) -> Result { - let (matching, not_matching) = - subcommand_names.drain(..).partition(|subcommand_name| { - subcommand_name.starts_with(&format!("{} ", cmd_name)) - }); - *subcommand_names = not_matching; - Ok(if !matching.is_empty() { - UntaggedValue::table( - &(matching - .into_iter() - .map(|cmd_name: String| -> Result<_, ShellError> { - let mut short_desc = TaggedDictBuilder::new(name.clone()); - process_name( - &mut short_desc, - &cmd_name, - scope.clone(), - rest.clone(), - name.clone(), - )?; - Ok(short_desc.into_value()) - }) - .collect::, _>>()?[..]), - ) - .into_value(name) - } else { - UntaggedValue::nothing().into_value(name) - }) - } - - let iterator = - command_names - .into_iter() - .map(move |cmd_name| -> Result<_, ShellError> { - let mut short_desc = TaggedDictBuilder::new(name.clone()); - process_name( - &mut short_desc, - &cmd_name, - scope.clone(), - rest.clone(), - name.clone(), - )?; - short_desc.insert_value( - "subcommands", - make_subcommands_table( - &mut subcommand_names, - &cmd_name, - scope.clone(), - rest.clone(), - name.clone(), - )?, - ); - ReturnSuccess::value(short_desc.into_value()) - }); - - Ok(iterator.into_action_stream()) - } else if rest[0].item == "generate_docs" { - Ok(ActionStream::one(ReturnSuccess::value(generate_docs( - &scope, - )))) - } else if rest.len() == 2 { - // Check for a subcommand - let command_name = format!("{} {}", rest[0].item, rest[1].item); - if let Some(command) = scope.get_command(&command_name) { - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(get_full_help(command.stream_command(), &scope)) - .into_value(Tag::unknown()), - ))) - } else { - Ok(ActionStream::empty()) - } - } else if let Some(command) = scope.get_command(&rest[0].item) { - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(get_full_help(command.stream_command(), &scope)) - .into_value(Tag::unknown()), - ))) - } else { - Err(ShellError::labeled_error( - "Can't find command (use 'help commands' for full list)", - "can't find command", - rest[0].tag.span, - )) - } - } else { - let msg = r#"Welcome to Nushell. - -Here are some tips to help you get started. - * help commands - list all available commands - * help - display help about a particular command - -Nushell works on the idea of a "pipeline". Pipelines are commands connected with the '|' character. -Each stage in the pipeline works together to load, parse, and display information to you. - -[Examples] - -List the files in the current directory, sorted by size: - ls | sort-by size - -Get information about the current system: - sys | get host - -Get the processes on your system actively using CPU: - ps | where cpu > 0 - -You can also learn more at https://www.nushell.sh/book/"#; - - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(msg).into_value(Tag::unknown()), - ))) - } -} - -fn for_spec(name: &str, ty: &str, required: bool, tag: impl Into) -> Value { - let tag = tag.into(); - - let mut spec = TaggedDictBuilder::new(tag); - - spec.insert_untagged("name", UntaggedValue::string(name)); - spec.insert_untagged("type", UntaggedValue::string(ty)); - spec.insert_untagged( - "required", - UntaggedValue::string(if required { "yes" } else { "no" }), - ); - - spec.into_value() -} - -pub fn signature_dict(signature: Signature, tag: impl Into) -> Value { - let tag = tag.into(); - let mut sig = TaggedListBuilder::new(&tag); - - for arg in &signature.positional { - let is_required = matches!(arg.0, PositionalType::Mandatory(_, _)); - - sig.push_value(for_spec(arg.0.name(), "argument", is_required, &tag)); - } - - if signature.rest_positional.is_some() { - let is_required = false; - sig.push_value(for_spec("rest", "argument", is_required, &tag)); - } - - for (name, ty) in &signature.named { - match ty.0 { - NamedType::Mandatory(_, _) => sig.push_value(for_spec(name, "flag", true, &tag)), - NamedType::Optional(_, _) => sig.push_value(for_spec(name, "flag", false, &tag)), - NamedType::Switch(_) => sig.push_value(for_spec(name, "switch", false, &tag)), - } - } - - sig.into_value() -} - -fn command_dict(command: Command, tag: impl Into) -> Value { - let tag = tag.into(); - - let mut cmd_dict = TaggedDictBuilder::new(&tag); - - cmd_dict.insert_untagged("name", UntaggedValue::string(command.name())); - - cmd_dict.insert_untagged("type", UntaggedValue::string("Command")); - - cmd_dict.insert_value("signature", signature_dict(command.signature(), tag)); - cmd_dict.insert_untagged("usage", UntaggedValue::string(command.usage())); - - cmd_dict.into_value() -} - -#[cfg(test)] -mod tests { - use super::Help; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Help {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/history.rs b/old_nushell/crates/nu-command/src/commands/core_commands/history.rs deleted file mode 100644 index 76447b246..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/history.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; -use std::fs::File; -use std::io::{BufRead, BufReader}; - -pub struct History; - -impl WholeStreamCommand for History { - fn name(&self) -> &str { - "history" - } - - fn signature(&self) -> Signature { - Signature::build("history").switch("clear", "Clears out the history entries", Some('c')) - } - - fn usage(&self) -> &str { - "Display command history." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - history(args) - } -} - -fn history(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let clear = args.has_flag("clear"); - - let path = if let Some(global_cfg) = &ctx.configs().lock().global_config { - nu_data::config::path::history_path_or_default(global_cfg) - } else { - nu_data::config::path::default_history_path() - }; - - if clear { - // This is a NOOP, the logic to clear is handled in cli.rs - Ok(ActionStream::empty()) - } else if let Ok(file) = File::open(path) { - let reader = BufReader::new(file); - // Skips the first line, which is a Rustyline internal - let output = reader.lines().skip(1).filter_map(move |line| match line { - Ok(line) => Some(ReturnSuccess::value( - UntaggedValue::string(line).into_value(tag.clone()), - )), - Err(_) => None, - }); - - Ok(output.into_action_stream()) - } else { - Err(ShellError::labeled_error( - "Could not open history", - "history file could not be opened", - tag, - )) - } -} - -#[cfg(test)] -mod tests { - use super::History; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(History {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/if_.rs b/old_nushell/crates/nu-command/src/commands/core_commands/if_.rs deleted file mode 100644 index 85451ec19..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/if_.rs +++ /dev/null @@ -1,154 +0,0 @@ -use crate::prelude::*; -use nu_engine::evaluate_baseline_expr; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, -}; -use nu_stream::OutputStream; - -pub struct If; - -impl WholeStreamCommand for If { - fn name(&self) -> &str { - "if" - } - - fn signature(&self) -> Signature { - Signature::build("if") - .required( - "condition", - SyntaxShape::MathExpression, - "the condition that must match", - ) - .required( - "then_case", - SyntaxShape::Block, - "block to run if condition is true", - ) - .required( - "else_case", - SyntaxShape::Block, - "block to run if condition is false", - ) - } - - fn usage(&self) -> &str { - "Run blocks if a condition is true or false." - } - - fn run(&self, args: CommandArgs) -> Result { - if_command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Run a block if a condition is true", - example: "let x = 10; if $x > 5 { echo 'greater than 5' } { echo 'less than or equal to 5' }", - result: Some(vec![UntaggedValue::string("greater than 5").into()]), - }, - Example { - description: "Run a block if a condition is false", - example: "let x = 1; if $x > 5 { echo 'greater than 5' } { echo 'less than or equal to 5' }", - result: Some(vec![UntaggedValue::string("less than or equal to 5").into()]), - }, - ] - } -} -fn if_command(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let external_redirection = args.call_info.args.external_redirection; - let context = Arc::new(args.context.clone()); - - let condition: CapturedBlock = args.req(0)?; - let then_case: CapturedBlock = args.req(1)?; - let else_case: CapturedBlock = args.req(2)?; - let input = args.input; - - let cond = { - if condition.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match condition.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr, - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - } - }; - - context.scope.enter_scope(); - context.scope.add_vars(&condition.captured.entries); - - //FIXME: should we use the scope that's brought in as well? - let condition = evaluate_baseline_expr(cond, &context); - let result = match condition { - Ok(condition) => match condition.as_bool() { - Ok(b) => { - if b { - run_block(&then_case.block, &context, input, external_redirection) - } else { - run_block(&else_case.block, &context, input, external_redirection) - } - } - Err(e) => Ok(OutputStream::from_stream( - vec![UntaggedValue::Error(e).into_untagged_value()].into_iter(), - )), - }, - Err(e) => Ok(OutputStream::from_stream( - vec![UntaggedValue::Error(e).into_untagged_value()].into_iter(), - )), - }; - context.scope.exit_scope(); - result -} - -#[cfg(test)] -mod tests { - use super::If; - use super::ShellError; - use nu_test_support::nu; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(If {}) - } - - #[test] - fn if_doesnt_leak_on_error() { - let actual = nu!( - ".", - r#" - def test-leak [] { - let var = "hello" - if 0 == "" {echo ok} {echo not} - } - test-leak - echo $var - "# - ); - - assert!(actual.err.contains("unknown variable")); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/ignore.rs b/old_nushell/crates/nu-command/src/commands/core_commands/ignore.rs deleted file mode 100644 index 9283a4885..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/ignore.rs +++ /dev/null @@ -1,49 +0,0 @@ -extern crate unicode_segmentation; - -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::Signature; - -pub struct Ignore; - -impl WholeStreamCommand for Ignore { - fn name(&self) -> &str { - "ignore" - } - - fn signature(&self) -> Signature { - Signature::build("ignore") - } - - fn usage(&self) -> &str { - "Ignore the output of the previous command in the pipeline" - } - - fn run(&self, args: CommandArgs) -> Result { - let _: Vec<_> = args.input.collect(); - - Ok(OutputStream::empty()) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Ignore the output of an echo command", - example: r#"echo done | ignore"#, - result: None, - }] - } -} - -#[cfg(test)] -mod tests { - use super::Ignore; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Ignore {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/let_.rs b/old_nushell/crates/nu-command/src/commands/core_commands/let_.rs deleted file mode 100644 index fb52df72b..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/let_.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::prelude::*; -use nu_engine::{evaluate_baseline_expr, FromValue, WholeStreamCommand}; - -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ClassifiedCommand}, - Signature, SyntaxShape, UntaggedValue, -}; - -pub struct Let; - -impl WholeStreamCommand for Let { - fn name(&self) -> &str { - "let" - } - - fn signature(&self) -> Signature { - Signature::build("let") - .required("name", SyntaxShape::String, "the name of the variable") - .required("equals", SyntaxShape::String, "the equals sign") - .required( - "expr", - SyntaxShape::MathExpression, - "the value for the variable", - ) - } - - fn usage(&self) -> &str { - "Create a variable and give it a value." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - letcmd(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Assign a simple value to a variable", - example: "let x = 3", - result: Some(vec![]), - }, - Example { - description: "Assign the result of an expression to a variable", - example: "let result = (3 + 7); echo $result", - result: Some(vec![UntaggedValue::int(1).into()]), - }, - Example { - description: "Create a variable using the full name", - example: "let $three = 3", - result: Some(vec![]), - }, - ] - } -} - -pub fn letcmd(args: CommandArgs) -> Result { - let ctx = &args.context; - let positional = args - .call_info - .args - .positional - .expect("Internal error: type checker should require args"); - - let var_name = positional[0].var_name()?; - let rhs_raw = evaluate_baseline_expr(&positional[2], ctx)?; - let tag: Tag = positional[2].span.into(); - - let rhs: CapturedBlock = FromValue::from_value(&rhs_raw)?; - - let (expr, _) = { - if rhs.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a value", - "expected a value", - tag, - )); - } - match rhs.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => (expr, &rhs.captured), - _ => { - return Err(ShellError::labeled_error( - "Expected a value", - "expected a value", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a value", - "expected a value", - tag, - )); - } - } - }; - - ctx.scope.enter_scope(); - let value = evaluate_baseline_expr(expr, ctx); - ctx.scope.exit_scope(); - - let value = value?; - - // Note: this is a special case for setting the context from a command - // In this case, if we don't set it now, we'll lose the scope that this - // variable should be set into. - ctx.scope.add_var(var_name, value); - - Ok(ActionStream::empty()) -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/mod.rs b/old_nushell/crates/nu-command/src/commands/core_commands/mod.rs deleted file mode 100644 index c7fd932d5..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -mod alias; -mod debug; -mod def; -mod describe; -mod do_; -pub(crate) mod echo; -mod error; -mod find; -mod help; -mod history; -mod if_; -mod ignore; -mod let_; -mod nu_plugin; -mod nu_signature; -mod source; -mod tags; -mod tutor; -mod unalias; -mod version; - -pub use self::nu_plugin::SubCommand as NuPlugin; -pub use self::nu_signature::{ - loglevels, testbins, version as core_version, Command as NuSignature, -}; -pub use alias::Alias; -pub use debug::Debug; -pub use def::Def; -pub use describe::Describe; -pub use do_::Do; -pub use echo::Echo; -pub use error::*; -pub use find::Find; -pub use help::Help; -pub use history::History; -pub use if_::If; -pub use ignore::Ignore; -pub use let_::Let; -pub use source::Source; -pub use tags::Tags; -pub use tutor::Tutor; -pub use unalias::Unalias; -pub use version::{version, Version}; diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/nu_plugin.rs b/old_nushell/crates/nu-command/src/commands/core_commands/nu_plugin.rs deleted file mode 100644 index 0f91a6c14..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/nu_plugin.rs +++ /dev/null @@ -1,120 +0,0 @@ -use std::path::PathBuf; - -use crate::prelude::*; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_path::canonicalize_with; -use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -#[cfg(unix)] -use std::os::unix::fs::PermissionsExt; - -pub struct SubCommand; - -#[derive(Deserialize)] -pub struct Arguments { - #[serde(rename = "load")] - pub load_path: Option>, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "nu plugin" - } - - fn signature(&self) -> Signature { - Signature::build("nu plugin").named( - "load", - SyntaxShape::FilePath, - "a path to load the plugins from", - Some('l'), - ) - } - - fn usage(&self) -> &str { - "Nu Plugin" - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Load all plugins in the current directory", - example: "nu plugin --load .", - result: None, - }] - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let scope = args.scope().clone(); - let shell_manager = args.shell_manager(); - - let load_path: Option> = args.get_flag("load")?; - - if let Some(Tagged { - item: load_path, - tag, - }) = load_path - { - let path = canonicalize_with(load_path, shell_manager.path()).map_err(|_| { - ShellError::labeled_error( - "Cannot load plugins from directory", - "directory not found", - &tag, - ) - })?; - - if !path.is_dir() { - return Err(ShellError::labeled_error( - "Cannot load plugins from directory", - "is not a directory", - &tag, - )); - } - - #[cfg(unix)] - { - let has_exec = path - .metadata() - .map(|m| umask::Mode::from(m.permissions().mode()).has(umask::USER_READ)) - .map_err(|e| { - ShellError::labeled_error( - "Cannot load plugins from directory", - format!("cannot stat ({})", e), - &tag, - ) - })?; - - if !has_exec { - return Err(ShellError::labeled_error( - "Cannot load plugins from directory", - "permission denied", - &tag, - )); - } - } - - return Ok(vec![ReturnSuccess::action(CommandAction::AddPlugins( - path.to_string_lossy().to_string(), - ))] - .into()); - } - - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(get_full_help(&SubCommand, &scope)).into_value(Tag::unknown()), - ))) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/nu_signature.rs b/old_nushell/crates/nu-command/src/commands/core_commands/nu_signature.rs deleted file mode 100644 index d8a74295d..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/nu_signature.rs +++ /dev/null @@ -1,71 +0,0 @@ -use nu_engine::WholeStreamCommand; -use nu_protocol::{Signature, SyntaxShape}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "nu" - } - - fn signature(&self) -> Signature { - Signature::build("nu") - .switch("version", "Display Nu version", Some('v')) - .switch("stdin", "redirect stdin", None) - .switch("skip-plugins", "do not load plugins", None) - .switch("no-history", "don't save history", None) - .switch("perf", "show startup performance metrics", None) - .switch("login", "start Nu as if it was a login shell", Some('l')) - .named( - "commands", - SyntaxShape::String, - "commands to run", - Some('c'), - ) - .named( - "testbin", - SyntaxShape::String, - "test bin: echo_env, cococo, iecho, fail, nonu, chop, repeater, meow", - None, - ) - .named("develop", SyntaxShape::String, "trace mode", None) - .named("debug", SyntaxShape::String, "debug mode", None) - .named( - "loglevel", - SyntaxShape::String, - "LEVEL: error, warn, info, debug, trace", - None, - ) - .named( - "config-file", - SyntaxShape::FilePath, - "custom configuration source file", - None, - ) - .rest("rest", SyntaxShape::String, "source file(s) to run") - } - - fn usage(&self) -> &str { - "Nu - A new type of shell." - } -} - -pub fn version() -> &'static str { - env!("CARGO_PKG_VERSION") -} - -pub fn testbins() -> Vec { - vec![ - "echo_env", "cococo", "iecho", "fail", "nonu", "chop", "repeater", "meow", - ] - .into_iter() - .map(String::from) - .collect() -} - -pub fn loglevels() -> Vec { - vec!["error", "warn", "info", "debug", "trace"] - .into_iter() - .map(String::from) - .collect() -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/source.rs b/old_nushell/crates/nu-command/src/commands/core_commands/source.rs deleted file mode 100644 index 862ef6286..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/source.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::prelude::*; -use nu_engine::{script, WholeStreamCommand}; - -use nu_errors::ShellError; -use nu_path::{canonicalize, canonicalize_with}; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; - -use std::path::Path; - -pub struct Source; - -#[derive(Deserialize)] -pub struct SourceArgs { - pub filename: Tagged, -} - -impl WholeStreamCommand for Source { - fn name(&self) -> &str { - "source" - } - - fn signature(&self) -> Signature { - Signature::build("source").required( - "filename", - SyntaxShape::FilePath, - "the filepath to the script file to source", - ) - } - - fn usage(&self) -> &str { - "Runs a script file in the current context." - } - - fn run(&self, args: CommandArgs) -> Result { - source(args) - } - - fn examples(&self) -> Vec { - vec![] - } -} - -pub fn source(args: CommandArgs) -> Result { - let ctx = &args.context; - let filename: Tagged = args.req(0)?; - - let source_file = Path::new(&filename.item); - - // Note: this is a special case for setting the context from a command - // In this case, if we don't set it now, we'll lose the scope that this - // variable should be set into. - - let lib_dirs = &ctx - .configs() - .lock() - .global_config - .as_ref() - .map(|configuration| match configuration.var("lib_dirs") { - Some(paths) => paths - .table_entries() - .cloned() - .map(|path| path.as_string()) - .collect(), - None => vec![], - }); - - if let Some(dir) = lib_dirs { - for lib_path in dir { - match lib_path { - Ok(name) => { - let path = if let Ok(p) = canonicalize_with(&source_file, name) { - p - } else { - continue; - }; - - if let Ok(contents) = std::fs::read_to_string(path) { - let result = script::run_script_standalone(contents, true, ctx, false); - - if let Err(err) = result { - ctx.error(err); - } - return Ok(OutputStream::empty()); - } - } - Err(reason) => { - ctx.error(reason.clone()); - } - } - } - } - - let path = canonicalize(source_file).map_err(|e| { - ShellError::labeled_error( - format!("Can't load source file. Reason: {}", e), - "Can't load this file", - filename.span(), - ) - })?; - - let contents = std::fs::read_to_string(path); - - match contents { - Ok(contents) => { - let result = script::run_script_standalone(contents, true, ctx, false); - - if let Err(err) = result { - ctx.error(err); - } - Ok(OutputStream::empty()) - } - Err(e) => { - ctx.error(ShellError::labeled_error( - format!("Can't load source file. Reason: {}", e), - "Can't load this file", - filename.span(), - )); - - Ok(OutputStream::empty()) - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/tags.rs b/old_nushell/crates/nu-command/src/commands/core_commands/tags.rs deleted file mode 100644 index 73e39b274..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/tags.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value}; - -pub struct Tags; - -impl WholeStreamCommand for Tags { - fn name(&self) -> &str { - "tags" - } - - fn signature(&self) -> Signature { - Signature::build("tags") - } - - fn usage(&self) -> &str { - "Read the tags (metadata) for values." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(tags(args)) - } -} - -fn build_tag_table(tag: impl Into) -> Value { - let tag = tag.into(); - let span = tag.span; - - TaggedDictBuilder::build(tag.clone(), |tags| { - if let Some(anchor) = anchor_as_value(&tag) { - tags.insert_value("anchor", anchor); - } - - tags.insert_value( - "span", - TaggedDictBuilder::build(tag.clone(), |span_dict| { - span_dict.insert_untagged("start", UntaggedValue::int(span.start() as i64)); - span_dict.insert_untagged("end", UntaggedValue::int(span.end() as i64)); - }), - ); - }) -} - -fn tags(args: CommandArgs) -> OutputStream { - if args.input.is_empty() { - OutputStream::one(build_tag_table(&args.name_tag())) - } else { - args.input - .map(move |v| build_tag_table(v.tag())) - .into_output_stream() - } -} - -fn anchor_as_value(tag: &Tag) -> Option { - let anchor = tag.anchor.as_ref(); - - anchor.as_ref()?; - - Some(TaggedDictBuilder::build(tag, |table| { - let value = match anchor { - Some(AnchorLocation::File(path)) => { - Some(("file", UntaggedValue::from(path.to_string()))) - } - Some(AnchorLocation::Url(destination)) => { - Some(("url", UntaggedValue::from(destination.to_string()))) - } - Some(AnchorLocation::Source(text)) => Some(( - "source", - UntaggedValue::Primitive(Primitive::String(text.to_string())), - )), - None => None, - }; - - if let Some((key, value)) = value { - table.insert_untagged(key, value); - } - })) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Tags; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Tags {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/tutor.rs b/old_nushell/crates/nu-command/src/commands/core_commands/tutor.rs deleted file mode 100644 index 284515ae5..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/tutor.rs +++ /dev/null @@ -1,431 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; - -pub struct Tutor; - -impl WholeStreamCommand for Tutor { - fn name(&self) -> &str { - "tutor" - } - - fn signature(&self) -> Signature { - Signature::build("tutor") - .optional( - "search", - SyntaxShape::String, - "item to search for, or 'list' to list available tutorials", - ) - .named( - "find", - SyntaxShape::String, - "Search tutorial for a phrase", - Some('f'), - ) - } - - fn usage(&self) -> &str { - "Run the tutorial. To begin, run: tutor" - } - - fn run(&self, args: CommandArgs) -> Result { - tutor(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Begin the tutorial", - example: "tutor begin", - result: None, - }, - Example { - description: "Search a tutorial by phrase", - example: "tutor -f \"$in\"", - result: None, - }, - ] - } -} - -fn tutor(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let scope = args.scope().clone(); - - let search: Option = args.opt(0).unwrap_or(None); - let find: Option = args.get_flag("find")?; - - let search_space = [ - (vec!["begin"], begin_tutor()), - ( - vec!["table", "tables", "row", "rows", "column", "columns"], - table_tutor(), - ), - (vec!["cell", "cells"], cell_tutor()), - ( - vec![ - "expr", - "exprs", - "expressions", - "subexpression", - "subexpressions", - "sub-expression", - "sub-expressions", - ], - expression_tutor(), - ), - (vec!["echo"], echo_tutor()), - (vec!["each", "iteration", "iter"], each_tutor()), - ( - vec!["var", "vars", "variable", "variables"], - variable_tutor(), - ), - (vec!["engine-q", "e-q"], engineq_tutor()), - (vec!["block", "blocks"], block_tutor()), - (vec!["shorthand", "shorthands"], shorthand_tutor()), - ]; - - if let Some(find) = find { - let mut results = vec![]; - for search_group in search_space { - if search_group.1.contains(&find) { - results.push(search_group.0[0].to_string()) - } - } - - let message = format!("You can find '{}' in the following topics:\n{}\n\nYou can learn about a topic using `tutor` followed by the name of the topic.\nFor example: `tutor table` to open the table topic.\n\n", - find, - results.into_iter().map(|x| format!("- {}", x)).join("\n") - ); - - return Ok(display(tag, &scope, &message)); - } else if let Some(search) = search { - for search_group in search_space { - if search_group.0.contains(&search.as_str()) { - return Ok(display(tag, &scope, search_group.1)); - } - } - } - Ok(display(tag, &scope, default_tutor())) -} - -fn default_tutor() -> &'static str { - r#" -Welcome to the Nushell tutorial! - -With the `tutor` command, you'll be able to learn a lot about how Nushell -works along with many fun tips and tricks to speed up everyday tasks. - -To get started, you can use `tutor begin`. - -"# -} - -fn begin_tutor() -> &'static str { - r#" -Nushell is a structured shell and programming language. One way to begin -using it is to try a few of the commands. - -The first command to try is `ls`. The `ls` command will show you a list -of the files in the current directory. Notice that these files are shown -as a table. Each column of this table not only tells us what is being -shown, but also gives us a way to work with the data. - -You can combine the `ls` command with other commands using the pipeline -symbol '|'. This allows data to flow from one command to the next. - -For example, if we only wanted the name column, we could do: -``` -ls | select name -``` -Notice that we still get a table, but this time it only has one column: -the name column. - -You can continue to learn more about tables by running: -``` -tutor tables -``` -If at any point, you'd like to restart this tutorial, you can run: -``` -tutor begin -``` -"# -} - -fn table_tutor() -> &'static str { - r#" -The most common form of data in Nushell is the table. Tables contain rows and -columns of data. In each cell of the table, there is data that you can access -using Nushell commands. - -To get the 3rd row in the table, you can use the `nth` command: -``` -ls | nth 2 -``` -This will get the 3rd (note that `nth` is zero-based) row in the table created -by the `ls` command. You can use `nth` on any table created by other commands -as well. - -You can also access the column of data in one of two ways. If you want -to keep the column as part of a new table, you can use `select`. -``` -ls | select name -``` -This runs `ls` and returns only the "name" column of the table. - -If, instead, you'd like to get access to the values inside of the column, you -can use the `get` command. -``` -ls | get name -``` -This allows us to get to the list of strings that are the filenames rather -than having a full table. In some cases, this can make the names easier to -work with. - -You can continue to learn more about working with cells of the table by -running: -``` -tutor cells -``` -"# -} - -fn cell_tutor() -> &'static str { - r#" -Working with cells of data in the table is a key part of working with data in -Nushell. Because of this, there is a rich list of commands to work with cells -as well as handy shorthands for accessing cells. - -Cells can hold simple values like strings and numbers, or more complex values -like lists and tables. - -To reach a cell of data from a table, you can combine a row operation and a -column operation. -``` -ls | nth 4 | get name -``` -You can combine these operations into one step using a shortcut. -``` -(ls).4.name -``` -Names/strings represent columns names and numbers represent row numbers. - -The `(ls)` is a form of expression. You can continue to learn more about -expressions by running: -``` -tutor expressions -``` -You can also learn about these cell shorthands by running: -``` -tutor shorthands -``` -"# -} - -fn expression_tutor() -> &'static str { - r#" -Expressions give you the power to mix calls to commands with math. The -simplest expression is a single value like a string or number. -``` -3 -``` -Expressions can also include math operations like addition or division. -``` -10 / 2 -``` -Normally, an expression is one type of operation: math or commands. You can -mix these types by using subexpressions. Subexpressions are just like -expressions, but they're wrapped in parentheses `()`. -``` -10 * (3 + 4) -``` -Here we use parentheses to create a higher math precedence in the math -expression. -``` -echo (2 + 3) -``` -You can continue to learn more about the `echo` command by running: -``` -tutor echo -``` -"# -} - -fn echo_tutor() -> &'static str { - r#" -The `echo` command in Nushell is a powerful tool for not only seeing values, -but also for creating new ones. -``` -echo "Hello" -``` -You can echo output. This output, if it's not redirected using a "|" pipeline -will be displayed to the screen. -``` -echo 1..10 -``` -You can also use echo to work with individual values of a range. In this -example, `echo` will create the values from 1 to 10 as a list. -``` -echo 1 2 3 4 5 -``` -You can also create lists of values by passing `echo` multiple arguments. -This can be helpful if you want to later processes these values. - -The `echo` command can pair well with the `each` command which can run -code on each row, or item, of input. - -You can continue to learn more about the `each` command by running: -``` -tutor each -``` -"# -} - -fn each_tutor() -> &'static str { - r#" -The `each` command gives us a way of working with each individual row or -element of a list one at a time. It reads these in from the pipeline and -runs a block on each element. A block is a group of pipelines. -``` -echo 1 2 3 | each { $it + 10} -``` -This example iterates over each element sent by `echo`, giving us three new -values that are the original value + 10. Here, the `$it` is a variable that -is the name given to the block's parameter by default. - -You can learn more about blocks by running: -``` -tutor blocks -``` -You can also learn more about variables by running: -``` -tutor variables -``` -"# -} - -fn variable_tutor() -> &'static str { - r#" -Variables are an important way to store values to be used later. To create a -variable, you can use the `let` keyword. The `let` command will create a -variable and then assign it a value in one step. -``` -let $x = 3 -``` -Once created, we can refer to this variable by name. -``` -$x -``` -Nushell also comes with built-in variables. The `$nu` variable is a reserved -variable that contains a lot of information about the currently running -instance of Nushell. The `$it` variable is the name given to block parameters -if you don't specify one. And `$in` is the variable that allows you to work -with all of the data coming in from the pipeline in one place. - -"# -} - -fn block_tutor() -> &'static str { - r#" -Blocks are a special form of expression that hold code to be run at a later -time. Often, you'll see blocks as one of the arguments given to commands -like `each` and `if`. -``` -ls | each {|x| $x.name} -``` -The above will create a list of the filenames in the directory. -``` -if $true { echo "it's true" } { echo "it's not true" } -``` -This `if` call will run the first block if the expression is true, or the -second block if the expression is false. - -"# -} - -fn shorthand_tutor() -> &'static str { - r#" -You can access cells in a table using a shorthand notation sometimes called a -"column path" or "cell path". These paths allow you to go from a table to -rows, columns, or cells inside of the table. - -Shorthand paths are made from rows numbers, column names, or both. You can use -them on any variable or subexpression. -``` -$nu.cwd -``` -The above accesses the built-in `$nu` variable, gets its table, and then uses -the shorthand path to retrieve only the cell data inside the "cwd" column. -``` -(ls).name.4 -``` -This will retrieve the cell data in the "name" column on the 5th row (note: -row numbers are zero-based). - -Rows and columns don't need to come in any specific order. You can get the -same value using: -``` -(ls).4.name -``` -"# -} - -fn engineq_tutor() -> &'static str { - r#" -Engine-q is the upcoming engine for Nushell. Build for speed and correctness, -it also comes with a set of changes from Nushell versions prior to 0.60. To -get ready for engine-q look for some of these changes that might impact your -current scripts: - -* Engine-q now uses a few new data structures, including a record syntax - that allows you to model key-value pairs similar to JSON objects. -* Environment variables can now contain more than just strings. Structured - values are converted to strings for external commands using converters. -* `if` will now use an `else` keyword before the else block. -* We're moving from "config.toml" to "config.nu". This means startup will - now be a script file. -* `config` and its subcommands are being replaced by a record that you can - update in the shell which contains all the settings under the variable - `$config`. -* bigint/bigdecimal values are now machine i64 and f64 values -* And more, you can read more about upcoming changes in the up-to-date list - at: https://github.com/nushell/engine-q/issues/522 -"# -} - -fn display(tag: Tag, scope: &Scope, help: &str) -> OutputStream { - let help = help.split('`'); - - let mut build = String::new(); - let mut code_mode = false; - let palette = nu_engine::DefaultPalette {}; - - for item in help { - if code_mode { - code_mode = false; - - //TODO: support no-color mode - let colored_example = nu_engine::Painter::paint_string(item, scope, &palette); - build.push_str(&colored_example); - } else { - code_mode = true; - build.push_str(item); - } - } - - OutputStream::one(UntaggedValue::string(build).into_value(tag)) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Tutor; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Tutor {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/unalias.rs b/old_nushell/crates/nu-command/src/commands/core_commands/unalias.rs deleted file mode 100644 index 75de72b95..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/unalias.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; - -pub struct Unalias; - -impl WholeStreamCommand for Unalias { - fn name(&self) -> &str { - "unalias" - } - - fn signature(&self) -> Signature { - Signature::build("unalias").required("name", SyntaxShape::String, "the name of the alias") - } - - fn usage(&self) -> &str { - "Removes an alias" - } - - fn run(&self, args: CommandArgs) -> Result { - unalias(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Remove the 'v' alias", - example: "unalias v", - result: None, - }] - } -} - -pub fn unalias(_: CommandArgs) -> Result { - Ok(OutputStream::empty()) -} diff --git a/old_nushell/crates/nu-command/src/commands/core_commands/version.rs b/old_nushell/crates/nu-command/src/commands/core_commands/version.rs deleted file mode 100644 index dcd08bcf0..000000000 --- a/old_nushell/crates/nu-command/src/commands/core_commands/version.rs +++ /dev/null @@ -1,315 +0,0 @@ -use crate::prelude::*; -use indexmap::IndexMap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{value::StrExt, value::StringExt, Dictionary, Signature, UntaggedValue}; - -pub mod shadow { - include!(concat!(env!("OUT_DIR"), "/shadow.rs")); -} - -pub struct Version; - -impl WholeStreamCommand for Version { - fn name(&self) -> &str { - "version" - } - - fn signature(&self) -> Signature { - Signature::build("version") - } - - fn usage(&self) -> &str { - "Display Nu version." - } - - fn run(&self, args: CommandArgs) -> Result { - version(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Display Nu version", - example: "version", - result: None, - }] - } -} - -pub fn version(args: CommandArgs) -> Result { - let tag = args.call_info.args.span; - - let mut indexmap = IndexMap::with_capacity(4); - - indexmap.insert( - "version".to_string(), - UntaggedValue::string(super::nu_signature::version()).into_value(&tag), - ); - - let branch: Option<&str> = Some(shadow::BRANCH).filter(|x| !x.is_empty()); - if let Some(branch) = branch { - indexmap.insert( - "branch".to_string(), - branch.to_pattern_untagged_value().into_value(&tag), - ); - } - - let short_commit: Option<&str> = Some(shadow::SHORT_COMMIT).filter(|x| !x.is_empty()); - if let Some(short_commit) = short_commit { - indexmap.insert( - "short_commit".to_string(), - short_commit.to_pattern_untagged_value().into_value(&tag), - ); - } - let commit_hash: Option<&str> = Some(shadow::COMMIT_HASH).filter(|x| !x.is_empty()); - if let Some(commit_hash) = commit_hash { - indexmap.insert( - "commit_hash".to_string(), - commit_hash.to_pattern_untagged_value().into_value(&tag), - ); - } - let commit_date: Option<&str> = Some(shadow::COMMIT_DATE).filter(|x| !x.is_empty()); - if let Some(commit_date) = commit_date { - indexmap.insert( - "commit_date".to_string(), - commit_date.to_pattern_untagged_value().into_value(&tag), - ); - } - - let build_os: Option<&str> = Some(shadow::BUILD_OS).filter(|x| !x.is_empty()); - if let Some(build_os) = build_os { - indexmap.insert( - "build_os".to_string(), - build_os.to_pattern_untagged_value().into_value(&tag), - ); - } - - let rust_version: Option<&str> = Some(shadow::RUST_VERSION).filter(|x| !x.is_empty()); - if let Some(rust_version) = rust_version { - indexmap.insert( - "rust_version".to_string(), - rust_version.to_pattern_untagged_value().into_value(&tag), - ); - } - - let rust_channel: Option<&str> = Some(shadow::RUST_CHANNEL).filter(|x| !x.is_empty()); - if let Some(rust_channel) = rust_channel { - indexmap.insert( - "rust_channel".to_string(), - rust_channel.to_pattern_untagged_value().into_value(&tag), - ); - } - - let cargo_version: Option<&str> = Some(shadow::CARGO_VERSION).filter(|x| !x.is_empty()); - if let Some(cargo_version) = cargo_version { - indexmap.insert( - "cargo_version".to_string(), - cargo_version.to_pattern_untagged_value().into_value(&tag), - ); - } - - let pkg_version: Option<&str> = Some(shadow::PKG_VERSION).filter(|x| !x.is_empty()); - if let Some(pkg_version) = pkg_version { - indexmap.insert( - "pkg_version".to_string(), - pkg_version.to_pattern_untagged_value().into_value(&tag), - ); - } - - let build_time: Option<&str> = Some(shadow::BUILD_TIME).filter(|x| !x.is_empty()); - if let Some(build_time) = build_time { - indexmap.insert( - "build_time".to_string(), - build_time.to_pattern_untagged_value().into_value(&tag), - ); - } - - let build_rust_channel: Option<&str> = - Some(shadow::BUILD_RUST_CHANNEL).filter(|x| !x.is_empty()); - if let Some(build_rust_channel) = build_rust_channel { - indexmap.insert( - "build_rust_channel".to_string(), - build_rust_channel - .to_pattern_untagged_value() - .into_value(&tag), - ); - } - - indexmap.insert( - "features".to_string(), - features_enabled().join(", ").to_string_value_create_tag(), - ); - - // Manually create a list of all possible plugin names - let all_plugins = vec![ - "fetch", - "inc", - "match", - "post", - "ps", - "sys", - "textview", - "binaryview", - "chart bar", - "chart line", - "from bson", - "from sqlite", - "query json", - "s3", - "selector", - "start", - "to bson", - "to sqlite", - "tree", - "xpath", - ]; - - // Get a list of command names and check for plugins - let installed_plugins = args - .scope() - .get_command_names() - .into_iter() - .filter(|cmd| all_plugins.contains(&cmd.as_str())) - .collect::>(); - - indexmap.insert( - "installed_plugins".to_string(), - installed_plugins.join(", ").to_string_value_create_tag(), - ); - - let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag); - Ok(OutputStream::one(value)) -} - -fn features_enabled() -> Vec { - let mut names = vec!["default".to_string()]; - - // NOTE: There should be another way to know - // features on. - #[cfg(feature = "ctrlc")] - { - names.push("ctrlc".to_string()); - } - - // #[cfg(feature = "rich-benchmark")] - // { - // names.push("rich-benchmark".to_string()); - // } - - #[cfg(feature = "rustyline-support")] - { - names.push("rustyline".to_string()); - } - - #[cfg(feature = "term")] - { - names.push("term".to_string()); - } - - #[cfg(feature = "uuid_crate")] - { - names.push("uuid".to_string()); - } - - #[cfg(feature = "which")] - { - names.push("which".to_string()); - } - - #[cfg(feature = "zip")] - { - names.push("zip".to_string()); - } - - #[cfg(feature = "trash-support")] - { - names.push("trash".to_string()); - } - - #[cfg(feature = "dataframe")] - { - names.push("dataframe".to_string()); - } - - #[cfg(feature = "table-pager")] - { - names.push("table-pager".to_string()); - } - - // #[cfg(feature = "binaryview")] - // { - // names.push("binaryview".to_string()); - // } - - // #[cfg(feature = "start")] - // { - // names.push("start".to_string()); - // } - - // #[cfg(feature = "bson")] - // { - // names.push("bson".to_string()); - // } - - // #[cfg(feature = "sqlite")] - // { - // names.push("sqlite".to_string()); - // } - - // #[cfg(feature = "s3")] - // { - // names.push("s3".to_string()); - // } - - // #[cfg(feature = "chart")] - // { - // names.push("chart".to_string()); - // } - - // #[cfg(feature = "xpath")] - // { - // names.push("xpath".to_string()); - // } - - // #[cfg(feature = "selector")] - // { - // names.push("selector".to_string()); - // } - - // #[cfg(feature = "extra")] - // { - // names.push("extra".to_string()); - // } - - // #[cfg(feature = "preserve_order")] - // { - // names.push("preserve_order".to_string()); - // } - - // #[cfg(feature = "wee_alloc")] - // { - // names.push("wee_alloc".to_string()); - // } - - // #[cfg(feature = "console_error_panic_hook")] - // { - // names.push("console_error_panic_hook".to_string()); - // } - - names.sort(); - - names -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Version; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Version {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/aggregate.rs b/old_nushell/crates/nu-command/src/commands/dataframe/aggregate.rs deleted file mode 100644 index b5649a56b..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/aggregate.rs +++ /dev/null @@ -1,293 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, FrameStruct, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::Tagged; -use polars::{frame::groupby::GroupBy, prelude::PolarsError}; - -enum Operation { - Mean, - Sum, - Min, - Max, - First, - Last, - Nunique, - Quantile(f64), - Median, - Var, - Std, - Count, -} - -impl Operation { - fn from_tagged( - name: &Tagged, - quantile: Option>, - ) -> Result { - match name.item.as_ref() { - "mean" => Ok(Operation::Mean), - "sum" => Ok(Operation::Sum), - "min" => Ok(Operation::Min), - "max" => Ok(Operation::Max), - "first" => Ok(Operation::First), - "last" => Ok(Operation::Last), - "nunique" => Ok(Operation::Nunique), - "quantile" => { - match quantile { - None => Err(ShellError::labeled_error( - "Quantile value not fount", - "Quantile operation requires quantile value", - &name.tag, - )), - Some(value ) => { - if (value.item < 0.0) | (value.item > 1.0) { - Err(ShellError::labeled_error( - "Inappropriate quantile", - "Quantile value should be between 0.0 and 1.0", - &value.tag, - )) - } else { - Ok(Operation::Quantile(value.item)) - } - } - } - } - "median" => Ok(Operation::Median), - "var" => Ok(Operation::Var), - "std" => Ok(Operation::Std), - "count" => Ok(Operation::Count), - _ => Err(ShellError::labeled_error_with_secondary( - "Operation not fount", - "Operation does not exist", - &name.tag, - "Perhaps you want: mean, sum, min, max, first, last, nunique, quantile, median, var, std, or count", - &name.tag, - )), - } - } -} - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe aggregate" - } - - fn usage(&self) -> &str { - "[DataFrame, GroupBy, Series] Performs an aggregation operation on a dataframe, groupby or series object" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe aggregate") - .required("operation", SyntaxShape::String, "aggregate operation") - .named( - "quantile", - SyntaxShape::Number, - "quantile value for quantile operation", - Some('q'), - ) - .switch( - "explicit", - "returns explicit names for groupby aggregations", - Some('e'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Aggregate sum by grouping by column a and summing on col b", - example: - "[[a b]; [one 1] [one 2]] | dataframe to-df | dataframe group-by a | dataframe aggregate sum", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![UntaggedValue::string("one").into()]), - Column::new("b".to_string(), vec![UntaggedValue::int(3).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Aggregate sum in dataframe columns", - example: "[[a b]; [4 1] [5 2]] | dataframe to-df | dataframe aggregate sum", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![UntaggedValue::int(9).into()]), - Column::new("b".to_string(), vec![UntaggedValue::int(3).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Aggregate sum in series", - example: "[4 1 5 6] | dataframe to-df | dataframe aggregate sum", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("0".to_string(), vec![UntaggedValue::int(16).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let quantile: Option> = args.get_flag("quantile")?; - let operation: Tagged = args.req(0)?; - let op = Operation::from_tagged(&operation, quantile)?; - - let value = args.input.next().ok_or_else(|| { - ShellError::labeled_error("Empty stream", "No value found in the stream", &tag) - })?; - - match value.value { - UntaggedValue::FrameStruct(FrameStruct::GroupBy(nu_groupby)) => { - let groupby = nu_groupby.to_groupby()?; - - let res = perform_groupby_aggregation( - groupby, - op, - &operation.tag, - &tag.span, - args.has_flag("explicit"), - )?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) - } - UntaggedValue::DataFrame(df) => { - let df = df.as_ref(); - - let res = perform_dataframe_aggregation(df, op, &operation.tag)?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) - } - _ => Err(ShellError::labeled_error( - "No groupby, dataframe or series in stream", - "no groupby, dataframe or series found in input stream", - &value.tag.span, - )), - } -} - -fn perform_groupby_aggregation( - groupby: GroupBy, - operation: Operation, - operation_tag: &Tag, - agg_span: &Span, - explicit: bool, -) -> Result { - let mut res = match operation { - Operation::Mean => groupby.mean(), - Operation::Sum => groupby.sum(), - Operation::Min => groupby.min(), - Operation::Max => groupby.max(), - Operation::First => groupby.first(), - Operation::Last => groupby.last(), - Operation::Nunique => groupby.n_unique(), - Operation::Quantile(quantile) => groupby.quantile(quantile), - Operation::Median => groupby.median(), - Operation::Var => groupby.var(), - Operation::Std => groupby.std(), - Operation::Count => groupby.count(), - } - .map_err(|e| { - let span = match &e { - PolarsError::NotFound(_) => agg_span, - _ => &operation_tag.span, - }; - - parse_polars_error::<&str>(&e, span, None) - })?; - - if !explicit { - let col_names = res - .get_column_names() - .iter() - .map(|name| name.to_string()) - .collect::>(); - - for col in col_names { - let from = match operation { - Operation::Mean => "_mean", - Operation::Sum => "_sum", - Operation::Min => "_min", - Operation::Max => "_max", - Operation::First => "_first", - Operation::Last => "_last", - Operation::Nunique => "_n_unique", - Operation::Quantile(_) => "_quantile", - Operation::Median => "_median", - Operation::Var => "_agg_var", - Operation::Std => "_agg_std", - Operation::Count => "_count", - }; - - let new_col = match col.find(from) { - Some(index) => &col[..index], - None => &col[..], - }; - - res.rename(&col, new_col) - .expect("Column is always there. Looping with known names"); - } - } - - Ok(res) -} - -fn perform_dataframe_aggregation( - dataframe: &polars::prelude::DataFrame, - operation: Operation, - operation_tag: &Tag, -) -> Result { - match operation { - Operation::Mean => Ok(dataframe.mean()), - Operation::Sum => Ok(dataframe.sum()), - Operation::Min => Ok(dataframe.min()), - Operation::Max => Ok(dataframe.max()), - Operation::Quantile(quantile) => dataframe - .quantile(quantile) - .map_err(|e| parse_polars_error::<&str>(&e, &operation_tag.span, None)), - Operation::Median => Ok(dataframe.median()), - Operation::Var => Ok(dataframe.var()), - Operation::Std => Ok(dataframe.std()), - _ => Err(ShellError::labeled_error_with_secondary( - "Not valid operation", - "operation not valid for dataframe", - &operation_tag.span, - "Perhaps you want: mean, sum, min, max, quantile, median, var, or std", - &operation_tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/append.rs b/old_nushell/crates/nu-command/src/commands/dataframe/append.rs deleted file mode 100644 index 503daac65..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/append.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Axis, Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tagged; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe append" - } - - fn usage(&self) -> &str { - "[DataFrame] Appends a new dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe append") - .required_named( - "other", - SyntaxShape::Any, - "dataframe to be appended", - Some('o'), - ) - .required_named( - "axis", - SyntaxShape::String, - "row or col axis orientation", - Some('a'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Appends a dataframe as new columns", - example: r#"let a = ([[a b]; [1 2] [3 4]] | dataframe to-df); - $a | dataframe append -o $a -a row"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - ), - Column::new( - "b".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()], - ), - Column::new( - "a_x".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - ), - Column::new( - "b_x".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Appends a dataframe merging at the end of columns", - example: r#"let a = ([[a b]; [1 2] [3 4]] | dataframe to-df); - $a | dataframe append -o $a -a col"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - ], - ), - Column::new( - "b".to_string(), - vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(4).into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let other: Value = args.req_named("other")?; - let axis: Tagged = args.req_named("axis")?; - - let axis = Axis::try_from_str(&axis.item, &axis.tag.span)?; - - let df_other = match other.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only append a dataframe to a dataframe", - other.tag.span, - )), - }?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let df_new = df.append_df(&df_other, axis, &tag.span)?; - Ok(OutputStream::one(df_new.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/column.rs b/old_nushell/crates/nu-command/src/commands/dataframe/column.rs deleted file mode 100644 index e0b566818..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/column.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; - -use nu_source::Tagged; - -use super::utils::parse_polars_error; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe column" - } - - fn usage(&self) -> &str { - "[DataFrame] Returns the selected column as Series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe column").required("column", SyntaxShape::String, "column name") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns the selected column as series", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe column a", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let column: Tagged = args.req(0)?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df - .as_ref() - .column(&column.item) - .map_err(|e| parse_polars_error::<&str>(&e, &column.tag.span, None))?; - - let df = NuDataFrame::try_from_series(vec![res.clone()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/command.rs b/old_nushell/crates/nu-command/src/commands/dataframe/command.rs deleted file mode 100644 index 09ea55aba..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/command.rs +++ /dev/null @@ -1,26 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "dataframe" - } - - fn usage(&self) -> &str { - "Commands to work with polars dataframes" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe") - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&Command, args.scope())).into_value(Tag::unknown()), - )) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/describe.rs b/old_nushell/crates/nu-command/src/commands/dataframe/describe.rs deleted file mode 100644 index 6cd06bfbc..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/describe.rs +++ /dev/null @@ -1,232 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::{ - chunked_array::ChunkedArray, - prelude::{ - AnyValue, DataFrame as PolarsDF, DataType, Float64Type, IntoSeries, NewChunkedArray, - Series, Utf8Type, - }, -}; - -use super::utils::parse_polars_error; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe describe" - } - - fn usage(&self) -> &str { - "[DataFrame] Describes dataframes numeric columns" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe describe") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Describes dataframe", - example: "[[a b]; [1 1] [1 1]] | dataframe to-df | dataframe describe", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "descriptor".to_string(), - vec![ - UntaggedValue::string("count").into(), - UntaggedValue::string("sum").into(), - UntaggedValue::string("mean").into(), - UntaggedValue::string("median").into(), - UntaggedValue::string("std").into(), - UntaggedValue::string("min").into(), - UntaggedValue::string("25%").into(), - UntaggedValue::string("50%").into(), - UntaggedValue::string("75%").into(), - UntaggedValue::string("max").into(), - ], - ), - Column::new( - "a (i64)".to_string(), - vec![ - UntaggedValue::decimal_from_float(2.0, Span::default()).into(), - UntaggedValue::decimal_from_float(2.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(0.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - ], - ), - Column::new( - "b (i64)".to_string(), - vec![ - UntaggedValue::decimal_from_float(2.0, Span::default()).into(), - UntaggedValue::decimal_from_float(2.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(0.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - UntaggedValue::decimal_from_float(1.0, Span::default()).into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let names = ChunkedArray::::new_from_opt_slice( - "descriptor", - &[ - Some("count"), - Some("sum"), - Some("mean"), - Some("median"), - Some("std"), - Some("min"), - Some("25%"), - Some("50%"), - Some("75%"), - Some("max"), - ], - ) - .into_series(); - - let head = std::iter::once(names); - - let tail = df.as_ref().get_columns().iter().map(|col| { - let count = col.len() as f64; - - let sum = match col.sum_as_series().cast(&DataType::Float64) { - Ok(ca) => match ca.get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }, - Err(_) => None, - }; - - let mean = match col.mean_as_series().get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }; - - let median = match col.median_as_series().get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }; - - let std = match col.std_as_series().get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }; - - let min = match col.min_as_series().cast(&DataType::Float64) { - Ok(ca) => match ca.get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }, - Err(_) => None, - }; - - let q_25 = match col.quantile_as_series(0.25) { - Ok(ca) => match ca.cast(&DataType::Float64) { - Ok(ca) => match ca.get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }, - Err(_) => None, - }, - Err(_) => None, - }; - - let q_50 = match col.quantile_as_series(0.50) { - Ok(ca) => match ca.cast(&DataType::Float64) { - Ok(ca) => match ca.get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }, - Err(_) => None, - }, - Err(_) => None, - }; - - let q_75 = match col.quantile_as_series(0.75) { - Ok(ca) => match ca.cast(&DataType::Float64) { - Ok(ca) => match ca.get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }, - Err(_) => None, - }, - Err(_) => None, - }; - - let max = match col.max_as_series().cast(&DataType::Float64) { - Ok(ca) => match ca.get(0) { - AnyValue::Float64(v) => Some(v), - _ => None, - }, - Err(_) => None, - }; - - let name = format!("{} ({})", col.name(), col.dtype()); - ChunkedArray::::new_from_opt_slice( - &name, - &[ - Some(count), - sum, - mean, - median, - std, - min, - q_25, - q_50, - q_75, - max, - ], - ) - .into_series() - }); - - let res = head.chain(tail).collect::>(); - let df = PolarsDF::new(res).map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - let df = NuDataFrame::dataframe_to_value(df, tag); - Ok(OutputStream::one(df)) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/drop.rs b/old_nushell/crates/nu-command/src/commands/dataframe/drop.rs deleted file mode 100644 index eef03a3ff..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/drop.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::{convert_columns, parse_polars_error}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe drop" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates a new dataframe by dropping the selected columns" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe drop").rest( - "rest", - SyntaxShape::Any, - "column names to be dropped", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "drop column a", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe drop a", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "b".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let columns: Vec = args.rest(0)?; - let (col_string, col_span) = convert_columns(&columns, &tag)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let new_df = match col_string.get(0) { - Some(col) => df - .as_ref() - .drop(col) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None)), - None => Err(ShellError::labeled_error( - "Empty names list", - "No column names where found", - &col_span, - )), - }?; - - // If there are more columns in the drop selection list, these - // are added from the resulting dataframe - let res = col_string.iter().skip(1).try_fold(new_df, |new_df, col| { - new_df - .drop(col) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None)) - })?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/drop_duplicates.rs b/old_nushell/crates/nu-command/src/commands/dataframe/drop_duplicates.rs deleted file mode 100644 index 31420c3bc..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/drop_duplicates.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::{convert_columns, parse_polars_error}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe drop-duplicates" - } - - fn usage(&self) -> &str { - "[DataFrame] Drops duplicate values in dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe drop-duplicates") - .optional( - "subset", - SyntaxShape::Table, - "subset of columns to drop duplicates", - ) - .switch("maintain", "maintain order", Some('m')) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "drop duplicates", - example: "[[a b]; [1 2] [3 4] [1 2]] | dataframe to-df | dataframe drop-duplicates", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - ), - Column::new( - "b".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - // Extracting the selection columns of the columns to perform the aggregation - let columns: Option> = args.opt(0)?; - let (subset, col_span) = match columns { - Some(cols) => { - let (agg_string, col_span) = convert_columns(&cols, &tag)?; - (Some(agg_string), col_span) - } - None => (None, Span::unknown()), - }; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let subset_slice = subset.as_ref().map(|cols| &cols[..]); - - let res = df - .as_ref() - .drop_duplicates(args.has_flag("maintain"), subset_slice) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/drop_nulls.rs b/old_nushell/crates/nu-command/src/commands/dataframe/drop_nulls.rs deleted file mode 100644 index f974d914a..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/drop_nulls.rs +++ /dev/null @@ -1,132 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::{convert_columns, parse_polars_error}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe drop-nulls" - } - - fn usage(&self) -> &str { - "[DataFrame, Series] Drops null values in dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe drop-nulls").optional( - "subset", - SyntaxShape::Table, - "subset of columns to drop duplicates", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "drop null values in dataframe", - example: r#"let df = ([[a b]; [1 2] [3 0] [1 2]] | dataframe to-df); - let res = ($df.b / $df.b); - let df = ($df | dataframe with-column $res --name res); - $df | dataframe drop-nulls"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(1).into()], - ), - Column::new( - "b".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(2).into()], - ), - Column::new( - "res".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(1).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "drop null values in dataframe", - example: r#"let s = ([1 2 0 0 3 4] | dataframe to-df); - ($s / $s) | dataframe drop-nulls"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "div_0_0".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let value = args.input.next().ok_or_else(|| { - ShellError::labeled_error("Empty stream", "No value found in stream", &tag.span) - })?; - - match value.value { - UntaggedValue::DataFrame(df) => { - // Extracting the selection columns of the columns to perform the aggregation - let columns: Option> = args.opt(0)?; - let (subset, col_span) = match columns { - Some(cols) => { - let (agg_string, col_span) = convert_columns(&cols, &tag)?; - (Some(agg_string), col_span) - } - None => (None, Span::unknown()), - }; - - let subset_slice = subset.as_ref().map(|cols| &cols[..]); - - let res = df - .as_ref() - .drop_nulls(subset_slice) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) - } - _ => Err(ShellError::labeled_error( - "Incorrect type", - "drop nulls cannot be done with this value", - &value.tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/dtypes.rs b/old_nushell/crates/nu-command/src/commands/dataframe/dtypes.rs deleted file mode 100644 index ac997ef55..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/dtypes.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, Value, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe dtypes" - } - - fn usage(&self) -> &str { - "[DataFrame] Show dataframe data types" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe dtypes") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "drop column a", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe dtypes", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "column".to_string(), - vec![ - UntaggedValue::string("a").into(), - UntaggedValue::string("b").into(), - ], - ), - Column::new( - "dtype".to_string(), - vec![ - UntaggedValue::string("i64").into(), - UntaggedValue::string("i64").into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -#[allow(clippy::needless_collect)] -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut dtypes: Vec = Vec::new(); - let names: Vec = df - .as_ref() - .get_column_names() - .iter() - .map(|v| { - let dtype = df - .as_ref() - .column(v) - .expect("using name from list of names from dataframe") - .dtype(); - - let dtype_str = dtype.to_string(); - dtypes.push(Value { - value: dtype_str.into(), - tag: Tag::default(), - }); - - Value { - value: v.to_string().into(), - tag: Tag::default(), - } - }) - .collect(); - - let names_col = Column::new("column".to_string(), names); - let dtypes_col = Column::new("dtype".to_string(), dtypes); - - let df = NuDataFrame::try_from_columns(vec![names_col, dtypes_col], &tag.span)?; - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/dummies.rs b/old_nushell/crates/nu-command/src/commands/dataframe/dummies.rs deleted file mode 100644 index cd977712e..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/dummies.rs +++ /dev/null @@ -1,142 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use super::utils::parse_polars_error; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe to-dummies" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates a new dataframe with dummy variables" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe to-dummies") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Create new dataframe with dummy variables from a dataframe", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe to-dummies", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a_1".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(0).into()], - ), - Column::new( - "a_3".to_string(), - vec![UntaggedValue::int(0).into(), UntaggedValue::int(1).into()], - ), - Column::new( - "b_2".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(0).into()], - ), - Column::new( - "b_4".to_string(), - vec![UntaggedValue::int(0).into(), UntaggedValue::int(1).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Create new dataframe with dummy variables from a series", - example: "[1 2 2 3 3] | dataframe to-df | dataframe to-dummies", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "0_1".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(0).into(), - UntaggedValue::int(0).into(), - UntaggedValue::int(0).into(), - UntaggedValue::int(0).into(), - ], - ), - Column::new( - "0_2".to_string(), - vec![ - UntaggedValue::int(0).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(0).into(), - UntaggedValue::int(0).into(), - ], - ), - Column::new( - "0_3".to_string(), - vec![ - UntaggedValue::int(0).into(), - UntaggedValue::int(0).into(), - UntaggedValue::int(0).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let value = args.input.next().ok_or_else(|| { - ShellError::labeled_error("Empty stream", "No value found in stream", &tag.span) - })?; - - match value.value { - UntaggedValue::DataFrame(df) => { - let res = df.as_ref().to_dummies().map_err(|e| { - parse_polars_error( - &e, - &tag.span, - Some("The only allowed column types for dummies are String or Int"), - ) - })?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) - } - _ => Err(ShellError::labeled_error( - "Incorrect type", - "dummies cannot be done with this value", - &value.tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/filter.rs b/old_nushell/crates/nu-command/src/commands/dataframe/filter.rs deleted file mode 100644 index 26a485028..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/filter.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::parse_polars_error; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe filter-with" - } - - fn usage(&self) -> &str { - "[DataFrame] Filters dataframe using a mask as reference" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe filter-with").required( - "mask", - SyntaxShape::Any, - "boolean mask used to filter data", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Filter dataframe using a bool mask", - example: r#"let mask = ([$true $false] | dataframe to-df); - [[a b]; [1 2] [3 4]] | dataframe to-df | dataframe filter-with $mask"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![UntaggedValue::int(1).into()]), - Column::new("b".to_string(), vec![UntaggedValue::int(2).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Filter dataframe by creating a mask from operation", - example: r#"let mask = (([5 6] | dataframe to-df) > 5); - [[a b]; [1 2] [3 4]] | dataframe to-df | dataframe filter-with $mask"#, - result: None, - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let value: Value = args.req(0)?; - - let series_span = value.tag.span; - let df = match value.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only add a series to a dataframe", - value.tag.span, - )), - }?; - let series = df.as_series(&series_span)?; - let casted = series.bool().map_err(|e| { - parse_polars_error( - &e, - &series_span, - Some("Perhaps you want to use a series with booleans as mask"), - ) - })?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df - .as_ref() - .filter(casted) - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/first.rs b/old_nushell/crates/nu-command/src/commands/dataframe/first.rs deleted file mode 100644 index 0c23f4d59..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/first.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; - -use nu_source::Tagged; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe first" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates new dataframe with first rows" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe select").optional( - "rows", - SyntaxShape::Number, - "Number of rows for head", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create new dataframe with head rows", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe first 1", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![UntaggedValue::int(1).into()]), - Column::new("b".to_string(), vec![UntaggedValue::int(2).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let rows: Option> = args.opt(0)?; - - let rows = match rows { - Some(val) => val.item, - None => 5, - }; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let res = df.as_ref().head(Some(rows)); - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/get.rs b/old_nushell/crates/nu-command/src/commands/dataframe/get.rs deleted file mode 100644 index ebb8e6b85..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/get.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::{convert_columns, parse_polars_error}; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates dataframe with the selected columns" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get").rest( - "rest", - SyntaxShape::Any, - "column names to sort dataframe", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Creates dataframe with selected columns", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe get a", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let columns: Vec = args.rest(0)?; - - let (col_string, col_span) = convert_columns(&columns, &tag)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df - .as_ref() - .select(&col_string) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/groupby.rs b/old_nushell/crates/nu-command/src/commands/dataframe/groupby.rs deleted file mode 100644 index 3236f6d1c..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/groupby.rs +++ /dev/null @@ -1,68 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{FrameStruct, NuDataFrame, NuGroupBy}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::convert_columns; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe group-by" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates a groupby object that can be used for other aggregations" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe group-by").rest("rest", SyntaxShape::Any, "groupby columns") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Grouping by column a", - example: "[[a b]; [one 1] [one 2]] | dataframe to-df | dataframe group-by a", - result: None, - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - // Extracting the names of the columns to perform the groupby - let by_columns: Vec = args.rest(0)?; - let (columns_string, col_span) = convert_columns(&by_columns, &tag)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - // This is the expensive part of the groupby; to create the - // groups that will be used for grouping the data in the - // dataframe. Once it has been done these values can be stored - // in a NuGroupBy - let groupby = df - .as_ref() - .groupby(&columns_string) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None))?; - - let groups = groupby.get_groups().to_vec(); - let groupby = Value { - tag, - value: UntaggedValue::FrameStruct(FrameStruct::GroupBy(NuGroupBy::new( - NuDataFrame::new(df.as_ref().clone()), - columns_string, - groups, - ))), - }; - - Ok(OutputStream::one(groupby)) -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/join.rs b/old_nushell/crates/nu-command/src/commands/dataframe/join.rs deleted file mode 100644 index da18eb8bf..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/join.rs +++ /dev/null @@ -1,233 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::{convert_columns, parse_polars_error}; - -use polars::prelude::JoinType; - -use nu_source::Tagged; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe join" - } - - fn usage(&self) -> &str { - "[DataFrame] Joins a dataframe using columns as reference" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe join") - .required("dataframe", SyntaxShape::Any, "right dataframe to join") - .required_named( - "left", - SyntaxShape::Table, - "left column names to perform join", - Some('l'), - ) - .required_named( - "right", - SyntaxShape::Table, - "right column names to perform join", - Some('r'), - ) - .named( - "type", - SyntaxShape::String, - "type of join. Inner by default", - Some('t'), - ) - .named( - "suffix", - SyntaxShape::String, - "suffix for the columns of the right dataframe", - Some('s'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "inner join dataframe", - example: r#"let right = ([[a b c]; [1 2 5] [3 4 5] [5 6 6]] | dataframe to-df); - $right | dataframe join $right -l [a b] -r [a b]"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(5).into(), - ], - ), - Column::new( - "b".to_string(), - vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(6).into(), - ], - ), - Column::new( - "c".to_string(), - vec![ - UntaggedValue::int(5).into(), - UntaggedValue::int(5).into(), - UntaggedValue::int(6).into(), - ], - ), - Column::new( - "c_right".to_string(), - vec![ - UntaggedValue::int(5).into(), - UntaggedValue::int(5).into(), - UntaggedValue::int(6).into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let r_df: Value = args.req(0)?; - let l_col: Vec = args.req_named("left")?; - let r_col: Vec = args.req_named("right")?; - let r_suffix: Option> = args.get_flag("suffix")?; - let join_type_op: Option> = args.get_flag("type")?; - - let join_type = match join_type_op { - None => JoinType::Inner, - Some(val) => match val.item.as_ref() { - "inner" => JoinType::Inner, - "outer" => JoinType::Outer, - "left" => JoinType::Left, - _ => { - return Err(ShellError::labeled_error_with_secondary( - "Incorrect join type", - "Invalid join type", - &val.tag, - "Perhaps you mean: inner, outer or left", - &val.tag, - )) - } - }, - }; - - let suffix = r_suffix.map(|s| s.item); - - let (l_col_string, l_col_span) = convert_columns(&l_col, &tag)?; - let (r_col_string, r_col_span) = convert_columns(&r_col, &tag)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = match r_df.value { - UntaggedValue::DataFrame(r_df) => { - // Checking the column types before performing the join - check_column_datatypes( - df.as_ref(), - r_df.as_ref(), - &l_col_string, - &l_col_span, - &r_col_string, - &r_col_span, - )?; - - df.as_ref() - .join( - r_df.as_ref(), - &l_col_string, - &r_col_string, - join_type, - suffix, - ) - .map_err(|e| parse_polars_error::<&str>(&e, &l_col_span, None)) - } - _ => Err(ShellError::labeled_error( - "Not a dataframe", - "not a dataframe type value", - &r_df.tag, - )), - }?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -fn check_column_datatypes>( - df_l: &polars::prelude::DataFrame, - df_r: &polars::prelude::DataFrame, - l_cols: &[T], - l_col_span: &Span, - r_cols: &[T], - r_col_span: &Span, -) -> Result<(), ShellError> { - if l_cols.len() != r_cols.len() { - return Err(ShellError::labeled_error_with_secondary( - "Mismatched number of column names", - format!( - "found {} left names vs {} right names", - l_cols.len(), - r_cols.len() - ), - l_col_span, - "perhaps you need to change the number of columns to join", - r_col_span, - )); - } - - for (l, r) in l_cols.iter().zip(r_cols) { - let l_series = df_l - .column(l.as_ref()) - .map_err(|e| parse_polars_error::<&str>(&e, l_col_span, None))?; - - let r_series = df_r - .column(r.as_ref()) - .map_err(|e| parse_polars_error::<&str>(&e, r_col_span, None))?; - - if l_series.dtype() != r_series.dtype() { - return Err(ShellError::labeled_error_with_secondary( - "Mismatched datatypes", - format!( - "left column type '{}' doesn't match '{}' right column match", - l_series.dtype(), - r_series.dtype() - ), - l_col_span, - "perhaps you need to select other column to match", - r_col_span, - )); - } - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/last.rs b/old_nushell/crates/nu-command/src/commands/dataframe/last.rs deleted file mode 100644 index 1838570ca..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/last.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; - -use nu_source::Tagged; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe last" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates new dataframe with tail rows" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe last").optional( - "n_rows", - SyntaxShape::Number, - "Number of rows for tail", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create new dataframe with last rows", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe last 1", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![UntaggedValue::int(3).into()]), - Column::new("b".to_string(), vec![UntaggedValue::int(4).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let rows: Option> = args.opt(0)?; - - let rows = match rows { - Some(val) => val.item, - None => 5, - }; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df.as_ref().tail(Some(rows)); - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/list.rs b/old_nushell/crates/nu-command/src/commands/dataframe/list.rs deleted file mode 100644 index 56e78ce8b..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/list.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, Value, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe list" - } - - fn usage(&self) -> &str { - "Lists stored dataframes" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe list") - } - - fn run(&self, args: CommandArgs) -> Result { - let data = args - .context - .scope - .get_vars() - .into_iter() - .filter_map(|(name, value)| { - if let UntaggedValue::DataFrame(df) = &value.value { - let rows = Value { - value: (df.as_ref().height() as i64).into(), - tag: Tag::default(), - }; - - let cols = Value { - value: (df.as_ref().width() as i64).into(), - tag: Tag::default(), - }; - - let location = match value.tag.anchor { - Some(AnchorLocation::File(name)) => name, - Some(AnchorLocation::Url(name)) => name, - Some(AnchorLocation::Source(text)) => text.slice(0..text.end).text, - None => "stream".to_string(), - }; - - let location = Value { - value: location.into(), - tag: Tag::default(), - }; - - let name = Value { - value: name.into(), - tag: Tag::default(), - }; - - Some((name, rows, cols, location)) - } else { - None - } - }); - - let mut name = Column::new_empty("name".to_string()); - let mut rows = Column::new_empty("rows".to_string()); - let mut cols = Column::new_empty("columns".to_string()); - let mut location = Column::new_empty("location".to_string()); - - for tuple in data { - name.push(tuple.0); - rows.push(tuple.1); - cols.push(tuple.2); - location.push(tuple.3); - } - - let tag = args.call_info.name_tag; - let df = NuDataFrame::try_from_columns(vec![name, rows, cols, location], &tag.span)?; - Ok(OutputStream::one(df.into_value(tag))) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Lists loaded dataframes in current scope", - example: "let a = ([[a b];[1 2] [3 4]] | dataframe to-df); dataframe list", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("name".to_string(), vec![UntaggedValue::string("$a").into()]), - Column::new("rows".to_string(), vec![UntaggedValue::int(2).into()]), - Column::new("columns".to_string(), vec![UntaggedValue::int(2).into()]), - Column::new( - "location".to_string(), - vec![UntaggedValue::string("stream").into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/melt.rs b/old_nushell/crates/nu-command/src/commands/dataframe/melt.rs deleted file mode 100644 index 702571920..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/melt.rs +++ /dev/null @@ -1,204 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tagged; - -use super::utils::convert_columns; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe melt" - } - - fn usage(&self) -> &str { - "[DataFrame] Unpivot a DataFrame from wide to long format" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe melt") - .required_named( - "columns", - SyntaxShape::Table, - "column names for melting", - Some('c'), - ) - .required_named( - "values", - SyntaxShape::Table, - "column names used as value columns", - Some('v'), - ) - .named( - "variable_name", - SyntaxShape::String, - "optional name for variable column", - Some('r'), - ) - .named( - "value_name", - SyntaxShape::String, - "optional name for value column", - Some('l'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "melt dataframe", - example: - "[[a b c d]; [x 1 4 a] [y 2 5 b] [z 3 6 c]] | dataframe to-df | dataframe melt -c [b c] -v [a d]", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "b".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - ], - ), - Column::new( - "c".to_string(), - vec![ - UntaggedValue::int(4).into(), - UntaggedValue::int(5).into(), - UntaggedValue::int(6).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(5).into(), - UntaggedValue::int(6).into(), - ], - ), - Column::new( - "variable".to_string(), - vec![ - UntaggedValue::string("a").into(), - UntaggedValue::string("a").into(), - UntaggedValue::string("a").into(), - UntaggedValue::string("d").into(), - UntaggedValue::string("d").into(), - UntaggedValue::string("d").into(), - ], - ), - Column::new( - "value".to_string(), - vec![ - UntaggedValue::string("x").into(), - UntaggedValue::string("y").into(), - UntaggedValue::string("z").into(), - UntaggedValue::string("a").into(), - UntaggedValue::string("b").into(), - UntaggedValue::string("c").into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let id_col: Vec = args.req_named("columns")?; - let val_col: Vec = args.req_named("values")?; - - let value_name: Option> = args.get_flag("value_name")?; - let variable_name: Option> = args.get_flag("variable_name")?; - - let (id_col_string, id_col_span) = convert_columns(&id_col, &tag)?; - let (val_col_string, val_col_span) = convert_columns(&val_col, &tag)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - check_column_datatypes(df.as_ref(), &id_col_string, &id_col_span)?; - check_column_datatypes(df.as_ref(), &val_col_string, &val_col_span)?; - - let mut res = df - .as_ref() - .melt(&id_col_string, &val_col_string) - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - if let Some(name) = &variable_name { - res.rename("variable", &name.item) - .map_err(|e| parse_polars_error::<&str>(&e, &name.tag.span, None))?; - } - - if let Some(name) = &value_name { - res.rename("value", &name.item) - .map_err(|e| parse_polars_error::<&str>(&e, &name.tag.span, None))?; - } - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -fn check_column_datatypes>( - df: &polars::prelude::DataFrame, - cols: &[T], - col_span: &Span, -) -> Result<(), ShellError> { - if cols.is_empty() { - return Err(ShellError::labeled_error( - "Merge error", - "empty column list", - col_span, - )); - } - - // Checking if they are same type - if cols.len() > 1 { - for w in cols.windows(2) { - let l_series = df - .column(w[0].as_ref()) - .map_err(|e| parse_polars_error::<&str>(&e, col_span, None))?; - - let r_series = df - .column(w[1].as_ref()) - .map_err(|e| parse_polars_error::<&str>(&e, col_span, None))?; - - if l_series.dtype() != r_series.dtype() { - return Err(ShellError::labeled_error_with_secondary( - "Merge error", - "found different column types in list", - col_span, - format!( - "datatypes {} and {} are incompatible", - l_series.dtype(), - r_series.dtype() - ), - col_span, - )); - } - } - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/mod.rs b/old_nushell/crates/nu-command/src/commands/dataframe/mod.rs deleted file mode 100644 index 4df4a935f..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/mod.rs +++ /dev/null @@ -1,112 +0,0 @@ -pub mod aggregate; -pub mod append; -pub mod column; -pub mod command; -pub mod describe; -pub mod drop; -pub mod drop_duplicates; -pub mod drop_nulls; -pub mod dtypes; -pub mod dummies; -pub mod filter; -pub mod first; -pub mod get; -pub mod groupby; -pub mod join; -pub mod last; -pub mod list; -pub mod melt; -pub mod open; -pub mod pivot; -pub mod rename; -pub mod sample; -pub mod select; -pub mod shape; -pub mod show; -pub mod slice; -pub mod sort; -pub mod take; -pub mod to_csv; -pub mod to_df; -pub mod to_parquet; -pub(crate) mod utils; -pub mod where_; -pub mod with_column; - -pub use aggregate::DataFrame as DataFrameAggregate; -pub use append::DataFrame as DataFrameAppend; -pub use column::DataFrame as DataFrameColumn; -pub use command::Command as DataFrame; -pub use describe::DataFrame as DataFrameDescribe; -pub use drop::DataFrame as DataFrameDrop; -pub use drop_duplicates::DataFrame as DataFrameDropDuplicates; -pub use drop_nulls::DataFrame as DataFrameDropNulls; -pub use dtypes::DataFrame as DataFrameDTypes; -pub use dummies::DataFrame as DataFrameDummies; -pub use filter::DataFrame as DataFrameFilter; -pub use first::DataFrame as DataFrameFirst; -pub use get::DataFrame as DataFrameGet; -pub use groupby::DataFrame as DataFrameGroupBy; -pub use join::DataFrame as DataFrameJoin; -pub use last::DataFrame as DataFrameLast; -pub use list::DataFrame as DataFrameList; -pub use melt::DataFrame as DataFrameMelt; -pub use open::DataFrame as DataFrameOpen; -pub use pivot::DataFrame as DataFramePivot; -pub use rename::DataFrame as DataFrameRename; -pub use sample::DataFrame as DataFrameSample; -pub use select::DataFrame as DataFrameSelect; -pub use shape::DataFrame as DataFrameShape; -pub use show::DataFrame as DataFrameShow; -pub use slice::DataFrame as DataFrameSlice; -pub use sort::DataFrame as DataFrameSort; -pub use take::DataFrame as DataFrameTake; -pub use to_csv::DataFrame as DataFrameToCsv; -pub use to_df::DataFrame as DataFrameToDF; -pub use to_parquet::DataFrame as DataFrameToParquet; -pub use where_::DataFrame as DataFrameWhere; -pub use with_column::DataFrame as DataFrameWithColumn; - -pub mod series; -pub use series::DataFrameAllFalse; -pub use series::DataFrameAllTrue; -pub use series::DataFrameArgMax; -pub use series::DataFrameArgMin; -pub use series::DataFrameArgSort; -pub use series::DataFrameArgTrue; -pub use series::DataFrameArgUnique; -pub use series::DataFrameConcatenate; -pub use series::DataFrameContains; -pub use series::DataFrameCumulative; -pub use series::DataFrameGetDay; -pub use series::DataFrameGetHour; -pub use series::DataFrameGetMinute; -pub use series::DataFrameGetMonth; -pub use series::DataFrameGetNanoSecond; -pub use series::DataFrameGetOrdinal; -pub use series::DataFrameGetSecond; -pub use series::DataFrameGetWeek; -pub use series::DataFrameGetWeekDay; -pub use series::DataFrameGetYear; -pub use series::DataFrameIsDuplicated; -pub use series::DataFrameIsIn; -pub use series::DataFrameIsNotNull; -pub use series::DataFrameIsNull; -pub use series::DataFrameIsUnique; -pub use series::DataFrameNNull; -pub use series::DataFrameNUnique; -pub use series::DataFrameNot; -pub use series::DataFrameReplace; -pub use series::DataFrameReplaceAll; -pub use series::DataFrameRolling; -pub use series::DataFrameSeriesRename; -pub use series::DataFrameSet; -pub use series::DataFrameSetWithIdx; -pub use series::DataFrameShift; -pub use series::DataFrameStrFTime; -pub use series::DataFrameStringLengths; -pub use series::DataFrameStringSlice; -pub use series::DataFrameToLowercase; -pub use series::DataFrameToUppercase; -pub use series::DataFrameUnique; -pub use series::DataFrameValueCounts; diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/open.rs b/old_nushell/crates/nu-command/src/commands/dataframe/open.rs deleted file mode 100644 index 72ce158d0..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/open.rs +++ /dev/null @@ -1,211 +0,0 @@ -use std::path::PathBuf; - -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::NuDataFrame, Primitive, Signature, SyntaxShape, UntaggedValue, Value, -}; - -use nu_source::Tagged; -use polars::prelude::{CsvEncoding, CsvReader, JsonReader, ParquetReader, SerReader}; -use std::fs::File; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe open" - } - - fn usage(&self) -> &str { - "Opens csv, json or parquet file to create dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe open") - .required( - "file", - SyntaxShape::FilePath, - "file path to load values from", - ) - .named( - "delimiter", - SyntaxShape::String, - "file delimiter character. CSV file", - Some('d'), - ) - .switch( - "no_header", - "Indicates if file doesn't have header. CSV file", - None, - ) - .named( - "infer_schema", - SyntaxShape::Number, - "Set number of rows to infer the schema of the file. CSV file", - None, - ) - .named( - "skip_rows", - SyntaxShape::Number, - "Number of rows to skip from file. CSV file", - None, - ) - .named( - "columns", - SyntaxShape::Table, - "Columns to be selected from csv file. CSV file", - None, - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Takes a file name and creates a dataframe", - example: "dataframe open test.csv", - result: None, - }] - } -} - -fn command(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let file: Tagged = args.req(0)?; - - let df = match file.item().extension() { - Some(e) => match e.to_str() { - Some("csv") => from_csv(args), - Some("parquet") => from_parquet(args), - Some("json") => from_json(args), - _ => Err(ShellError::labeled_error( - "Error with file", - "Not a csv, parquet or json file", - &file.tag, - )), - }, - None => Err(ShellError::labeled_error( - "Error with file", - "File without extension", - &file.tag, - )), - }?; - - let file_name = match file.item.into_os_string().into_string() { - Ok(name) => name, - Err(e) => { - return Err(ShellError::labeled_error( - "File Name Error", - format!("{:?}", e), - &file.tag, - )) - } - }; - - let df_tag = Tag { - anchor: Some(AnchorLocation::File(file_name)), - span: tag.span, - }; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value( - df, df_tag, - ))) -} - -fn from_parquet(args: CommandArgs) -> Result { - let file: Tagged = args.req(0)?; - - let r = File::open(&file.item) - .map_err(|e| ShellError::labeled_error("Error with file", format!("{:?}", e), &file.tag))?; - - let reader = ParquetReader::new(r); - - reader - .finish() - .map_err(|e| parse_polars_error::<&str>(&e, &file.tag.span, None)) -} - -fn from_json(args: CommandArgs) -> Result { - let file: Tagged = args.req(0)?; - - let r = File::open(&file.item) - .map_err(|e| ShellError::labeled_error("Error with file", format!("{:?}", e), &file.tag))?; - - let reader = JsonReader::new(r); - - reader - .finish() - .map_err(|e| parse_polars_error::<&str>(&e, &file.tag.span, None)) -} - -fn from_csv(args: CommandArgs) -> Result { - let file: Tagged = args.req(0)?; - let delimiter: Option> = args.get_flag("delimiter")?; - let no_header: bool = args.has_flag("no_header"); - let infer_schema: Option> = args.get_flag("infer_schema")?; - let skip_rows: Option> = args.get_flag("skip_rows")?; - let columns: Option> = args.get_flag("columns")?; - - let csv_reader = CsvReader::from_path(&file.item) - .map_err(|e| parse_polars_error::<&str>(&e, &file.tag.span, None))? - .with_encoding(CsvEncoding::LossyUtf8); - - let csv_reader = match delimiter { - None => csv_reader, - Some(d) => { - if d.item.len() != 1 { - return Err(ShellError::labeled_error( - "Incorrect delimiter", - "Delimiter has to be one char", - &d.tag, - )); - } else { - let delimiter = match d.item.chars().next() { - Some(d) => d as u8, - None => unreachable!(), - }; - csv_reader.with_delimiter(delimiter) - } - } - }; - - let csv_reader = csv_reader.has_header(!no_header); - - let csv_reader = match infer_schema { - None => csv_reader, - Some(r) => csv_reader.infer_schema(Some(r.item)), - }; - - let csv_reader = match skip_rows { - None => csv_reader, - Some(r) => csv_reader.with_skip_rows(r.item), - }; - - let csv_reader = match columns { - None => csv_reader, - Some(c) => { - let columns = c - .into_iter() - .map(|value| match value.value { - UntaggedValue::Primitive(Primitive::String(s)) => Ok(s), - _ => Err(ShellError::labeled_error( - "Incorrect type for column", - "Only string as columns", - &value.tag, - )), - }) - .collect::, ShellError>>(); - - csv_reader.with_columns(Some(columns?)) - } - }; - - match csv_reader.finish() { - Ok(df) => Ok(df), - Err(e) => Err(parse_polars_error::<&str>(&e, &file.tag.span, None)), - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/pivot.rs b/old_nushell/crates/nu-command/src/commands/dataframe/pivot.rs deleted file mode 100644 index 22dfa2728..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/pivot.rs +++ /dev/null @@ -1,169 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{NuDataFrame, NuGroupBy}, - Signature, SyntaxShape, -}; -use nu_source::Tagged; - -use polars::prelude::DataType; - -enum Operation { - First, - Sum, - Min, - Max, - Mean, - Median, -} - -impl Operation { - fn from_tagged(name: &Tagged) -> Result { - match name.item.as_ref() { - "first" => Ok(Operation::First), - "sum" => Ok(Operation::Sum), - "min" => Ok(Operation::Min), - "max" => Ok(Operation::Max), - "mean" => Ok(Operation::Mean), - "median" => Ok(Operation::Median), - _ => Err(ShellError::labeled_error_with_secondary( - "Operation not fount", - "Operation does not exist for pivot", - &name.tag, - "Perhaps you want: first, sum, min, max, mean, median", - &name.tag, - )), - } - } -} - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe pivot" - } - - fn usage(&self) -> &str { - "[GroupBy] Performs a pivot operation on a groupby object" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe pivot") - .required( - "pivot column", - SyntaxShape::String, - "pivot column to perform pivot", - ) - .required( - "value column", - SyntaxShape::String, - "value column to perform pivot", - ) - .required("operation", SyntaxShape::String, "aggregate operation") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Pivot a dataframe on b and aggregation on col c", - example: - "[[a b c]; [one x 1] [two y 2]] | dataframe to-df | dataframe group-by a | dataframe pivot b c sum", - result: None, // No sample because there are nulls in the result dataframe - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - // Extracting the pivot col from arguments - let pivot_col: Tagged = args.req(0)?; - - // Extracting the value col from arguments - let value_col: Tagged = args.req(1)?; - - let operation: Tagged = args.req(2)?; - let op = Operation::from_tagged(&operation)?; - - // The operation is only done in one groupby. Only one input is - // expected from the InputStream - let nu_groupby = NuGroupBy::try_from_stream(&mut args.input, &tag.span)?; - let df_ref = nu_groupby.as_ref(); - - check_pivot_column(df_ref, &pivot_col)?; - check_value_column(df_ref, &value_col)?; - - let mut groupby = nu_groupby.to_groupby()?; - - let pivot = groupby.pivot(&pivot_col.item, &value_col.item); - - let res = match op { - Operation::Mean => pivot.mean(), - Operation::Sum => pivot.sum(), - Operation::Min => pivot.min(), - Operation::Max => pivot.max(), - Operation::First => pivot.first(), - Operation::Median => pivot.median(), - } - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -fn check_pivot_column( - df: &polars::prelude::DataFrame, - col: &Tagged, -) -> Result<(), ShellError> { - let series = df - .column(&col.item) - .map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?; - - match series.dtype() { - DataType::UInt8 - | DataType::UInt16 - | DataType::UInt32 - | DataType::UInt64 - | DataType::Int8 - | DataType::Int16 - | DataType::Int32 - | DataType::Int64 - | DataType::Utf8 => Ok(()), - _ => Err(ShellError::labeled_error( - "Pivot error", - format!("Unsupported datatype {}", series.dtype()), - col.tag.span, - )), - } -} - -fn check_value_column( - df: &polars::prelude::DataFrame, - col: &Tagged, -) -> Result<(), ShellError> { - let series = df - .column(&col.item) - .map_err(|e| parse_polars_error::<&str>(&e, &col.tag.span, None))?; - - match series.dtype() { - DataType::UInt8 - | DataType::UInt16 - | DataType::UInt32 - | DataType::UInt64 - | DataType::Int8 - | DataType::Int16 - | DataType::Int32 - | DataType::Int64 - | DataType::Float32 - | DataType::Float64 => Ok(()), - _ => Err(ShellError::labeled_error( - "Pivot error", - format!("Unsupported datatype {}", series.dtype()), - col.tag.span, - )), - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/rename.rs b/old_nushell/crates/nu-command/src/commands/dataframe/rename.rs deleted file mode 100644 index 28e922b6d..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/rename.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; - -use nu_source::Tagged; - -use super::utils::parse_polars_error; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe rename-col" - } - - fn usage(&self) -> &str { - "[DataFrame] rename a dataframe column" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe rename-col") - .required("from", SyntaxShape::String, "column name to be renamed") - .required("to", SyntaxShape::String, "new column name") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Renames a dataframe column", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe rename-col a ab", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "ab".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - ), - Column::new( - "b".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let from: Tagged = args.req(0)?; - let to: Tagged = args.req(1)?; - - let (mut df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - df.as_mut() - .rename(&from.item, &to.item) - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/sample.rs b/old_nushell/crates/nu-command/src/commands/dataframe/sample.rs deleted file mode 100644 index d32a09283..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/sample.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{dataframe::NuDataFrame, Signature, SyntaxShape}; - -use nu_source::Tagged; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe sample" - } - - fn usage(&self) -> &str { - "[DataFrame] Create sample dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe sample") - .named( - "n_rows", - SyntaxShape::Number, - "number of rows to be taken from dataframe", - Some('n'), - ) - .named( - "fraction", - SyntaxShape::Number, - "fraction of dataframe to be taken", - Some('f'), - ) - .switch("replace", "sample with replace", Some('e')) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Sample rows from dataframe", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe sample -n 1", - result: None, // No expected value because sampling is random - }, - Example { - description: "Shows sample row using fraction and replace", - example: - "[[a b]; [1 2] [3 4] [5 6]] | dataframe to-df | dataframe sample -f 0.5 -e", - result: None, // No expected value because sampling is random - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let rows: Option> = args.get_flag("n_rows")?; - let fraction: Option> = args.get_flag("fraction")?; - let replace: bool = args.has_flag("replace"); - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = match (rows, fraction) { - (Some(rows), None) => df - .as_ref() - .sample_n(rows.item, replace) - .map_err(|e| parse_polars_error::<&str>(&e, &rows.tag.span, None)), - (None, Some(frac)) => df - .as_ref() - .sample_frac(frac.item, replace) - .map_err(|e| parse_polars_error::<&str>(&e, &frac.tag.span, None)), - (Some(_), Some(_)) => Err(ShellError::labeled_error( - "Incompatible flags", - "Only one selection criterion allowed", - &tag, - )), - (None, None) => Err(ShellError::labeled_error_with_secondary( - "No selection", - "No selection criterion was found", - &tag, - "Perhaps you want to use the flag -n or -f", - &tag, - )), - }?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/select.rs b/old_nushell/crates/nu-command/src/commands/dataframe/select.rs deleted file mode 100644 index 4d6c7d817..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/select.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::{convert_columns, parse_polars_error}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe select" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates a new dataframe with the selected columns" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe select").rest("rest", SyntaxShape::Any, "selected column names") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create new dataframe with column a", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe select a", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let columns: Vec = args.rest(0)?; - - let (col_string, col_span) = convert_columns(&columns, &tag)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df - .as_ref() - .select(&col_string) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/all_false.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/all_false.rs deleted file mode 100644 index 88c5b3fdb..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/all_false.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, Value, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe all-false" - } - - fn usage(&self) -> &str { - "[Series] Returns true if all values are false" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe all-false") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Returns true if all values are false", - example: "[$false $false $false] | dataframe to-df | dataframe all-false", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "all_false".to_string(), - vec![UntaggedValue::boolean(true).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Checks the result from a comparison", - example: r#"let s = ([5 6 2 10] | dataframe to-df); - let res = ($s > 9); - $res | dataframe all-false"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "all_false".to_string(), - vec![UntaggedValue::boolean(false).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let bool = series.bool().map_err(|e| { - parse_polars_error::<&str>( - &e, - &tag.span, - Some("all-false only works with series of type bool"), - ) - })?; - - let res = bool.all_false(); - - let value = Value { - value: UntaggedValue::Primitive(res.into()), - tag: tag.clone(), - }; - - let df = NuDataFrame::try_from_columns( - vec![Column::new("all_false".to_string(), vec![value])], - &tag.span, - )?; - - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/all_true.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/all_true.rs deleted file mode 100644 index 46a8e3e3c..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/all_true.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, Value, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe all-true" - } - - fn usage(&self) -> &str { - "[Series] Returns true if all values are true" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe all-true") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Returns true if all values are true", - example: "[$true $true $true] | dataframe to-df | dataframe all-true", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "all_true".to_string(), - vec![UntaggedValue::boolean(true).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Checks the result from a comparison", - example: r#"let s = ([5 6 2 8] | dataframe to-df); - let res = ($s > 9); - $res | dataframe all-true"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "all_true".to_string(), - vec![UntaggedValue::boolean(false).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let bool = series.bool().map_err(|e| { - parse_polars_error::<&str>( - &e, - &tag.span, - Some("all-true only works with series of type bool"), - ) - })?; - - let res = bool.all_true(); - - let value = Value { - value: UntaggedValue::Primitive(res.into()), - tag: tag.clone(), - }; - - let df = NuDataFrame::try_from_columns( - vec![Column::new("all_true".to_string(), vec![value])], - &tag.span, - )?; - - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_max.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_max.rs deleted file mode 100644 index 050f4534f..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_max.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::{IntoSeries, NewChunkedArray, UInt32Chunked}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe arg-max" - } - - fn usage(&self) -> &str { - "[Series] Return index for max value in series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe arg-max") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns index for max value", - example: "[1 3 2] | dataframe to-df | dataframe arg-max", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "arg_max".to_string(), - vec![UntaggedValue::int(1).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let res = series.arg_max(); - - let chunked = match res { - Some(index) => UInt32Chunked::new_from_slice("arg_max", &[index as u32]), - None => UInt32Chunked::new_from_slice("arg_max", &[]), - }; - - let res = chunked.into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_min.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_min.rs deleted file mode 100644 index 710410bdb..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_min.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::{IntoSeries, NewChunkedArray, UInt32Chunked}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe arg-min" - } - - fn usage(&self) -> &str { - "[Series] Return index for min value in series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe arg-min") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns index for min value", - example: "[1 3 2] | dataframe to-df | dataframe arg-min", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "arg_min".to_string(), - vec![UntaggedValue::int(0).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df.as_series(&df_tag.span)?.arg_min(); - - let chunked = match res { - Some(index) => UInt32Chunked::new_from_slice("arg_min", &[index as u32]), - None => UInt32Chunked::new_from_slice("arg_min", &[]), - }; - - let res = chunked.into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_sort.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_sort.rs deleted file mode 100644 index af5cf7a48..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_sort.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe arg-sort" - } - - fn usage(&self) -> &str { - "[Series] Returns indexes for a sorted series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe arg-sort").switch("reverse", "reverse order", Some('r')) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns indexes for a sorted series", - example: "[1 2 2 3 3] | dataframe to-df | dataframe arg-sort", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "arg_sort".to_string(), - vec![ - UntaggedValue::int(0).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let reverse = args.has_flag("reverse"); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut res = df.as_series(&df_tag.span)?.argsort(reverse).into_series(); - res.rename("arg_sort"); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_true.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_true.rs deleted file mode 100644 index 1f278f91d..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_true.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe arg-true" - } - - fn usage(&self) -> &str { - "[Series] Returns indexes where values are true" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe arg-true") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns indexes where values are true", - example: "[$false $true $false] | dataframe to-df | dataframe arg-true", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "arg_true".to_string(), - vec![UntaggedValue::int(1).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let bool = series.bool().map_err(|e| { - parse_polars_error::<&str>( - &e, - &tag.span, - Some("arg-true only works with series of type bool"), - ) - })?; - - let mut res = bool.arg_true().into_series(); - res.rename("arg_true"); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_unique.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_unique.rs deleted file mode 100644 index dc33e14e2..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/arg_unique.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe arg-unique" - } - - fn usage(&self) -> &str { - "[Series] Returns indexes for unique values" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe arg-unique") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns indexes for unique values", - example: "[1 2 2 3 3] | dataframe to-df | dataframe arg-unique", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "arg_unique".to_string(), - vec![ - UntaggedValue::int(0).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut res = df - .as_series(&df_tag.span)? - .arg_unique() - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))? - .into_series(); - - res.rename("arg_unique"); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/concatenate.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/concatenate.rs deleted file mode 100644 index e6dc0ef26..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/concatenate.rs +++ /dev/null @@ -1,107 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe concatenate" - } - - fn usage(&self) -> &str { - "[Series] Concatenates strings with other array" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe concatenate").required( - "other", - SyntaxShape::Any, - "Other array with string to be concatenated", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Concatenate string", - example: r#"let other = ([za xs cd] | dataframe to-df); - [abc abc abc] | dataframe to-df | dataframe concatenate $other"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("abcza").into(), - UntaggedValue::string("abcxs").into(), - UntaggedValue::string("abccd").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let other: Value = args.req(0)?; - - let other_df = match &other.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only concatenate another series", - other.tag.span, - )), - }?; - - let other_series = other_df.as_series(&other.tag.span)?; - let other_chunked = other_series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &other.tag.span, - Some("The concatenate command can only be used with string columns"), - ) - })?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The concatenate command can only be used with string columns"), - ) - })?; - - let mut res = chunked.concat(other_chunked); - - res.rename(series.name()); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/contains.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/contains.rs deleted file mode 100644 index b99f6f715..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/contains.rs +++ /dev/null @@ -1,89 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::Tagged; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe contains" - } - - fn usage(&self) -> &str { - "[Series] Checks if a pattern is contained in a string" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe contains").required( - "pattern", - SyntaxShape::String, - "Regex pattern to be searched", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns boolean indicating if pattern was found", - example: "[abc acb acb] | dataframe to-df | dataframe contains ab", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let pattern: Tagged = args.req(0)?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The contains command can only be used with string columns"), - ) - })?; - - let res = chunked - .contains(&pattern.item) - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/cumulative.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/cumulative.rs deleted file mode 100644 index c2cb72728..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/cumulative.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::Tagged; -use polars::prelude::DataType; - -enum CumType { - Min, - Max, - Sum, -} - -impl CumType { - fn from_str(roll_type: &str, span: &Span) -> Result { - match roll_type { - "min" => Ok(Self::Min), - "max" => Ok(Self::Max), - "sum" => Ok(Self::Sum), - _ => Err(ShellError::labeled_error_with_secondary( - "Wrong operation", - "Operation not valid for cumulative", - span, - "Perhaps you want to use: max, min, sum", - span, - )), - } - } - - fn to_str(&self) -> &'static str { - match self { - CumType::Min => "cum_min", - CumType::Max => "cum_max", - CumType::Sum => "cum_sum", - } - } -} - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe cum" - } - - fn usage(&self) -> &str { - "[Series] Cumulative calculation for a series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe cum") - .required("type", SyntaxShape::String, "rolling operation") - .switch("reverse", "Reverse cumulative calculation", Some('r')) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Cumulative sum for a series", - example: "[1 2 3 4 5] | dataframe to-df | dataframe cum sum", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0_cum_sum".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(6).into(), - UntaggedValue::int(10).into(), - UntaggedValue::int(15).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cum_type: Tagged = args.req(0)?; - let reverse = args.has_flag("reverse"); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - if let DataType::Object(_) = series.dtype() { - return Err(ShellError::labeled_error( - "Found object series", - "Series of type object cannot be used for cumulative operation", - &df_tag.span, - )); - } - - let cum_type = CumType::from_str(&cum_type.item, &cum_type.tag.span)?; - let mut res = match cum_type { - CumType::Max => series.cummax(reverse), - CumType::Min => series.cummin(reverse), - CumType::Sum => series.cumsum(reverse), - }; - - let name = format!("{}_{}", series.name(), cum_type.to_str()); - res.rename(&name); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_day.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_day.rs deleted file mode 100644 index 7a2d96405..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_day.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-day" - } - - fn usage(&self) -> &str { - "[Series] Gets day from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-day") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns day from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-day"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(4).into(), UntaggedValue::int(4).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.day().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_hour.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_hour.rs deleted file mode 100644 index 96baef7fd..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_hour.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-hour" - } - - fn usage(&self) -> &str { - "[Series] Gets hour from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-hour") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns hour from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-hour"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(16).into(), UntaggedValue::int(16).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.hour().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_minute.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_minute.rs deleted file mode 100644 index 750040452..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_minute.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-minute" - } - - fn usage(&self) -> &str { - "[Series] Gets minute from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-minute") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns minute from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-minute"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(39).into(), UntaggedValue::int(39).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.minute().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_month.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_month.rs deleted file mode 100644 index dba70abef..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_month.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-month" - } - - fn usage(&self) -> &str { - "[Series] Gets month from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-month") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns month from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-month"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(8).into(), UntaggedValue::int(8).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.month().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_nanosecond.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_nanosecond.rs deleted file mode 100644 index 39f89af77..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_nanosecond.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-nanosecond" - } - - fn usage(&self) -> &str { - "[Series] Gets nanosecond from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-nanosecond") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns nanosecond from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-nanosecond"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(0).into(), UntaggedValue::int(0).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.nanosecond().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_ordinal.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_ordinal.rs deleted file mode 100644 index af8537d38..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_ordinal.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-ordinal" - } - - fn usage(&self) -> &str { - "[Series] Gets ordinal date from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-ordinal") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns ordinal from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-ordinal"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::int(217).into(), - UntaggedValue::int(217).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.ordinal().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_second.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_second.rs deleted file mode 100644 index 13984dbef..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_second.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-second" - } - - fn usage(&self) -> &str { - "[Series] Gets second from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-second") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns second from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-second"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(18).into(), UntaggedValue::int(18).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.second().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_week.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_week.rs deleted file mode 100644 index 4d51a470c..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_week.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-week" - } - - fn usage(&self) -> &str { - "[Series] Gets week from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-week") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns week from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-week"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(32).into(), UntaggedValue::int(32).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.week().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_weekday.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_weekday.rs deleted file mode 100644 index 75cc99754..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_weekday.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-weekday" - } - - fn usage(&self) -> &str { - "[Series] Gets weekday from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-weekday") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns weekday from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-weekday"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(1).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.weekday().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_year.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/get_year.rs deleted file mode 100644 index 3a03e4ef1..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/get_year.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe get-year" - } - - fn usage(&self) -> &str { - "[Series] Gets year from date" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe get-year") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns year from a date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe get-year"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::int(2020).into(), - UntaggedValue::int(2020).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.year().into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_duplicated.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/is_duplicated.rs deleted file mode 100644 index 071cb879b..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_duplicated.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe is-duplicated" - } - - fn usage(&self) -> &str { - "[Series] Creates mask indicating duplicated values" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe is-duplicated") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create mask indicating duplicated values", - example: "[5 6 6 6 8 8 8] | dataframe to-df | dataframe is-duplicated", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "is_duplicated".to_string(), - vec![ - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut res = df - .as_series(&df_tag.span)? - .is_duplicated() - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))? - .into_series(); - - res.rename("is_duplicated"); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_in.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/is_in.rs deleted file mode 100644 index 01f2557a1..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_in.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe is-in" - } - - fn usage(&self) -> &str { - "[Series] Checks if elements from a series are contained in right series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe is-in").required("other", SyntaxShape::Any, "right series") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Checks if elements from a series are contained in right series", - example: r#"let other = ([1 3 6] | dataframe to-df); - [5 6 6 6 8 8 8] | dataframe to-df | dataframe is-in $other"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "is_in".to_string(), - vec![ - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let value: Value = args.req(0)?; - - let other_df = match value.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only search in a series", - value.tag.span, - )), - }?; - - let other = other_df.as_series(&value.tag.span)?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut res = df - .as_series(&df_tag.span)? - .is_in(&other) - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))? - .into_series(); - - res.rename("is_in"); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_not_null.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/is_not_null.rs deleted file mode 100644 index 6dc6c5e88..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_not_null.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe is-not-null" - } - - fn usage(&self) -> &str { - "[Series] Creates mask where value is not null" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe is-not-null") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create mask where values are not null", - example: r#"let s = ([5 6 0 8] | dataframe to-df); - let res = ($s / $s); - $res | dataframe is-not-null"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "is_not_null".to_string(), - vec![ - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(true).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df.as_series(&df_tag.span)?.is_not_null(); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_null.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/is_null.rs deleted file mode 100644 index dcd8f37d1..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_null.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe is-null" - } - - fn usage(&self) -> &str { - "[Series] Creates mask where value is null" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe is-null") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create mask where values are null", - example: r#"let s = ([5 6 0 8] | dataframe to-df); - let res = ($s / $s); - $res | dataframe is-null"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "is_null".to_string(), - vec![ - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(false).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df.as_series(&df_tag.span)?.is_null(); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_unique.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/is_unique.rs deleted file mode 100644 index 85c539663..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/is_unique.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe is-unique" - } - - fn usage(&self) -> &str { - "[Series] Creates mask indicating unique values" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe is-unique") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create mask indicating unique values", - example: "[5 6 6 6 8 8 8] | dataframe to-df | dataframe is-unique", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "is_unique".to_string(), - vec![ - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(false).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut res = df - .as_series(&df_tag.span)? - .is_unique() - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))? - .into_series(); - - res.rename("is_unique"); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/mod.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/mod.rs deleted file mode 100644 index a51930f4c..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/mod.rs +++ /dev/null @@ -1,85 +0,0 @@ -pub mod all_false; -pub mod all_true; -pub mod arg_max; -pub mod arg_min; -pub mod arg_sort; -pub mod arg_true; -pub mod arg_unique; -pub mod concatenate; -pub mod contains; -pub mod cumulative; -pub mod get_day; -pub mod get_hour; -pub mod get_minute; -pub mod get_month; -pub mod get_nanosecond; -pub mod get_ordinal; -pub mod get_second; -pub mod get_week; -pub mod get_weekday; -pub mod get_year; -pub mod is_duplicated; -pub mod is_in; -pub mod is_not_null; -pub mod is_null; -pub mod is_unique; -pub mod n_null; -pub mod n_unique; -pub mod not; -pub mod rename; -pub mod replace; -pub mod replace_all; -pub mod rolling; -pub mod set; -pub mod set_with_idx; -pub mod shift; -pub mod str_lengths; -pub mod str_slice; -pub mod strftime; -pub mod to_lowercase; -pub mod to_uppercase; -pub mod unique; -pub mod value_counts; - -pub use all_false::DataFrame as DataFrameAllFalse; -pub use all_true::DataFrame as DataFrameAllTrue; -pub use arg_max::DataFrame as DataFrameArgMax; -pub use arg_min::DataFrame as DataFrameArgMin; -pub use arg_sort::DataFrame as DataFrameArgSort; -pub use arg_true::DataFrame as DataFrameArgTrue; -pub use arg_unique::DataFrame as DataFrameArgUnique; -pub use concatenate::DataFrame as DataFrameConcatenate; -pub use contains::DataFrame as DataFrameContains; -pub use cumulative::DataFrame as DataFrameCumulative; -pub use get_day::DataFrame as DataFrameGetDay; -pub use get_hour::DataFrame as DataFrameGetHour; -pub use get_minute::DataFrame as DataFrameGetMinute; -pub use get_month::DataFrame as DataFrameGetMonth; -pub use get_nanosecond::DataFrame as DataFrameGetNanoSecond; -pub use get_ordinal::DataFrame as DataFrameGetOrdinal; -pub use get_second::DataFrame as DataFrameGetSecond; -pub use get_week::DataFrame as DataFrameGetWeek; -pub use get_weekday::DataFrame as DataFrameGetWeekDay; -pub use get_year::DataFrame as DataFrameGetYear; -pub use is_duplicated::DataFrame as DataFrameIsDuplicated; -pub use is_in::DataFrame as DataFrameIsIn; -pub use is_not_null::DataFrame as DataFrameIsNotNull; -pub use is_null::DataFrame as DataFrameIsNull; -pub use is_unique::DataFrame as DataFrameIsUnique; -pub use n_null::DataFrame as DataFrameNNull; -pub use n_unique::DataFrame as DataFrameNUnique; -pub use not::DataFrame as DataFrameNot; -pub use rename::DataFrame as DataFrameSeriesRename; -pub use replace::DataFrame as DataFrameReplace; -pub use replace_all::DataFrame as DataFrameReplaceAll; -pub use rolling::DataFrame as DataFrameRolling; -pub use set::DataFrame as DataFrameSet; -pub use set_with_idx::DataFrame as DataFrameSetWithIdx; -pub use shift::DataFrame as DataFrameShift; -pub use str_lengths::DataFrame as DataFrameStringLengths; -pub use str_slice::DataFrame as DataFrameStringSlice; -pub use strftime::DataFrame as DataFrameStrFTime; -pub use to_lowercase::DataFrame as DataFrameToLowercase; -pub use to_uppercase::DataFrame as DataFrameToUppercase; -pub use unique::DataFrame as DataFrameUnique; -pub use value_counts::DataFrame as DataFrameValueCounts; diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/n_null.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/n_null.rs deleted file mode 100644 index 42cac40c2..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/n_null.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Primitive, Signature, UntaggedValue, Value, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe count-null" - } - - fn usage(&self) -> &str { - "[Series] Counts null values" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe count-null") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Counts null values", - example: r#"let s = ([1 1 0 0 3 3 4] | dataframe to-df); - ($s / $s) | dataframe count-null"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "count_null".to_string(), - vec![UntaggedValue::int(2).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df.as_series(&df_tag.span)?.null_count(); - - let value = Value { - value: UntaggedValue::Primitive(Primitive::Int(res as i64)), - tag: tag.clone(), - }; - - let df = NuDataFrame::try_from_columns( - vec![Column::new("count_null".to_string(), vec![value])], - &tag.span, - )?; - - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/n_unique.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/n_unique.rs deleted file mode 100644 index cc774f77d..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/n_unique.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Primitive, Signature, UntaggedValue, Value, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe count-unique" - } - - fn usage(&self) -> &str { - "[Series] Counts unique value" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe count-unique") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Counts unique values", - example: "[1 1 2 2 3 3 4] | dataframe to-df | dataframe count-unique", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "count_unique".to_string(), - vec![UntaggedValue::int(4).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df - .as_series(&df_tag.span)? - .n_unique() - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - let value = Value { - value: UntaggedValue::Primitive(Primitive::Int(res as i64)), - tag: tag.clone(), - }; - - let df = NuDataFrame::try_from_columns( - vec![Column::new("count_unique".to_string(), vec![value])], - &tag.span, - )?; - - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/not.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/not.rs deleted file mode 100644 index d51fe7e27..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/not.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; -use std::ops::Not; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe not" - } - - fn usage(&self) -> &str { - "[Series] Inverts boolean mask" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe not") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Inverts boolean mask", - example: "[$true $false $true] | dataframe to-df | dataframe not", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::boolean(false).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(false).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let bool = series.bool().map_err(|e| { - parse_polars_error::<&str>( - &e, - &tag.span, - Some("not only works with series of type bool"), - ) - })?; - - let res = bool.not(); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/rename.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/rename.rs deleted file mode 100644 index d14b49a7a..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/rename.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::Tagged; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe rename" - } - - fn usage(&self) -> &str { - "[Series] Renames a series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe rename").required( - "name", - SyntaxShape::String, - "new series name", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Renames a series", - example: "[5 6 7 8] | dataframe to-df | dataframe rename new_name", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "new_name".to_string(), - vec![ - UntaggedValue::int(5).into(), - UntaggedValue::int(6).into(), - UntaggedValue::int(7).into(), - UntaggedValue::int(8).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let name: Tagged = args.req(0)?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut series = df.as_series(&df_tag.span)?; - - series.rename(&name.item); - - let df = NuDataFrame::try_from_series(vec![series], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/replace.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/replace.rs deleted file mode 100644 index 7e3fc6ef6..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/replace.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::{Span, Tagged}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe replace" - } - - fn usage(&self) -> &str { - "[Series] Replace the leftmost (sub)string by a regex pattern" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe replace") - .required_named( - "pattern", - SyntaxShape::String, - "Regex pattern to be matched", - Some('p'), - ) - .required_named( - "replace", - SyntaxShape::String, - "replacing string", - Some('r'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Replaces string", - example: "[abc abc abc] | dataframe to-df | dataframe replace -p ab -r AB", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("ABc").into(), - UntaggedValue::string("ABc").into(), - UntaggedValue::string("ABc").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let pattern: Tagged = args.req_named("pattern")?; - let replace: Tagged = args.req_named("replace")?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The replace-all command can only be used with string columns"), - ) - })?; - - let mut res = chunked - .replace(&pattern.item, &replace.item) - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - res.rename(series.name()); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/replace_all.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/replace_all.rs deleted file mode 100644 index 6834391e4..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/replace_all.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::Tagged; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe replace-all" - } - - fn usage(&self) -> &str { - "[Series] Replace all (sub)strings by a regex pattern" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe replace") - .required_named( - "pattern", - SyntaxShape::String, - "Regex pattern to be matched", - Some('p'), - ) - .required_named( - "replace", - SyntaxShape::String, - "replacing string", - Some('r'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Replaces string", - example: "[abac abac abac] | dataframe to-df | dataframe replace-all -p a -r A", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("AbAc").into(), - UntaggedValue::string("AbAc").into(), - UntaggedValue::string("AbAc").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let pattern: Tagged = args.req_named("pattern")?; - let replace: Tagged = args.req_named("replace")?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The replace command can only be used with string columns"), - ) - })?; - - let mut res = chunked - .replace_all(&pattern.item, &replace.item) - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - res.rename(series.name()); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/rolling.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/rolling.rs deleted file mode 100644 index 8a37242b7..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/rolling.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::Tagged; -use polars::prelude::{DataType, RollingOptions}; - -enum RollType { - Min, - Max, - Sum, - Mean, -} - -impl RollType { - fn from_str(roll_type: &str, span: &Span) -> Result { - match roll_type { - "min" => Ok(Self::Min), - "max" => Ok(Self::Max), - "sum" => Ok(Self::Sum), - "mean" => Ok(Self::Mean), - _ => Err(ShellError::labeled_error_with_secondary( - "Wrong operation", - "Operation not valid for rolling", - span, - "Perhaps you want to use: max, min, sum, mean", - span, - )), - } - } - - fn to_str(&self) -> &'static str { - match self { - RollType::Min => "rolling_min", - RollType::Max => "rolling_max", - RollType::Sum => "rolling_sum", - RollType::Mean => "rolling_mean", - } - } -} - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe rolling" - } - - fn usage(&self) -> &str { - "[Series] Rolling calculation for a series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe rolling") - .required("type", SyntaxShape::String, "rolling operation") - .required("window", SyntaxShape::Int, "Window size for rolling") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Rolling sum for a series", - example: - "[1 2 3 4 5] | dataframe to-df | dataframe rolling sum 2 | dataframe drop-nulls", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0_rolling_sum".to_string(), - vec![ - UntaggedValue::int(3).into(), - UntaggedValue::int(5).into(), - UntaggedValue::int(7).into(), - UntaggedValue::int(9).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Rolling max for a series", - example: - "[1 2 3 4 5] | dataframe to-df | dataframe rolling max 2 | dataframe drop-nulls", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0_rolling_max".to_string(), - vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(5).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let roll_type: Tagged = args.req(0)?; - let window_size: Tagged = args.req(1)?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - if let DataType::Object(_) = series.dtype() { - return Err(ShellError::labeled_error( - "Found object series", - "Series of type object cannot be used for rolling operation", - &df_tag.span, - )); - } - - let roll_type = RollType::from_str(&roll_type.item, &roll_type.tag.span)?; - let rolling_opts = RollingOptions { - window_size: window_size.item as usize, - min_periods: window_size.item as usize, - weights: None, - center: false, - }; - let res = match roll_type { - RollType::Max => series.rolling_max(rolling_opts), - RollType::Min => series.rolling_min(rolling_opts), - RollType::Sum => series.rolling_sum(rolling_opts), - RollType::Mean => series.rolling_mean(rolling_opts), - }; - - let mut res = res.map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let name = format!("{}_{}", series.name(), roll_type.to_str()); - res.rename(&name); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/set.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/set.rs deleted file mode 100644 index 68b13a125..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/set.rs +++ /dev/null @@ -1,171 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Primitive, Signature, SyntaxShape, UntaggedValue, Value, -}; -use polars::prelude::{ChunkSet, DataType, IntoSeries}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe set" - } - - fn usage(&self) -> &str { - "[Series] Sets value where given mask is true" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe set") - .required("value", SyntaxShape::Any, "value to be inserted in series") - .required_named( - "mask", - SyntaxShape::Any, - "mask indicating insertions", - Some('m'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Shifts the values by a given period", - example: r#"let s = ([1 2 2 3 3] | dataframe to-df | dataframe shift 2); - let mask = ($s | dataframe is-null); - $s | dataframe set 0 --mask $mask"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::int(0).into(), - UntaggedValue::int(0).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(2).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let value: Value = args.req(0)?; - let mask: Value = args.req_named("mask")?; - - let mask_df = match &mask.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only use a series as mask", - value.tag.span, - )), - }?; - - let mask_series = mask_df.as_series(&mask.tag.span)?; - - let bool_mask = match mask_series.dtype() { - DataType::Boolean => mask_series - .bool() - .map_err(|e| parse_polars_error::<&str>(&e, &mask.tag.span, None)), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only use bool series as mask", - value.tag.span, - )), - }?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - match &value.value { - UntaggedValue::Primitive(Primitive::Int(val)) => { - let chunked = series.i64().map_err(|e| { - parse_polars_error::<&str>( - &e, - &value.tag.span, - Some("The value has to match the set value type"), - ) - })?; - - let res = chunked - .set(bool_mask, Some(*val)) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) - } - UntaggedValue::Primitive(Primitive::Decimal(val)) => { - let chunked = series.as_ref().f64().map_err(|e| { - parse_polars_error::<&str>( - &e, - &value.tag.span, - Some("The value has to match the series type"), - ) - })?; - - let res = chunked - .set( - bool_mask, - Some( - val.to_f64() - .expect("internal error: expected f64-compatible decimal"), - ), - ) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) - } - UntaggedValue::Primitive(Primitive::String(val)) => { - let chunked = series.as_ref().utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &value.tag.span, - Some("The value has to match the series type"), - ) - })?; - - let res = chunked - .set(bool_mask, Some(val.as_ref())) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - let mut res = res.into_series(); - res.rename("string"); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) - } - _ => Err(ShellError::labeled_error( - "Incorrect type", - format!( - "this value cannot be set in a series of type '{}'", - series.dtype() - ), - value.tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/set_with_idx.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/set_with_idx.rs deleted file mode 100644 index e541be455..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/set_with_idx.rs +++ /dev/null @@ -1,181 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Primitive, Signature, SyntaxShape, UntaggedValue, Value, -}; -use polars::prelude::{ChunkSet, DataType, IntoSeries}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe set-with-idx" - } - - fn usage(&self) -> &str { - "[Series] Sets value in the given index" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe set-with-idx") - .required("value", SyntaxShape::Any, "value to be inserted in series") - .required_named( - "indices", - SyntaxShape::Any, - "list of indices indicating where to set the value", - Some('i'), - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Set value in selected rows from series", - example: r#"let series = ([4 1 5 2 4 3] | dataframe to-df); - let indices = ([0 2] | dataframe to-df); - $series | dataframe set-with-idx 6 -i $indices"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::int(6).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(6).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(3).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let value: Value = args.req(0)?; - let indices: Value = args.req_named("indices")?; - - let indices = match &indices.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only use a series for set command", - value.tag.span, - )), - }?; - - let indices = indices.as_series(&value.tag.span)?; - - let casted = match indices.dtype() { - DataType::UInt32 | DataType::UInt64 | DataType::Int32 | DataType::Int64 => indices - .as_ref() - .cast(&DataType::UInt32) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None)), - _ => Err(ShellError::labeled_error_with_secondary( - "Incorrect type", - "Series with incorrect type", - &value.tag.span, - "Consider using a Series with type int type", - &value.tag.span, - )), - }?; - - let indices = casted - .u32() - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))? - .into_iter() - .filter_map(|val| val.map(|v| v as usize)); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - match &value.value { - UntaggedValue::Primitive(Primitive::Int(val)) => { - let chunked = series.i64().map_err(|e| { - parse_polars_error::<&str>( - &e, - &value.tag.span, - Some("The value has to match the set value type"), - ) - })?; - - let res = chunked - .set_at_idx(indices, Some(*val)) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) - } - UntaggedValue::Primitive(Primitive::Decimal(val)) => { - let chunked = series.as_ref().f64().map_err(|e| { - parse_polars_error::<&str>( - &e, - &value.tag.span, - Some("The value has to match the series type"), - ) - })?; - - let res = chunked - .set_at_idx( - indices, - Some( - val.to_f64() - .expect("internal error: expected f64-compatible decimal"), - ), - ) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) - } - UntaggedValue::Primitive(Primitive::String(val)) => { - let chunked = series.as_ref().utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &value.tag.span, - Some("The value has to match the series type"), - ) - })?; - - let res = chunked - .set_at_idx(indices, Some(val.as_ref())) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - let mut res = res.into_series(); - res.rename("string"); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) - } - _ => Err(ShellError::labeled_error( - "Incorrect type", - format!( - "this value cannot be set in a series of type '{}'", - series.as_ref().dtype() - ), - value.tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/shift.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/shift.rs deleted file mode 100644 index 6aaa6b60b..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/shift.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{dataframe::NuDataFrame, Signature, SyntaxShape}; -use nu_source::Tagged; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe shift" - } - - fn usage(&self) -> &str { - "[Series] Shifts the values by a given period" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe unique").required("period", SyntaxShape::Int, "shift period") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Shifts the values by a given period", - example: "[1 2 2 3 3] | dataframe to-df | dataframe shift 2", - result: None, - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let period: Tagged = args.req(0)?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df.as_series(&df_tag.span)?.shift(period.item); - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/str_lengths.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/str_lengths.rs deleted file mode 100644 index a2d31e160..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/str_lengths.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe str-lengths" - } - - fn usage(&self) -> &str { - "[Series] Get lengths of all strings" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe str-lengths") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns string lengths", - example: "[a ab abc] | dataframe to-df | dataframe str-lengths", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The str-lengths command can only be used with string columns"), - ) - })?; - - let res = chunked.as_ref().str_lengths(); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/str_slice.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/str_slice.rs deleted file mode 100644 index 2689348c3..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/str_slice.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; -use nu_source::Tagged; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe str-slice" - } - - fn usage(&self) -> &str { - "[Series] Slices the string from the start position until the selected length" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe replace") - .required_named("start", SyntaxShape::Int, "start of slice", Some('s')) - .named("length", SyntaxShape::Int, "optional length", Some('l')) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Creates slices from the strings", - example: "[abcded abc321 abc123] | dataframe to-df | dataframe str-slice -s 1 -l 2", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("bc").into(), - UntaggedValue::string("bc").into(), - UntaggedValue::string("bc").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let start: Tagged = args.req_named("start")?; - - let length: Option> = args.get_flag("length")?; - let length = length.map(|v| v.item as u64); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The str-slice command can only be used with string columns"), - ) - })?; - - let mut res = chunked - .str_slice(start.item, length) - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - res.rename(series.name()); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/strftime.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/strftime.rs deleted file mode 100644 index 8be3f31fb..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/strftime.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; - -use nu_source::Tagged; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe strftime" - } - - fn usage(&self) -> &str { - "[Series] Formats date based on string rule" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe strftime").required("fmt", SyntaxShape::String, "Format rule") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Formats date", - example: r#"let dt = ('2020-08-04T16:39:18+00:00' | str to-datetime -z 'UTC'); - let df = ([$dt $dt] | dataframe to-df); - $df | dataframe strftime "%Y/%m/%d""#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("2020/08/04").into(), - UntaggedValue::string("2020/08/04").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let fmt: Tagged = args.req(0)?; - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let series = df.as_series(&df_tag.span)?; - - let casted = series - .datetime() - .map_err(|e| parse_polars_error::<&str>(&e, &df_tag.span, None))?; - - let res = casted.strftime(&fmt.item).into_series(); - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/to_lowercase.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/to_lowercase.rs deleted file mode 100644 index 7ea88f3b1..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/to_lowercase.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe to-lowercase" - } - - fn usage(&self) -> &str { - "[Series] Lowercase the strings in the column" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe to-lowercase") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Modifies strings to lowercase", - example: "[Abc aBc abC] | dataframe to-df | dataframe to-lowercase", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("abc").into(), - UntaggedValue::string("abc").into(), - UntaggedValue::string("abc").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The to-lowercase command can only be used with string columns"), - ) - })?; - - let mut res = chunked.to_lowercase(); - res.rename(series.name()); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/to_uppercase.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/to_uppercase.rs deleted file mode 100644 index ab0665572..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/to_uppercase.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; -use polars::prelude::IntoSeries; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe to-uppercase" - } - - fn usage(&self) -> &str { - "[Series] Uppercase the strings in the column" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe to-uppercase") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Modifies strings to uppercase", - example: "[Abc aBc abC] | dataframe to-df | dataframe to-uppercase", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("ABC").into(), - UntaggedValue::string("ABC").into(), - UntaggedValue::string("ABC").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let series = df.as_series(&df_tag.span)?; - let chunked = series.utf8().map_err(|e| { - parse_polars_error::<&str>( - &e, - &df_tag.span, - Some("The to-uppercase command can only be used with string columns"), - ) - })?; - - let mut res = chunked.to_uppercase(); - res.rename(series.name()); - - let df = NuDataFrame::try_from_series(vec![res.into_series()], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/unique.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/unique.rs deleted file mode 100644 index eac8994b5..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/unique.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::{commands::dataframe::utils::parse_polars_error, prelude::*}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe unique" - } - - fn usage(&self) -> &str { - "[Series] Returns unique values from a series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe unique") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Returns unique values from a series", - example: "[2 2 2 2 2] | dataframe to-df | dataframe unique", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(2).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let res = df - .as_series(&df_tag.span)? - .unique() - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - let df = NuDataFrame::try_from_series(vec![res], &tag.span)?; - Ok(OutputStream::one(df.into_value(df_tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/series/value_counts.rs b/old_nushell/crates/nu-command/src/commands/dataframe/series/value_counts.rs deleted file mode 100644 index a992db6a5..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/series/value_counts.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -use crate::commands::dataframe::utils::parse_polars_error; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe value-counts" - } - - fn usage(&self) -> &str { - "[Series] Returns a dataframe with the counts for unique values in series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe value-counts") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Calculates value counts", - example: "[5 5 5 5 6 6] | dataframe to-df | dataframe value-counts", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "0".to_string(), - vec![UntaggedValue::int(5).into(), UntaggedValue::int(6).into()], - ), - Column::new( - "counts".to_string(), - vec![UntaggedValue::int(4).into(), UntaggedValue::int(2).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, df_tag) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let df_new = df - .as_series(&df_tag.span)? - .value_counts() - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value( - df_new, tag, - ))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/shape.rs b/old_nushell/crates/nu-command/src/commands/dataframe/shape.rs deleted file mode 100644 index 29424b034..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/shape.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, Value, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe shape" - } - - fn usage(&self) -> &str { - "[DataFrame] Shows column and row size for a dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe shape") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Shows row and column shape", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe shape", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("rows".to_string(), vec![UntaggedValue::int(2).into()]), - Column::new("columns".to_string(), vec![UntaggedValue::int(2).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let rows = Value { - value: (df.as_ref().height() as i64).into(), - tag: Tag::default(), - }; - - let cols = Value { - value: (df.as_ref().width() as i64).into(), - tag: Tag::default(), - }; - - let rows_col = Column::new("rows".to_string(), vec![rows]); - let cols_col = Column::new("columns".to_string(), vec![cols]); - - let df = NuDataFrame::try_from_columns(vec![rows_col, cols_col], &tag.span)?; - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/show.rs b/old_nushell/crates/nu-command/src/commands/dataframe/show.rs deleted file mode 100644 index 6a21d24da..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/show.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{dataframe::NuDataFrame, Signature, SyntaxShape}; - -use nu_source::Tagged; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe show" - } - - fn usage(&self) -> &str { - "[DataFrame] Converts a section of the dataframe to a Table or List value" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe show") - .named( - "n_rows", - SyntaxShape::Number, - "number of rows to be shown", - Some('n'), - ) - .switch("tail", "shows tail rows", Some('t')) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Shows head rows from dataframe", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe show", - result: None, - }, - Example { - description: "Shows tail rows from dataframe", - example: "[[a b]; [1 2] [3 4] [5 6]] | dataframe to-df | dataframe show -t -n 1", - result: None, - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let rows: Option> = args.get_flag("n_rows")?; - let tail: bool = args.has_flag("tail"); - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let rows = rows.map(|v| v.item); - let values = if tail { df.tail(rows)? } else { df.head(rows)? }; - - Ok(OutputStream::from_stream(values.into_iter())) -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/slice.rs b/old_nushell/crates/nu-command/src/commands/dataframe/slice.rs deleted file mode 100644 index 5a7b5c6f2..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/slice.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, -}; - -use nu_source::Tagged; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe slice" - } - - fn usage(&self) -> &str { - "[DataFrame] Creates new dataframe from a slice of rows" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe slice") - .required("offset", SyntaxShape::Number, "start of slice") - .required("size", SyntaxShape::Number, "size of slice") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Create new dataframe from a slice of the rows", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe slice 0 1", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![UntaggedValue::int(1).into()]), - Column::new("b".to_string(), vec![UntaggedValue::int(2).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let offset: Tagged = args.req(0)?; - let size: Tagged = args.req(1)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - let res = df.as_ref().slice(offset.item as i64, size.item); - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/sort.rs b/old_nushell/crates/nu-command/src/commands/dataframe/sort.rs deleted file mode 100644 index 6146847a8..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/sort.rs +++ /dev/null @@ -1,134 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; - -use super::utils::{convert_columns, parse_polars_error}; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe sort" - } - - fn usage(&self) -> &str { - "[DataFrame, Series] Creates new sorted dataframe or series" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe sort") - .switch("reverse", "invert sort", Some('r')) - .rest("rest", SyntaxShape::Any, "column names to sort dataframe") - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Create new sorted dataframe", - example: "[[a b]; [3 4] [1 2]] | dataframe to-df | dataframe sort a", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - ), - Column::new( - "b".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Create new sorted series", - example: "[3 4 1 2] | dataframe to-df | dataframe sort", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let value = args.input.next().ok_or_else(|| { - ShellError::labeled_error("Empty stream", "No value found in stream", &tag.span) - })?; - - let reverse = args.has_flag("reverse"); - - match &value.value { - UntaggedValue::DataFrame(df) => { - if df.is_series() { - let columns = df.as_ref().get_column_names(); - - let res = df - .as_ref() - .sort(columns, reverse) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) - } else { - let columns: Vec = args.rest(0)?; - - if !columns.is_empty() { - let (col_string, col_span) = convert_columns(&columns, &tag)?; - - let res = df - .as_ref() - .sort(&col_string, reverse) - .map_err(|e| parse_polars_error::<&str>(&e, &col_span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) - } else { - Err(ShellError::labeled_error( - "Missing columns", - "missing column name to perform sort", - &tag.span, - )) - } - } - } - _ => Err(ShellError::labeled_error( - "Incorrect type", - "sort cannot be done with this value", - &value.tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/take.rs b/old_nushell/crates/nu-command/src/commands/dataframe/take.rs deleted file mode 100644 index 1373d8c7d..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/take.rs +++ /dev/null @@ -1,142 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; -use polars::prelude::DataType; - -use super::utils::parse_polars_error; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe take" - } - - fn usage(&self) -> &str { - "[DataFrame, Series] Creates new dataframe using the given indices" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe take").required( - "indices", - SyntaxShape::Any, - "list of indices used to take data", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Takes selected rows from dataframe", - example: r#"let df = ([[a b]; [4 1] [5 2] [4 3]] | dataframe to-df); - let indices = ([0 2] | dataframe to-df); - $df | dataframe take $indices"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![UntaggedValue::int(4).into(), UntaggedValue::int(4).into()], - ), - Column::new( - "b".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Takes selected rows from series", - example: r#"let series = ([4 1 5 2 4 3] | dataframe to-df); - let indices = ([0 2] | dataframe to-df); - $series | dataframe take $indices"#, - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![UntaggedValue::int(4).into(), UntaggedValue::int(5).into()], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let value: Value = args.req(0)?; - - let df = match &value.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only use a series for take command", - value.tag.span, - )), - }?; - - let series = df.as_series(&value.tag.span)?; - - let casted = match series.dtype() { - DataType::UInt32 | DataType::UInt64 | DataType::Int32 | DataType::Int64 => series - .as_ref() - .cast(&DataType::UInt32) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None)), - _ => Err(ShellError::labeled_error_with_secondary( - "Incorrect type", - "Series with incorrect type", - &value.tag.span, - "Consider using a Series with type int type", - &value.tag.span, - )), - }?; - - let indices = casted - .u32() - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - let value = args.input.next().ok_or_else(|| { - ShellError::labeled_error("Empty stream", "No value found in the stream", &tag) - })?; - - match &value.value { - UntaggedValue::DataFrame(df) => { - let res = df - .as_ref() - .take(indices) - .map_err(|e| parse_polars_error::<&str>(&e, &value.tag.span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value(res, tag))) - } - _ => Err(ShellError::labeled_error( - "No dataframe or series in stream", - "no dataframe or series found in input stream", - &value.tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/to_csv.rs b/old_nushell/crates/nu-command/src/commands/dataframe/to_csv.rs deleted file mode 100644 index d0d9a600a..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/to_csv.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::fs::File; -use std::path::PathBuf; - -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::dataframe::NuDataFrame; -use nu_protocol::Primitive; -use nu_protocol::Value; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; - -use polars::prelude::{CsvWriter, SerWriter}; - -use nu_source::Tagged; - -use super::utils::parse_polars_error; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe to-csv" - } - - fn usage(&self) -> &str { - "[DataFrame] Saves dataframe to csv file" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe to-csv") - .required("file", SyntaxShape::FilePath, "file path to save dataframe") - .named( - "delimiter", - SyntaxShape::String, - "file delimiter character", - Some('d'), - ) - .switch("no_header", "Indicates if file doesn't have header", None) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Saves dataframe to csv file", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe to-csv test.csv", - result: None, - }, - Example { - description: "Saves dataframe to csv file using other delimiter", - example: - "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe to-csv test.csv -d '|'", - result: None, - }, - ] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let file_name: Tagged = args.req(0)?; - let delimiter: Option> = args.get_flag("delimiter")?; - let no_header: bool = args.has_flag("no_header"); - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let mut file = File::create(&file_name.item).map_err(|e| { - ShellError::labeled_error("Error with file name", e.to_string(), &file_name.tag.span) - })?; - - let writer = CsvWriter::new(&mut file); - - let writer = if no_header { - writer.has_header(false) - } else { - writer.has_header(true) - }; - - let writer = match delimiter { - None => writer, - Some(d) => { - if d.item.len() != 1 { - return Err(ShellError::labeled_error( - "Incorrect delimiter", - "Delimiter has to be one char", - &d.tag, - )); - } else { - let delimiter = match d.item.chars().next() { - Some(d) => d as u8, - None => unreachable!(), - }; - - writer.with_delimiter(delimiter) - } - } - }; - - writer - .finish(df.as_ref()) - .map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?; - - let tagged_value = Value { - value: UntaggedValue::Primitive(Primitive::String(format!( - "saved {}", - &file_name.item.to_str().expect("csv file") - ))), - tag: Tag::unknown(), - }; - - Ok(InputStream::one(tagged_value).into_output_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/to_df.rs b/old_nushell/crates/nu-command/src/commands/dataframe/to_df.rs deleted file mode 100644 index cb85d6b08..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/to_df.rs +++ /dev/null @@ -1,137 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, UntaggedValue, -}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe to-df" - } - - fn usage(&self) -> &str { - "Converts a List, Table or Dictionary into a polars dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe to-df") - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let df = NuDataFrame::try_from_iter(args.input, &tag)?; - - Ok(InputStream::one(df.into_value(tag))) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Takes a dictionary and creates a dataframe", - example: "[[a b];[1 2] [3 4]] | dataframe to-df", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![UntaggedValue::int(1).into(), UntaggedValue::int(3).into()], - ), - Column::new( - "b".to_string(), - vec![UntaggedValue::int(2).into(), UntaggedValue::int(4).into()], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Takes a list of tables and creates a dataframe", - example: "[[1 2 a] [3 4 b] [5 6 c]] | dataframe to-df", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "0".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(5).into(), - ], - ), - Column::new( - "1".to_string(), - vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(6).into(), - ], - ), - Column::new( - "2".to_string(), - vec![ - UntaggedValue::string("a").into(), - UntaggedValue::string("b").into(), - UntaggedValue::string("c").into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Takes a list and creates a dataframe", - example: "[a b c] | dataframe to-df", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::string("a").into(), - UntaggedValue::string("b").into(), - UntaggedValue::string("c").into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - Example { - description: "Takes a list of booleans and creates a dataframe", - example: "[$true $true $false] | dataframe to-df", - result: Some(vec![NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![ - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(true).into(), - UntaggedValue::boolean(false).into(), - ], - )], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }, - ] - } -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/to_parquet.rs b/old_nushell/crates/nu-command/src/commands/dataframe/to_parquet.rs deleted file mode 100644 index 87bb4b925..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/to_parquet.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::fs::File; -use std::path::PathBuf; - -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::dataframe::NuDataFrame; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; - -use polars::prelude::ParquetWriter; - -use nu_source::Tagged; - -use super::utils::parse_polars_error; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe to-parquet" - } - - fn usage(&self) -> &str { - "[DataFrame] Saves dataframe to parquet file" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe to-parquet").required( - "file", - SyntaxShape::FilePath, - "file path to save dataframe", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Saves dataframe to parquet file", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe to-parquet test.parquet", - result: None, - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let file_name: Tagged = args.req(0)?; - - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - let file = File::create(&file_name.item).map_err(|e| { - ShellError::labeled_error("Error with file name", e.to_string(), &file_name.tag.span) - })?; - - ParquetWriter::new(file) - .finish(df.as_ref()) - .map_err(|e| parse_polars_error::<&str>(&e, &file_name.tag.span, None))?; - - let tagged_value = Value { - value: UntaggedValue::Primitive(Primitive::String(format!( - "saved {}", - &file_name.item.to_str().expect("parquet file") - ))), - tag: Tag::unknown(), - }; - - Ok(InputStream::one(tagged_value).into_output_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/utils.rs b/old_nushell/crates/nu-command/src/commands/dataframe/utils.rs deleted file mode 100644 index 20245c25c..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/utils.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{Primitive, UntaggedValue, Value}; -use polars::prelude::PolarsError; - -// Converts a Vec to a Vec with a Span marking the whole -// location of the columns for error referencing -pub(crate) fn convert_columns( - columns: &[Value], - tag: &Tag, -) -> Result<(Vec, Span), ShellError> { - let mut col_span = match columns - .get(0) - .map(|v| Span::new(v.tag.span.start(), v.tag.span.end())) - { - Some(span) => span, - None => { - return Err(ShellError::labeled_error( - "Empty column list", - "Empty list found for command", - tag, - )) - } - }; - - let res = columns - .iter() - .map(|value| match &value.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - col_span = col_span.until(value.tag.span); - Ok(s.clone()) - } - _ => Err(ShellError::labeled_error( - "Incorrect column format", - "Only string as column name", - &value.tag, - )), - }) - .collect::, _>>()?; - - Ok((res, col_span)) -} - -pub(crate) fn parse_polars_error>( - e: &PolarsError, - span: &Span, - secondary: Option, -) -> ShellError { - let msg = match e { - PolarsError::PolarsArrowError(_) => "PolarsArrow Error", - PolarsError::ArrowError(_) => "Arrow Error", - PolarsError::InvalidOperation(_) => "Invalid Operation", - PolarsError::DataTypeMisMatch(_) => "Data Type Mismatch", - PolarsError::NotFound(_) => "Not Found", - PolarsError::ShapeMisMatch(_) => "Shape Mismatch", - PolarsError::ComputeError(_) => "Computer error", - PolarsError::OutOfBounds(_) => "Out Of Bounds", - PolarsError::NoSlice => "No Slice", - PolarsError::NoData(_) => "No Data", - PolarsError::ValueError(_) => "Value Error", - PolarsError::MemoryNotAligned => "Memory Not Aligned", - PolarsError::RandError(_) => "Rand Error", - PolarsError::HasNullValues(_) => "Has Null Values", - PolarsError::UnknownSchema(_) => "Unknown Schema", - PolarsError::Various(_) => "Various", - PolarsError::Io(_) => "Io Error", - PolarsError::Regex(_) => "Regex Error", - PolarsError::Duplicate(_) => "Duplicate Error", - PolarsError::ImplementationError => "Implementation Error", - }; - - let label = e.to_string(); - - match secondary { - None => ShellError::labeled_error(msg, label, span), - Some(s) => ShellError::labeled_error_with_secondary(msg, label, span, s.as_ref(), span), - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/where_.rs b/old_nushell/crates/nu-command/src/commands/dataframe/where_.rs deleted file mode 100644 index aaf5d2b25..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/where_.rs +++ /dev/null @@ -1,237 +0,0 @@ -use crate::prelude::*; -use nu_engine::{evaluate_baseline_expr, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - hir::{CapturedBlock, ClassifiedCommand, Expression, Literal, Operator, SpannedExpression}, - Primitive, Signature, SyntaxShape, UnspannedPathMember, UntaggedValue, Value, -}; - -use super::utils::parse_polars_error; -use polars::prelude::{ChunkCompare, DataType, Series}; - -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe where" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe where").required( - "condition", - SyntaxShape::RowCondition, - "the condition that must match", - ) - } - - fn usage(&self) -> &str { - "[DataFrame] Filter dataframe to match the condition" - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Filter dataframe based on column a", - example: "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe where a == 1", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new("a".to_string(), vec![UntaggedValue::int(1).into()]), - Column::new("b".to_string(), vec![UntaggedValue::int(2).into()]), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - - let expression = block - .block - .block - .get(0) - .and_then(|group| { - group - .pipelines - .get(0) - .and_then(|v| v.list.get(0)) - .and_then(|expr| match &expr { - ClassifiedCommand::Expr(expr) => match &expr.as_ref().expr { - Expression::Binary(expr) => Some(expr), - _ => None, - }, - _ => None, - }) - }) - .ok_or_else(|| { - ShellError::labeled_error("Expected a condition", "expected a condition", &tag.span) - })?; - - let lhs = match &expression.left.expr { - Expression::FullColumnPath(p) => p.as_ref().tail.get(0), - _ => None, - } - .ok_or_else(|| { - ShellError::labeled_error( - "No column name", - "Not a column name found in left hand side of comparison", - &expression.left.span, - ) - })?; - - let (col_name, col_name_span) = match &lhs.unspanned { - UnspannedPathMember::String(name) => Ok((name, &lhs.span)), - _ => Err(ShellError::labeled_error( - "No column name", - "Not a string as column name", - &lhs.span, - )), - }?; - - let rhs = evaluate_baseline_expr(&expression.right, &args.context)?; - - filter_dataframe(args, col_name, col_name_span, &rhs, &expression.op) -} - -macro_rules! comparison_arm { - ($comparison:expr, $col:expr, $condition:expr, $span:expr) => { - match $condition { - Primitive::Int(val) => Ok($comparison($col, *val)), - Primitive::BigInt(val) => Ok($comparison( - $col, - val.to_i64() - .expect("Internal error: protocol did not use compatible decimal"), - )), - Primitive::Decimal(val) => Ok($comparison( - $col, - val.to_f64() - .expect("Internal error: protocol did not use compatible decimal"), - )), - Primitive::String(val) => { - let temp: &str = val.as_ref(); - Ok($comparison($col, temp)) - } - _ => Err(ShellError::labeled_error( - "Invalid datatype", - format!( - "this operator cannot be used with the selected '{}' datatype", - $col.dtype() - ), - &$span, - )), - } - }; -} - -// With the information extracted from the block we can filter the dataframe using -// polars operations -fn filter_dataframe( - mut args: CommandArgs, - col_name: &str, - col_name_span: &Span, - rhs: &Value, - operator: &SpannedExpression, -) -> Result { - let right_condition = match &rhs.value { - UntaggedValue::Primitive(primitive) => Ok(primitive), - _ => Err(ShellError::labeled_error( - "Incorrect argument", - "Expected primitive values", - &rhs.tag.span, - )), - }?; - - let span = args.call_info.name_tag.span; - let (df, _) = NuDataFrame::try_from_stream(&mut args.input, &span)?; - - let col = df - .as_ref() - .column(col_name) - .map_err(|e| parse_polars_error::<&str>(&e, col_name_span, None))?; - - let op = match &operator.expr { - Expression::Literal(Literal::Operator(op)) => Ok(op), - _ => Err(ShellError::labeled_error( - "Incorrect argument", - "Expected operator", - &operator.span, - )), - }?; - - let mask = match op { - Operator::Equal => comparison_arm!(Series::eq, col, right_condition, operator.span), - Operator::NotEqual => comparison_arm!(Series::neq, col, right_condition, operator.span), - Operator::LessThan => comparison_arm!(Series::lt, col, right_condition, operator.span), - Operator::LessThanOrEqual => { - comparison_arm!(Series::lt_eq, col, right_condition, operator.span) - } - Operator::GreaterThan => comparison_arm!(Series::gt, col, right_condition, operator.span), - Operator::GreaterThanOrEqual => { - comparison_arm!(Series::gt_eq, col, right_condition, operator.span) - } - Operator::Contains => match col.dtype() { - DataType::Utf8 => match right_condition { - Primitive::String(pat) => { - let casted = col.utf8().map_err(|e| { - parse_polars_error::<&str>(&e, &args.call_info.name_tag.span, None) - })?; - - casted.contains(pat).map_err(|e| { - parse_polars_error::<&str>(&e, &args.call_info.name_tag.span, None) - }) - } - _ => Err(ShellError::labeled_error_with_secondary( - "Incorrect argument", - "Can't perform contains with this value", - &rhs.tag.span, - "Contains only works with strings", - &rhs.tag.span, - )), - }, - _ => Err(ShellError::labeled_error_with_secondary( - "Incorrect datatype", - format!("The selected column is of type '{}'", col.dtype()), - col_name_span, - "Perhaps you want to select a column of 'str' type", - col_name_span, - )), - }, - _ => Err(ShellError::labeled_error( - "Incorrect operator", - "Not implemented operator for dataframes filter", - &operator.span, - )), - }?; - - let res = df - .as_ref() - .filter(&mask) - .map_err(|e| parse_polars_error::<&str>(&e, &args.call_info.name_tag.span, None))?; - - Ok(OutputStream::one(NuDataFrame::dataframe_to_value( - res, - args.call_info.name_tag, - ))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/dataframe/with_column.rs b/old_nushell/crates/nu-command/src/commands/dataframe/with_column.rs deleted file mode 100644 index da2225add..000000000 --- a/old_nushell/crates/nu-command/src/commands/dataframe/with_column.rs +++ /dev/null @@ -1,107 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - dataframe::{Column, NuDataFrame}, - Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tagged; - -use super::utils::parse_polars_error; -pub struct DataFrame; - -impl WholeStreamCommand for DataFrame { - fn name(&self) -> &str { - "dataframe with-column" - } - - fn usage(&self) -> &str { - "[DataFrame] Adds a series to the dataframe" - } - - fn signature(&self) -> Signature { - Signature::build("dataframe with-column") - .required("series", SyntaxShape::Any, "series to be added") - .required_named("name", SyntaxShape::String, "column name", Some('n')) - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Adds a series to the dataframe", - example: - "[[a b]; [1 2] [3 4]] | dataframe to-df | dataframe with-column ([5 6] | dataframe to-df) --name c", - result: Some(vec![NuDataFrame::try_from_columns( - vec![ - Column::new( - "a".to_string(), - vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - ], - ), - Column::new( - "b".to_string(), - vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(4).into(), - ], - ), - Column::new( - "c".to_string(), - vec![ - UntaggedValue::int(5).into(), - UntaggedValue::int(6).into(), - ], - ), - ], - &Span::default(), - ) - .expect("simple df for test should not fail") - .into_value(Tag::default())]), - }] - } -} - -fn command(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let value: Value = args.req(0)?; - let name: Tagged = args.req_named("name")?; - - let df = match value.value { - UntaggedValue::DataFrame(df) => Ok(df), - _ => Err(ShellError::labeled_error( - "Incorrect type", - "can only add a series to a dataframe", - value.tag.span, - )), - }?; - - let mut series = df.as_series(&value.tag.span)?; - - let series = series.rename(&name.item).clone(); - - let (mut df, _) = NuDataFrame::try_from_stream(&mut args.input, &tag.span)?; - - df.as_mut() - .with_column(series) - .map_err(|e| parse_polars_error::<&str>(&e, &tag.span, None))?; - - Ok(OutputStream::one(df.into_value(tag))) -} - -#[cfg(test)] -mod tests { - use super::DataFrame; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test_dataframe as test_examples; - - test_examples(DataFrame {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/env/autoenv.rs b/old_nushell/crates/nu-command/src/commands/env/autoenv.rs deleted file mode 100644 index d8a8b492a..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/autoenv.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; -pub struct Autoenv; - -impl WholeStreamCommand for Autoenv { - fn name(&self) -> &str { - "autoenv" - } - fn usage(&self) -> &str { - "Manage directory specific environment variables and scripts." - } - - fn extra_usage(&self) -> &str { - // "Mark a .nu-env file in a directory as trusted. Needs to be re-run after each change to the file or its filepath." - r#"Create a file called .nu-env in any directory and run 'autoenv trust' to let nushell load it when entering the directory. -The .nu-env file has the same format as your $HOME/nu/config.toml file. By loading a .nu-env file the following applies: - - environment variables (section \"[env]\") are loaded from the .nu-env file. Those env variables only exist in this directory (and children directories) - - the \"startup\" commands are run when entering the directory - - the \"on_exit\" commands are run when leaving the directory -"# - } - - fn signature(&self) -> Signature { - Signature::build("autoenv") - } - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(get_full_help(&Autoenv, args.scope())).into_value(Tag::unknown()), - ))) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Example .nu-env file", - example: r#"cat .nu-env - startup = ["echo ...entering the directory", "echo 1 2 3"] - on_exit = ["echo ...leaving the directory"] - - [env] - mykey = "myvalue" - "#, - result: None, - }] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/env/autoenv_trust.rs b/old_nushell/crates/nu-command/src/commands/env/autoenv_trust.rs deleted file mode 100644 index d3f62ca05..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/autoenv_trust.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::prelude::*; -use nu_data::config::read_trusted; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::SyntaxShape; -use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; -use sha2::{Digest, Sha256}; -use std::{fs, path::PathBuf}; -pub struct AutoenvTrust; - -impl WholeStreamCommand for AutoenvTrust { - fn name(&self) -> &str { - "autoenv trust" - } - - fn signature(&self) -> Signature { - Signature::build("autoenv trust") - .optional("dir", SyntaxShape::String, "Directory to allow") - .switch("quiet", "Don't output success message", Some('q')) - } - - fn usage(&self) -> &str { - "Trust a .nu-env file in the current or given directory" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let file_to_trust = match args.opt(0)? { - Some(Value { - value: UntaggedValue::Primitive(Primitive::String(ref path)), - tag: _, - }) => { - let mut dir = nu_path::canonicalize(path)?; - dir.push(".nu-env"); - dir - } - _ => { - let mut dir = nu_path::canonicalize(std::env::current_dir()?)?; - dir.push(".nu-env"); - dir - } - }; - let quiet = args.has_flag("quiet"); - - let content = std::fs::read(&file_to_trust)?; - - let filename = file_to_trust.to_string_lossy().to_string(); - let mut allowed = read_trusted()?; - allowed - .files - .insert(filename, Sha256::digest(&content).as_slice().to_vec()); - - let config_path = config::default_path_for(&Some(PathBuf::from("nu-env.toml")))?; - let tomlstr = toml::to_string(&allowed).map_err(|_| { - ShellError::untagged_runtime_error("Couldn't serialize allowed dirs to nu-env.toml") - })?; - fs::write(config_path, tomlstr).expect("Couldn't write to toml file"); - - if quiet { - Ok(ActionStream::empty()) - } else { - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(".nu-env trusted!").into_value(tag), - ))) - } - } - fn is_binary(&self) -> bool { - false - } - fn examples(&self) -> Vec { - vec![ - Example { - description: "Allow .nu-env file in current directory", - example: "autoenv trust", - result: None, - }, - Example { - description: "Allow .nu-env file in directory foo", - example: "autoenv trust foo", - result: None, - }, - ] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/env/autoenv_untrust.rs b/old_nushell/crates/nu-command/src/commands/env/autoenv_untrust.rs deleted file mode 100644 index 61e144805..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/autoenv_untrust.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::prelude::*; -use nu_data::config::Trusted; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::SyntaxShape; -use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; -use std::io::Read; -use std::{fs, path::PathBuf}; -pub struct AutoenvUntrust; - -impl WholeStreamCommand for AutoenvUntrust { - fn name(&self) -> &str { - "autoenv untrust" - } - - fn signature(&self) -> Signature { - Signature::build("autoenv untrust") - .optional("dir", SyntaxShape::String, "Directory to disallow") - .switch("quiet", "Don't output success message", Some('q')) - } - - fn usage(&self) -> &str { - "Untrust a .nu-env file in the current or given directory" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let file_to_untrust = match args.opt(0)? { - Some(Value { - value: UntaggedValue::Primitive(Primitive::String(ref path)), - tag: _, - }) => { - let mut dir = nu_path::canonicalize(path)?; - dir.push(".nu-env"); - dir - } - _ => { - let mut dir = std::env::current_dir()?; - dir.push(".nu-env"); - dir - } - }; - let quiet = args.has_flag("quiet"); - - let config_path = config::default_path_for(&Some(PathBuf::from("nu-env.toml")))?; - - let mut file = match std::fs::OpenOptions::new() - .read(true) - .create(true) - .write(true) - .open(config_path.clone()) - { - Ok(p) => p, - Err(_) => { - return Err(ShellError::untagged_runtime_error( - "Couldn't open nu-env.toml", - )); - } - }; - - let mut doc = String::new(); - file.read_to_string(&mut doc)?; - - let mut allowed: Trusted = toml::from_str(&doc).unwrap_or_else(|_| Trusted::new()); - - let file_to_untrust = file_to_untrust.to_string_lossy().to_string(); - - if allowed.files.remove(&file_to_untrust).is_none() { - return - Err(ShellError::untagged_runtime_error( - "No .nu-env file to untrust in the given directory. Is it missing, or already untrusted?", - )); - } - - let tomlstr = toml::to_string(&allowed).map_err(|_| { - ShellError::untagged_runtime_error("Couldn't serialize allowed dirs to nu-env.toml") - })?; - fs::write(config_path, tomlstr).expect("Couldn't write to toml file"); - - if quiet { - Ok(ActionStream::empty()) - } else { - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(".nu-env untrusted!").into_value(tag), - ))) - } - } - fn is_binary(&self) -> bool { - false - } - fn examples(&self) -> Vec { - vec![ - Example { - description: "Disallow .nu-env file in current directory", - example: "autoenv untrust", - result: None, - }, - Example { - description: "Disallow .nu-env file in directory foo", - example: "autoenv untrust foo", - result: None, - }, - ] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/env/let_env.rs b/old_nushell/crates/nu-command/src/commands/env/let_env.rs deleted file mode 100644 index 30885a92e..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/let_env.rs +++ /dev/null @@ -1,104 +0,0 @@ -use std::convert::TryInto; - -use crate::prelude::*; -use nu_engine::{evaluate_baseline_expr, EnvVar, WholeStreamCommand}; - -use nu_errors::ShellError; -use nu_protocol::{hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape}; -use nu_source::Tagged; - -pub struct LetEnv; - -#[derive(Deserialize)] -pub struct LetEnvArgs { - pub name: Tagged, - pub equals: Tagged, - pub rhs: CapturedBlock, -} - -impl WholeStreamCommand for LetEnv { - fn name(&self) -> &str { - "let-env" - } - - fn signature(&self) -> Signature { - Signature::build("let-env") - .required( - "name", - SyntaxShape::String, - "the name of the environment variable", - ) - .required("equals", SyntaxShape::String, "the equals sign") - .required( - "expr", - SyntaxShape::MathExpression, - "the value for the environment variable", - ) - } - - fn usage(&self) -> &str { - "Create an environment variable and give it a value." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - set_env(args) - } - - fn examples(&self) -> Vec { - vec![] - } -} - -pub fn set_env(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let name: Tagged = args.req(0)?; - let rhs: CapturedBlock = args.req(2)?; - - let (expr, captured) = { - if rhs.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a value", - "expected a value", - tag, - )); - } - match rhs.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => (expr.clone(), rhs.captured.clone()), - _ => { - return Err(ShellError::labeled_error( - "Expected a value", - "expected a value", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a value", - "expected a value", - tag, - )); - } - } - }; - - ctx.scope.enter_scope(); - ctx.scope.add_vars(&captured.entries); - - let value = evaluate_baseline_expr(&expr, ctx); - - ctx.scope.exit_scope(); - - let value: EnvVar = value?.try_into()?; - let name = name.item; - - // Note: this is a special case for setting the context from a command - // In this case, if we don't set it now, we'll lose the scope that this - // variable should be set into. - ctx.scope.add_env_var(name, value); - - Ok(ActionStream::empty()) -} diff --git a/old_nushell/crates/nu-command/src/commands/env/load_env.rs b/old_nushell/crates/nu-command/src/commands/env/load_env.rs deleted file mode 100644 index e7a4eb1e1..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/load_env.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::convert::TryInto; - -use crate::prelude::*; -use nu_engine::{EnvVar, WholeStreamCommand}; - -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; - -pub struct LoadEnv; - -impl WholeStreamCommand for LoadEnv { - fn name(&self) -> &str { - "load-env" - } - - fn signature(&self) -> Signature { - Signature::build("load-env").optional( - "environ", - SyntaxShape::Any, - "Optional environment table to load in. If not provided, will use the table provided on the input stream", - ) - } - - fn usage(&self) -> &str { - "Set environment variables using a table stream" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - load_env(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Load variables from an input stream", - example: r#"echo [[name, value]; ["NAME", "JT"] ["AGE", "UNKNOWN"]] | load-env; echo $nu.env.NAME"#, - result: Some(vec![Value::from("JT")]), - }, - Example { - description: "Load variables from an argument", - example: r#"load-env [[name, value]; ["NAME", "JT"] ["AGE", "UNKNOWN"]]; echo $nu.env.NAME"#, - result: Some(vec![Value::from("JT")]), - }, - Example { - description: "Load variables from an argument and an input stream", - example: r#"echo [[name, value]; ["NAME", "JT"]] | load-env [[name, value]; ["VALUE", "FOO"]]; echo $nu.env.NAME $nu.env.VALUE"#, - result: Some(vec![Value::from("JT"), Value::from("UNKNOWN")]), - }, - ] - } -} - -fn load_env_from_table( - values: impl IntoIterator, - ctx: &EvaluationContext, -) -> Result<(), ShellError> { - for value in values { - let mut var_name = None; - let mut var_value = None; - - let tag = value.tag(); - - for (key, value) in value.row_entries() { - if key == "name" { - var_name = Some(value); - } else if key == "value" { - var_value = Some(value); - } - } - - match (var_name, var_value) { - (Some(name), Some(value)) => { - let env_var: EnvVar = value.try_into()?; - ctx.scope.add_env_var(name.as_string()?, env_var); - } - _ => { - return Err(ShellError::labeled_error( - r#"Expected each row in the table to have a "name" and "value" field."#, - r#"expected a "name" and "value" field"#, - tag, - )) - } - } - } - - Ok(()) -} - -pub fn load_env(args: CommandArgs) -> Result { - let ctx = &args.context; - - if let Some(values) = args.opt::>(0)? { - load_env_from_table(values, ctx)?; - } - - load_env_from_table(args.input, ctx)?; - - Ok(ActionStream::empty()) -} diff --git a/old_nushell/crates/nu-command/src/commands/env/mod.rs b/old_nushell/crates/nu-command/src/commands/env/mod.rs deleted file mode 100644 index 26b343ac5..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -mod autoenv; -mod autoenv_trust; -mod autoenv_untrust; -mod let_env; -mod load_env; -mod unlet_env; -mod with_env; - -pub use autoenv::Autoenv; -pub use autoenv_trust::AutoenvTrust; -pub use autoenv_untrust::AutoenvUntrust; -pub use let_env::LetEnv; -pub use load_env::LoadEnv; -pub use unlet_env::UnletEnv; -pub use with_env::WithEnv; diff --git a/old_nushell/crates/nu-command/src/commands/env/unlet_env.rs b/old_nushell/crates/nu-command/src/commands/env/unlet_env.rs deleted file mode 100644 index d639f8803..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/unlet_env.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; - -pub struct UnletEnv; - -#[derive(Deserialize)] -pub struct UnletEnvArgs { - pub name: Tagged, -} - -impl WholeStreamCommand for UnletEnv { - fn name(&self) -> &str { - "unlet-env" - } - - fn signature(&self) -> Signature { - Signature::build("unlet-env").required( - "name", - SyntaxShape::String, - "the name of the environment variable", - ) - } - - fn usage(&self) -> &str { - "Delete an environment variable." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - unlet_env(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Remove the environment variable named FOO.", - example: "unlet-env FOO", - result: None, - }] - } -} - -pub fn unlet_env(args: CommandArgs) -> Result { - let ctx = &args.context; - - let name: Tagged = args.req(0)?; - - if ctx.scope.remove_env_var(&name.item) == None { - return Err(ShellError::labeled_error( - "Not an environment variable. Run `echo $nu.env` to view the available variables.", - "not an environment variable", - name.span(), - )); - } - - Ok(ActionStream::empty()) -} diff --git a/old_nushell/crates/nu-command/src/commands/env/with_env.rs b/old_nushell/crates/nu-command/src/commands/env/with_env.rs deleted file mode 100644 index 4dc95326d..000000000 --- a/old_nushell/crates/nu-command/src/commands/env/with_env.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::convert::TryInto; - -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::EnvVar; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value, -}; - -pub struct WithEnv; - -impl WholeStreamCommand for WithEnv { - fn name(&self) -> &str { - "with-env" - } - - fn signature(&self) -> Signature { - Signature::build("with-env") - .required( - "variable", - SyntaxShape::Any, - "the environment variable to temporarily set", - ) - .required( - "block", - SyntaxShape::Block, - "the block to run once the variable is set", - ) - } - - fn usage(&self) -> &str { - "Runs a block with an environment variable set." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - with_env(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Set the MYENV environment variable", - example: r#"with-env [MYENV "my env value"] { echo $nu.env.MYENV }"#, - result: Some(vec![Value::from("my env value")]), - }, - Example { - description: "Set by primitive value list", - example: r#"with-env [X Y W Z] { echo $nu.env.X $nu.env.W }"#, - result: Some(vec![Value::from("Y"), Value::from("Z")]), - }, - Example { - description: "Set by single row table", - example: r#"with-env [[X W]; [Y Z]] { echo $nu.env.X $nu.env.W }"#, - result: Some(vec![Value::from("Y"), Value::from("Z")]), - }, - Example { - description: "Set by row(e.g. `open x.json` or `from json`)", - example: r#"echo '{"X":"Y","W":"Z"}'|from json|with-env $it { echo $nu.env.X $nu.env.W }"#, - result: None, - }, - ] - } -} - -fn with_env(args: CommandArgs) -> Result { - let external_redirection = args.call_info.args.external_redirection; - let context = &args.context; - let variable: Value = args.req(0)?; - let block: CapturedBlock = args.req(1)?; - - let mut env: IndexMap = IndexMap::new(); - - match &variable.value { - UntaggedValue::Table(table) => { - if table.len() == 1 { - // single row([[X W]; [Y Z]]) - for (k, v) in table[0].row_entries() { - env.insert(k.clone(), v.try_into()?); - } - } else { - // primitive values([X Y W Z]) - for row in table.chunks(2) { - if row.len() == 2 && row[0].is_primitive() && row[1].is_primitive() { - env.insert(row[0].convert_to_string(), (&row[1]).try_into()?); - } - } - } - } - // when get object by `open x.json` or `from json` - UntaggedValue::Row(row) => { - for (k, v) in &row.entries { - env.insert(k.clone(), v.try_into()?); - } - } - _ => { - return Err(ShellError::type_error( - "string list or single row", - variable.spanned_type_name(), - )); - } - }; - - context.scope.enter_scope(); - context.scope.add_env(env); - context.scope.add_vars(&block.captured.entries); - - let result = run_block(&block.block, context, args.input, external_redirection); - context.scope.exit_scope(); - - result.map(|x| x.into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::WithEnv; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(WithEnv {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/cd.rs b/old_nushell/crates/nu-command/src/commands/filesystem/cd.rs deleted file mode 100644 index f6c29130e..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/cd.rs +++ /dev/null @@ -1,72 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; - -use nu_engine::shell::CdArgs; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; - -pub struct Cd; - -impl WholeStreamCommand for Cd { - fn name(&self) -> &str { - "cd" - } - - fn signature(&self) -> Signature { - Signature::build("cd").optional( - "directory", - SyntaxShape::FilePath, - "the directory to change to", - ) - } - - fn usage(&self) -> &str { - "Change to a new path." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let shell_manager = args.shell_manager(); - let args = CdArgs { path: args.opt(0)? }; - - shell_manager.cd(args, name) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Change to a new directory called 'dirname'", - example: "cd dirname", - result: None, - }, - Example { - description: "Change to your home directory", - example: "cd", - result: None, - }, - Example { - description: "Change to your home directory (alternate version)", - example: "cd ~", - result: None, - }, - Example { - description: "Change to the previous directory", - example: "cd -", - result: None, - }, - ] - } -} - -#[cfg(test)] -mod tests { - use super::Cd; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Cd {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/cp.rs b/old_nushell/crates/nu-command/src/commands/filesystem/cp.rs deleted file mode 100644 index 6794424e2..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/cp.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::prelude::*; -use nu_engine::{shell::CopyArgs, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; - -pub struct Cpy; - -impl WholeStreamCommand for Cpy { - fn name(&self) -> &str { - "cp" - } - - fn signature(&self) -> Signature { - Signature::build("cp") - .required("src", SyntaxShape::GlobPattern, "the place to copy from") - .required("dst", SyntaxShape::FilePath, "the place to copy to") - .switch( - "recursive", - "copy recursively through subdirectories", - Some('r'), - ) - } - - fn usage(&self) -> &str { - "Copy files." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let shell_manager = args.shell_manager(); - let name = args.call_info.name_tag.clone(); - - let args = CopyArgs { - src: args.req(0)?, - dst: args.req(1)?, - recursive: args.has_flag("recursive"), - }; - shell_manager.cp(args, name) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Copy myfile to dir_b", - example: "cp myfile dir_b", - result: None, - }, - Example { - description: "Recursively copy dir_a to dir_b", - example: "cp -r dir_a dir_b", - result: None, - }, - ] - } -} - -#[cfg(test)] -mod tests { - use super::Cpy; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Cpy {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/ls.rs b/old_nushell/crates/nu-command/src/commands/filesystem/ls.rs deleted file mode 100644 index 23ac1e659..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/ls.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::prelude::*; -use nu_engine::{shell::LsArgs, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; - -pub struct Ls; - -impl WholeStreamCommand for Ls { - fn name(&self) -> &str { - "ls" - } - - fn signature(&self) -> Signature { - Signature::build("ls") - .optional( - "path", - SyntaxShape::GlobPattern, - "a path to get the directory contents from", - ) - .switch("all", "Show hidden files", Some('a')) - .switch( - "long", - "List all available columns for each entry", - Some('l'), - ) - .switch( - "short-names", - "Only print the file names and not the path", - Some('s'), - ) - .switch( - "du", - "Display the apparent directory size in place of the directory metadata size", - Some('d'), - ) - } - - fn usage(&self) -> &str { - "View the contents of the current or given path." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctrl_c = args.ctrl_c(); - let shell_manager = args.shell_manager(); - - let args = LsArgs { - path: args.opt(0)?, - all: args.has_flag("all"), - long: args.has_flag("long"), - short_names: args.has_flag("short-names"), - du: args.has_flag("du"), - }; - - shell_manager.ls(args, name, ctrl_c) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "List all files in the current directory", - example: "ls", - result: None, - }, - Example { - description: "List all files in a subdirectory", - example: "ls subdir", - result: None, - }, - Example { - description: "List all rust files", - example: "ls *.rs", - result: None, - }, - ] - } -} - -#[cfg(test)] -mod tests { - use super::Ls; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Ls {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/mkdir.rs b/old_nushell/crates/nu-command/src/commands/filesystem/mkdir.rs deleted file mode 100644 index 42950454e..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/mkdir.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::prelude::*; -use nu_engine::{shell::MkdirArgs, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -pub struct Mkdir; - -impl WholeStreamCommand for Mkdir { - fn name(&self) -> &str { - "mkdir" - } - - fn signature(&self) -> Signature { - Signature::build("mkdir") - .rest( - "rest", - SyntaxShape::FilePath, - "the name(s) of the path(s) to create", - ) - .switch("show-created-paths", "show the path(s) created.", Some('s')) - } - - fn usage(&self) -> &str { - "Make directories, creates intermediary directories as required." - } - - fn run(&self, args: CommandArgs) -> Result { - mkdir(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Make a directory named foo", - example: "mkdir foo", - result: None, - }] - } -} - -fn mkdir(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let shell_manager = args.shell_manager(); - - let args = MkdirArgs { - rest: args.rest(0)?, - show_created_paths: args.has_flag("show-created-paths"), - }; - - shell_manager.mkdir(args, name) -} - -#[cfg(test)] -mod tests { - use super::Mkdir; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Mkdir {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/mod.rs b/old_nushell/crates/nu-command/src/commands/filesystem/mod.rs deleted file mode 100644 index f8eb69d6f..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -mod cd; -mod cp; -mod ls; -mod mkdir; -mod mv; -pub(crate) mod open; -mod rm; -mod save; -mod touch; - -pub use cd::Cd; -pub use cp::Cpy; -pub use ls::Ls; -pub use mkdir::Mkdir; -pub use mv::Mv; -pub use open::Open; -pub use rm::Remove; -pub use save::Save; -pub use touch::Touch; diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/mv.rs b/old_nushell/crates/nu-command/src/commands/filesystem/mv.rs deleted file mode 100644 index b38178d13..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/mv.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::prelude::*; -use nu_engine::{shell::MvArgs, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; - -pub struct Mv; - -impl WholeStreamCommand for Mv { - fn name(&self) -> &str { - "mv" - } - - fn signature(&self) -> Signature { - Signature::build("mv") - .required( - "source", - SyntaxShape::GlobPattern, - "the location to move files/directories from", - ) - .required( - "destination", - SyntaxShape::FilePath, - "the location to move files/directories to", - ) - } - - fn usage(&self) -> &str { - "Move files or directories." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - mv(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Rename a file", - example: "mv before.txt after.txt", - result: None, - }, - Example { - description: "Move a file into a directory", - example: "mv test.txt my/subdirectory", - result: None, - }, - Example { - description: "Move many files into a directory", - example: "mv *.txt my/subdirectory", - result: None, - }, - ] - } -} - -fn mv(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let shell_manager = args.shell_manager(); - - let args = MvArgs { - src: args.req(0)?, - dst: args.req(1)?, - }; - - shell_manager.mv(args, name) -} - -#[cfg(test)] -mod tests { - use super::Mv; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Mv {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/open.rs b/old_nushell/crates/nu-command/src/commands/filesystem/open.rs deleted file mode 100644 index d8ddbcfb2..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/open.rs +++ /dev/null @@ -1,265 +0,0 @@ -use crate::commands::viewers::BAT_LANGUAGES; -use crate::prelude::*; -use encoding_rs::{Encoding, UTF_8}; - -use log::debug; -use nu_engine::StringOrBinary; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_path::canonicalize; -use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::{AnchorLocation, Span, Tagged}; -use std::path::{Path, PathBuf}; - -pub struct Open; - -impl WholeStreamCommand for Open { - fn name(&self) -> &str { - "open" - } - - fn signature(&self) -> Signature { - Signature::build(self.name()) - .required( - "path", - SyntaxShape::FilePath, - "the file path to load values from", - ) - .switch( - "raw", - "load content as a string instead of a table", - Some('r'), - ) - .named( - "encoding", - SyntaxShape::String, - "encoding to use to open file", - Some('e'), - ) - } - - fn usage(&self) -> &str { - "Load a file into a cell, convert to table if possible (avoid by appending '--raw')." - } - - fn extra_usage(&self) -> &str { - r#"Multiple encodings are supported for reading text files by using -the '--encoding ' parameter. Here is an example of a few: -big5, euc-jp, euc-kr, gbk, iso-8859-1, utf-16, cp1252, latin5 - -For a more complete list of encodings please refer to the encoding_rs -documentation link at https://docs.rs/encoding_rs/0.8.28/encoding_rs/#statics"# - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - open(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Opens \"users.csv\" and creates a table from the data", - example: "open users.csv", - result: None, - }, - Example { - description: "Opens file with iso-8859-1 encoding", - example: "open file.csv --encoding iso-8859-1 | from csv", - result: None, - }, - Example { - description: "Lists the contents of a directory (identical to `ls ../projectB`)", - example: "open ../projectB", - result: None, - }, - ] - } -} - -pub fn get_encoding(opt: Option>) -> Result<&'static Encoding, ShellError> { - match opt { - None => Ok(UTF_8), - Some(label) => match Encoding::for_label((&label.item).as_bytes()) { - None => Err(ShellError::labeled_error( - format!( - r#"{} is not a valid encoding, refer to https://docs.rs/encoding_rs/0.8.23/encoding_rs/#statics for a valid list of encodings"#, - label.item - ), - "invalid encoding", - label.span(), - )), - Some(encoding) => Ok(encoding), - }, - } -} - -fn open(args: CommandArgs) -> Result { - let scope = args.scope().clone(); - let shell_manager = args.shell_manager(); - let cwd = PathBuf::from(shell_manager.path()); - let name = args.call_info.name_tag.clone(); - let ctrl_c = args.ctrl_c(); - - let path: Tagged = args.req(0)?; - let raw = args.has_flag("raw"); - let encoding: Option> = args.get_flag("encoding")?; - - if path.is_dir() { - let args = nu_engine::shell::LsArgs { - path: Some(path), - all: false, - long: false, - short_names: false, - du: false, - }; - return shell_manager.ls(args, name, ctrl_c); - } - - // TODO: Remove once Streams are supported everywhere! - // As a short term workaround for getting AutoConvert and Bat functionality (Those don't currently support Streams) - - // Check if the extension has a "from *" command OR "bat" supports syntax highlighting - // AND the user doesn't want the raw output - // In these cases, we will collect the Stream - let ext = if raw { - None - } else { - path.extension() - .map(|name| name.to_string_lossy().to_string()) - }; - - if let Some(ext) = ext { - // Check if we have a conversion command - if let Some(_command) = scope.get_command(&format!("from {}", ext)) { - let (_, tagged_contents) = crate::commands::open::fetch( - &cwd, - &PathBuf::from(&path.item), - path.tag.span, - encoding, - )?; - return Ok(ActionStream::one(ReturnSuccess::action( - CommandAction::AutoConvert(tagged_contents, ext), - ))); - } - // Check if bat does syntax highlighting - if BAT_LANGUAGES.contains(&ext.as_ref()) { - let (_, tagged_contents) = crate::commands::open::fetch( - &cwd, - &PathBuf::from(&path.item), - path.tag.span, - encoding, - )?; - return Ok(ActionStream::one(ReturnSuccess::value(tagged_contents))); - } - } - - // Normal Streaming operation - let with_encoding = if encoding.is_none() { - None - } else { - Some(get_encoding(encoding)?) - }; - - let sob_stream = shell_manager.open(&path.item, path.tag.span, with_encoding)?; - - let final_stream = sob_stream.map(move |x| { - // The tag that will used when returning a Value - let file_tag = Tag { - span: path.tag.span, - anchor: Some(AnchorLocation::File(path.to_string_lossy().to_string())), - }; - - match x { - Ok(StringOrBinary::String(s)) => { - ReturnSuccess::value(UntaggedValue::string(s).into_value(file_tag)) - } - Ok(StringOrBinary::Binary(b)) => { - ReturnSuccess::value(UntaggedValue::binary(b).into_value(file_tag)) - } - Err(se) => Err(se), - } - }); - - Ok(ActionStream::new(final_stream)) -} - -// Note that we do not output a Stream in "fetch" since it is only used by "enter" command -// Which we expect to use a concrete Value a not a Stream -pub fn fetch( - cwd: &Path, - location: &Path, - span: Span, - encoding_choice: Option>, -) -> Result<(Option, Value), ShellError> { - // TODO: I don't understand the point of this? Maybe for better error reporting - let mut cwd = PathBuf::from(cwd); - cwd.push(location); - let nice_location = canonicalize(&cwd).map_err(|e| match e.kind() { - std::io::ErrorKind::NotFound => ShellError::labeled_error( - format!("Cannot find file {:?}", cwd), - "cannot find file", - span, - ), - std::io::ErrorKind::PermissionDenied => { - ShellError::labeled_error("Permission denied", "permission denied", span) - } - _ => ShellError::labeled_error( - format!("Cannot open file {:?} because {:?}", &cwd, e), - "Cannot open", - span, - ), - })?; - - // The extension may be used in AutoConvert later on - let ext = location - .extension() - .map(|name| name.to_string_lossy().to_string()); - - // The tag that will used when returning a Value - let file_tag = Tag { - span, - anchor: Some(AnchorLocation::File( - nice_location.to_string_lossy().to_string(), - )), - }; - - let res = std::fs::read(location) - .map_err(|_| ShellError::labeled_error("Can't open filename given", "can't open", span))?; - - // If no encoding is provided we try to guess the encoding to read the file with - let encoding = if encoding_choice.is_none() { - UTF_8 - } else { - get_encoding(encoding_choice.clone())? - }; - - // If the user specified an encoding, then do not do BOM sniffing - let decoded_res = if encoding_choice.is_some() { - let (cow_res, _replacements) = encoding.decode_with_bom_removal(&res); - cow_res - } else { - // Otherwise, use the default UTF-8 encoder with BOM sniffing - let (cow_res, actual_encoding, replacements) = encoding.decode(&res); - // If we had to use replacement characters then fallback to binary - if replacements { - return Ok((ext, UntaggedValue::binary(res).into_value(file_tag))); - } - debug!("Decoded using {:?}", actual_encoding); - cow_res - }; - let v = UntaggedValue::string(decoded_res.to_string()).into_value(file_tag); - Ok((ext, v)) -} - -#[cfg(test)] -mod tests { - use super::Open; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Open {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/rm.rs b/old_nushell/crates/nu-command/src/commands/filesystem/rm.rs deleted file mode 100644 index b45c839d4..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/rm.rs +++ /dev/null @@ -1,116 +0,0 @@ -use crate::prelude::*; -use nu_engine::shell::RemoveArgs; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -pub struct Remove; - -impl WholeStreamCommand for Remove { - fn name(&self) -> &str { - "rm" - } - - fn signature(&self) -> Signature { - Signature::build("rm") - .switch( - "trash", - "use the platform's recycle bin instead of permanently deleting", - Some('t'), - ) - .switch( - "permanent", - "don't use recycle bin, delete permanently", - Some('p'), - ) - .switch("recursive", "delete subdirectories recursively", Some('r')) - .switch("force", "suppress error when no file", Some('f')) - .rest( - "rest", - SyntaxShape::GlobPattern, - "the file path(s) to remove", - ) - } - - fn usage(&self) -> &str { - "Remove file(s)." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - rm(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Delete or move a file to the system trash (depending on 'rm_always_trash' config option)", - example: "rm file.txt", - result: None, - }, - Example { - description: "Move a file to the system trash", - example: "rm --trash file.txt", - result: None, - }, - Example { - description: "Delete a file permanently", - example: "rm --permanent file.txt", - result: None, - }, - Example { - description: "Delete a file, and suppress errors if no file is found", - example: "rm --force file.txt", - result: None, - } - ] - } -} - -fn rm(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let shell_manager = args.shell_manager(); - - let mut rm_args = RemoveArgs { - rest: args.rest(0)?, - recursive: args.has_flag("recursive"), - trash: args.has_flag("trash"), - permanent: args.has_flag("permanent"), - force: args.has_flag("force"), - }; - - if rm_args.trash && rm_args.permanent { - return Ok(ActionStream::one(Err(ShellError::labeled_error( - "only one of --permanent and --trash can be used", - "conflicting flags", - name, - )))); - } - - if rm_args.rest.is_empty() { - let mut input_peek = args.input.peekable(); - while let Some(v) = &input_peek.next() { - if let UntaggedValue::Primitive(Primitive::FilePath(path)) = &v.value { - rm_args.rest.push(Tagged { - item: path.to_path_buf(), - tag: args.call_info.name_tag.clone(), - }) - }; - } - } - - shell_manager.rm(rm_args, name) -} - -#[cfg(test)] -mod tests { - use super::Remove; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Remove {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/save.rs b/old_nushell/crates/nu-command/src/commands/filesystem/save.rs deleted file mode 100644 index 5f342683d..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/save.rs +++ /dev/null @@ -1,270 +0,0 @@ -use crate::prelude::*; -use nu_engine::{UnevaluatedCallInfo, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{ - hir::ExternalRedirection, Primitive, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tagged; -use std::path::{Path, PathBuf}; - -pub struct Save; - -macro_rules! process_unknown { - ($scope:tt, $input:ident, $name_tag:ident) => {{ - if $input.len() > 0 { - match $input[0] { - Value { - value: UntaggedValue::Primitive(Primitive::Binary(_)), - .. - } => process_binary!($scope, $input, $name_tag), - _ => process_string!($scope, $input, $name_tag), - } - } else { - process_string!($scope, $input, $name_tag) - } - }}; -} - -macro_rules! process_string { - ($scope:tt, $input:ident, $name_tag:ident) => {{ - let mut result_string = String::new(); - for res in $input { - match res { - Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - .. - } => { - result_string.push_str(&s); - } - _ => { - break $scope Err(ShellError::labeled_error( - "Save requires string data", - "consider converting data to string (see `help commands`)", - $name_tag, - )); - } - } - } - Ok(result_string.into_bytes()) - }}; -} - -macro_rules! process_binary { - ($scope:tt, $input:ident, $name_tag:ident) => {{ - let mut result_binary: Vec = Vec::new(); - for res in $input { - match res { - Value { - value: UntaggedValue::Primitive(Primitive::Binary(b)), - .. - } => { - for u in b.into_iter() { - result_binary.push(u); - } - } - _ => { - break $scope Err(ShellError::labeled_error( - "Save could not successfully save", - "unexpected data during binary save", - $name_tag, - )); - } - } - } - Ok(result_binary) - }}; -} - -macro_rules! process_string_return_success { - ($scope:tt, $result_vec:ident, $name_tag:ident) => {{ - let mut result_string = String::new(); - for res in $result_vec { - match res { - Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - .. - } => { - result_string.push_str(&s); - } - _ => { - break $scope Err(ShellError::labeled_error( - "Save could not successfully save", - "unexpected data during text save", - $name_tag, - )); - } - } - } - Ok(result_string.into_bytes()) - }}; -} - -macro_rules! process_binary_return_success { - ($scope:tt, $result_vec:ident, $name_tag:ident) => {{ - let mut result_binary: Vec = Vec::new(); - for res in $result_vec { - match res { - Value { - value: UntaggedValue::Primitive(Primitive::Binary(b)), - .. - } => { - for u in b.into_iter() { - result_binary.push(u); - } - } - _ => { - break $scope Err(ShellError::labeled_error( - "Save could not successfully save", - "unexpected data during binary save", - $name_tag, - )); - } - } - } - Ok(result_binary) - }}; -} - -impl WholeStreamCommand for Save { - fn name(&self) -> &str { - "save" - } - - fn signature(&self) -> Signature { - Signature::build("save") - .optional( - "path", - SyntaxShape::FilePath, - "the path to save contents to", - ) - .switch( - "raw", - "treat values as-is rather than auto-converting based on file extension", - Some('r'), - ) - .switch("append", "append values rather than overriding", Some('a')) - } - - fn usage(&self) -> &str { - "Save the contents of the pipeline to a file." - } - - fn run(&self, args: CommandArgs) -> Result { - save(args) - } -} - -fn save(args: CommandArgs) -> Result { - let shell_manager = args.shell_manager(); - let mut full_path = PathBuf::from(shell_manager.path()); - let name_tag = args.call_info.name_tag.clone(); - let name = args.call_info.name_tag.clone(); - let context = args.context.clone(); - let scope = args.scope().clone(); - - let head = args.call_info.args.head.clone(); - - let path: Option> = args.opt(0)?; - let save_raw = args.has_flag("raw"); - let append = args.has_flag("append"); - - let input: Vec = args.input.collect(); - if path.is_none() { - let mut should_return_file_path_error = true; - - // If there is no filename, check the metadata for the anchor filename - if !input.is_empty() { - let anchor = input[0].tag.anchor(); - - if let Some(AnchorLocation::File(file)) = anchor { - should_return_file_path_error = false; - full_path.push(Path::new(&file)); - } - } - - if should_return_file_path_error { - return Err(ShellError::labeled_error( - "Save requires a filepath", - "needs path", - name_tag, - )); - } - } else if let Some(file) = path { - full_path.push(file.item()); - } - - // TODO use label_break_value once it is stable: - // https://github.com/rust-lang/rust/issues/48594 - #[allow(clippy::never_loop)] - let content: Result, ShellError> = 'scope: loop { - break if !save_raw { - if let Some(extension) = full_path.extension() { - let command_name = format!("to {}", extension.to_string_lossy()); - if let Some(converter) = scope.get_command(&command_name) { - let new_args = CommandArgs { - context, - call_info: UnevaluatedCallInfo { - args: nu_protocol::hir::Call { - head, - positional: None, - named: None, - span: Span::unknown(), - external_redirection: ExternalRedirection::Stdout, - }, - name_tag: name_tag.clone(), - }, - input: InputStream::from_stream(input.into_iter()), - }; - let mut result = converter.run(new_args)?; - let result_vec: Vec = result.drain_vec(); - if converter.is_binary() { - process_binary_return_success!('scope, result_vec, name_tag) - } else { - process_string_return_success!('scope, result_vec, name_tag) - } - } else { - process_unknown!('scope, input, name_tag) - } - } else { - process_unknown!('scope, input, name_tag) - } - } else { - Ok(string_from(&input).into_bytes()) - }; - }; - - shell_manager.save(&full_path, &content?, name.span, append) -} - -fn string_from(input: &[Value]) -> String { - let mut save_data = String::new(); - - if !input.is_empty() { - let mut first = true; - for i in input { - if !first { - save_data.push('\n'); - } else { - first = false; - } - if let Ok(data) = &i.as_string() { - save_data.push_str(data); - } - } - } - - save_data -} - -#[cfg(test)] -mod tests { - use super::Save; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Save {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filesystem/touch.rs b/old_nushell/crates/nu-command/src/commands/filesystem/touch.rs deleted file mode 100644 index 6b2907f48..000000000 --- a/old_nushell/crates/nu-command/src/commands/filesystem/touch.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; -use std::fs::OpenOptions; -use std::path::PathBuf; - -pub struct Touch; - -impl WholeStreamCommand for Touch { - fn name(&self) -> &str { - "touch" - } - fn signature(&self) -> Signature { - Signature::build("touch") - .required( - "filename", - SyntaxShape::FilePath, - "the path of the file you want to create", - ) - .rest("rest", SyntaxShape::FilePath, "additional files to create") - } - fn usage(&self) -> &str { - "Creates one or more files." - } - fn run_with_actions(&self, args: CommandArgs) -> Result { - touch(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Creates \"fixture.json\"", - example: "touch fixture.json", - result: None, - }, - Example { - description: "Creates files a, b and c", - example: "touch a b c", - result: None, - }, - ] - } -} - -fn touch(args: CommandArgs) -> Result { - let target: Tagged = args.req(0)?; - let rest: Vec> = args.rest(1)?; - - for item in vec![target].into_iter().chain(rest) { - match OpenOptions::new().write(true).create(true).open(&item) { - Ok(_) => continue, - Err(err) => { - return Err(ShellError::labeled_error( - "File Error", - err.to_string(), - &item.tag, - )) - } - } - } - - Ok(ActionStream::empty()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Touch; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Touch {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/all.rs b/old_nushell/crates/nu-command/src/commands/filters/all.rs deleted file mode 100644 index 81e104196..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/all.rs +++ /dev/null @@ -1,139 +0,0 @@ -use crate::prelude::*; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, -}; - -pub struct Command; - -struct AllArgs { - predicate: CapturedBlock, -} - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "all?" - } - - fn signature(&self) -> Signature { - Signature::build("all?").required( - "condition", - SyntaxShape::RowCondition, - "the condition that must match", - ) - } - - fn usage(&self) -> &str { - "Find if the table rows matches the condition." - } - - fn run(&self, args: CommandArgs) -> Result { - all(args) - } - - fn examples(&self) -> Vec { - use nu_protocol::Value; - - vec![ - Example { - description: "Find if services are running", - example: "echo [[status]; [UP] [UP]] | all? status == UP", - result: Some(vec![Value::from(true)]), - }, - Example { - description: "Check that all values are even", - example: "echo [2 4 6 8] | all? ($it mod 2) == 0", - result: Some(vec![Value::from(true)]), - }, - ] - } -} - -fn all(args: CommandArgs) -> Result { - let ctx = &args.context; - let tag = args.call_info.name_tag.clone(); - let all_args = AllArgs { - predicate: args.req(0)?, - }; - - let err = Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - args.call_info.name_tag.clone(), - )); - - //This seems a little odd. Can't we have predicates with pipelines/multiple statements? - let condition = { - if all_args.predicate.block.block.len() != 1 { - return err; - } - match all_args.predicate.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr.clone(), - _ => { - return err; - } - }, - None => { - return err; - } - } - }; - - let scope = args.scope().clone(); - - let init = Ok(InputStream::one( - UntaggedValue::boolean(true).into_value(&tag), - )); - - // Variables in nu are immutable. Having the same variable across invocations - // of evaluate_baseline_expr does not mutate the variables and those each - // invocations are independent of each other! - scope.enter_scope(); - scope.add_vars(&all_args.predicate.captured.entries); - let result = args.input.fold(init, move |acc, row| { - let condition = condition.clone(); - let ctx = ctx.clone(); - if let Some(positional) = all_args.predicate.block.params.positional.get(0) { - ctx.scope.add_var(positional.0.name(), row); - } else { - ctx.scope.add_var("$it", row); - } - - let condition = evaluate_baseline_expr(&condition, &ctx); - - let curr = acc?.drain_vec(); - let curr = curr - .get(0) - .ok_or_else(|| ShellError::unexpected("No value to check with"))?; - let cond = curr.as_bool()?; - - match condition { - Ok(condition) => match condition.as_bool() { - Ok(b) => Ok(InputStream::one( - UntaggedValue::boolean(cond && b).into_value(&curr.tag), - )), - Err(e) => Err(e), - }, - Err(e) => Err(e), - } - }); - scope.exit_scope(); - - Ok(result?.into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/any.rs b/old_nushell/crates/nu-command/src/commands/filters/any.rs deleted file mode 100644 index ddcad4f16..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/any.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::prelude::*; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, -}; - -pub struct Command; - -struct AnyArgs { - predicate: CapturedBlock, -} - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "any?" - } - - fn signature(&self) -> Signature { - Signature::build("any?").required( - "condition", - SyntaxShape::RowCondition, - "the condition that must match", - ) - } - - fn usage(&self) -> &str { - "Find if the table rows matches the condition." - } - - fn run(&self, args: CommandArgs) -> Result { - any(args) - } - - fn examples(&self) -> Vec { - use nu_protocol::Value; - - vec![ - Example { - description: "Find if a service is not running", - example: "echo [[status]; [UP] [DOWN] [UP]] | any? status == DOWN", - result: Some(vec![Value::from(true)]), - }, - Example { - description: "Check if any of the values is odd", - example: "echo [2 4 1 6 8] | any? ($it mod 2) == 1", - result: Some(vec![Value::from(true)]), - }, - ] - } -} - -fn any(args: CommandArgs) -> Result { - let ctx = &args.context; - let tag = args.call_info.name_tag.clone(); - let any_args = AnyArgs { - predicate: args.req(0)?, - }; - - let err = Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - args.call_info.name_tag.clone(), - )); - - //This seems a little odd. Can't we have predicates with pipelines/multiple statements? - let condition = { - if any_args.predicate.block.block.len() != 1 { - return err; - } - match any_args.predicate.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr.clone(), - _ => { - return err; - } - }, - None => { - return err; - } - } - }; - - let scope = args.scope().clone(); - - let init = Ok(InputStream::one( - UntaggedValue::boolean(false).into_value(&tag), - )); - - // Variables in nu are immutable. Having the same variable across invocations - // of evaluate_baseline_expr does not mutate the variables and thus each - // invocations are independent of each other! - scope.enter_scope(); - scope.add_vars(&any_args.predicate.captured.entries); - - let result = args.input.fold(init, move |acc, row| { - let condition = condition.clone(); - let ctx = ctx.clone(); - if let Some((arg, _)) = any_args.predicate.block.params.positional.first() { - ctx.scope.add_var(arg.name(), row); - } - - let condition = evaluate_baseline_expr(&condition, &ctx); - - let curr = acc?.drain_vec(); - let curr = curr - .get(0) - .ok_or_else(|| ShellError::unexpected("No value to check with"))?; - let cond = curr.as_bool()?; - - match condition { - Ok(condition) => match condition.as_bool() { - Ok(b) => Ok(InputStream::one( - UntaggedValue::boolean(cond || b).into_value(&curr.tag), - )), - Err(e) => Err(e), - }, - Err(e) => Err(e), - } - }); - scope.exit_scope(); - - Ok(result?.into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/append.rs b/old_nushell/crates/nu-command/src/commands/filters/append.rs deleted file mode 100644 index f43a4f565..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/append.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "append" - } - - fn signature(&self) -> Signature { - Signature::build("append").required( - "row value", - SyntaxShape::Any, - "the value of the row to append to the table", - ) - } - - fn usage(&self) -> &str { - "Append a row to the table." - } - - fn run(&self, mut args: CommandArgs) -> Result { - let mut value: Value = args.req(0)?; - - let mut prepend = vec![]; - - if let Some(first) = args.input.next() { - value.tag = first.tag(); - prepend.push(first); - } - - // Checks if we are trying to append a row literal - if let Value { - value: UntaggedValue::Table(values), - tag, - } = &value - { - if values.len() == 1 && values[0].is_row() { - value = values[0].value.clone().into_value(tag); - } - } - - Ok(prepend - .into_iter() - .chain(args.input.into_iter().chain([value])) - .into_output_stream()) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Add values to the end of the table", - example: "echo [1 2 3] | append 4", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ]), - }, - Example { - description: "Add row value to the end of the table", - example: "echo [[country]; [Ecuador] ['New Zealand']] | append [[country]; [USA]]", - result: Some(vec![ - row! { "country".into() => Value::from("Ecuador")}, - row! { "country".into() => Value::from("New Zealand")}, - row! { "country".into() => Value::from("USA")}, - ]), - }, - ] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/collect.rs b/old_nushell/crates/nu-command/src/commands/filters/collect.rs deleted file mode 100644 index 10b4a3e15..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/collect.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{hir::CapturedBlock, Signature, SyntaxShape, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "collect" - } - - fn signature(&self) -> Signature { - Signature::build("collect").required( - "block", - SyntaxShape::Block, - "the block to run once the stream is collected", - ) - } - - fn usage(&self) -> &str { - "Collect the stream and pass it to a block." - } - - fn run(&self, args: CommandArgs) -> Result { - collect(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Use the second value in the stream", - example: "echo 1 2 3 | collect { |x| echo $x.1 }", - result: Some(vec![UntaggedValue::int(2).into()]), - }] - } -} - -fn collect(args: CommandArgs) -> Result { - let external_redirection = args.call_info.args.external_redirection; - let context = &args.context; - let tag = args.call_info.name_tag.clone(); - let block: CapturedBlock = args.req(0)?; - let mut input = args.input; - let param = if !block.block.params.positional.is_empty() { - block.block.params.positional[0].0.name() - } else { - "$it" - }; - - context.scope.enter_scope(); - - context.scope.add_vars(&block.captured.entries); - let mut input = input.drain_vec(); - match input.len() { - x if x > 1 => { - context - .scope - .add_var(param, UntaggedValue::Table(input).into_value(tag)); - } - 1 => { - let item = input.swap_remove(0); - context.scope.add_var(param, item); - } - _ => {} - } - - let result = run_block( - &block.block, - context, - InputStream::empty(), - external_redirection, - ); - context.scope.exit_scope(); - - Ok(result?.into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/compact.rs b/old_nushell/crates/nu-command/src/commands/filters/compact.rs deleted file mode 100644 index 814f569c7..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/compact.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::prelude::*; - -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct Compact; - -pub struct CompactArgs { - columns: Vec>, -} - -impl WholeStreamCommand for Compact { - fn name(&self) -> &str { - "compact" - } - - fn signature(&self) -> Signature { - Signature::build("compact").rest( - "rest", - SyntaxShape::Any, - "the columns to compact from the table", - ) - } - - fn usage(&self) -> &str { - "Creates a table with non-empty rows." - } - - fn run(&self, args: CommandArgs) -> Result { - compact(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Filter out all directory entries having no 'target'", - example: "ls -la | compact target", - result: None, - }] - } -} - -pub fn compact(args: CommandArgs) -> Result { - let (args, input) = ( - CompactArgs { - columns: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .filter(move |item| { - if args.columns.is_empty() { - !item.is_empty() - } else if let Value { - value: UntaggedValue::Row(ref r), - .. - } = item - { - args.columns - .iter() - .all(|field| r.get_data(field).borrow().is_some()) - } else { - false - } - }) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Compact; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Compact {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/default.rs b/old_nushell/crates/nu-command/src/commands/filters/default.rs deleted file mode 100644 index 5778f8e5b..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/default.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use nu_value_ext::ValueExt; - -pub struct Default; - -impl WholeStreamCommand for Default { - fn name(&self) -> &str { - "default" - } - - fn signature(&self) -> Signature { - Signature::build("default") - .required("column name", SyntaxShape::String, "the name of the column") - .required( - "column value", - SyntaxShape::Any, - "the value of the column to default", - ) - } - - fn usage(&self) -> &str { - "Sets a default row's column if missing." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - default(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Give a default 'target' to all file entries", - example: "ls -la | default target 'nothing'", - result: None, - }] - } -} - -fn default(args: CommandArgs) -> Result { - let column: Tagged = args.req(0)?; - let value: Value = args.req(1)?; - - let input = args.input; - - Ok(input - .map(move |item| { - let should_add = matches!( - item, - Value { - value: UntaggedValue::Row(ref r), - .. - } if r.get_data(&column.item).borrow().is_none() - ); - - if should_add { - match item.insert_data_at_path(&column.item, value.clone()) { - Some(new_value) => ReturnSuccess::value(new_value), - None => ReturnSuccess::value(item), - } - } else { - ReturnSuccess::value(item) - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Default; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Default {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/drop/column.rs b/old_nushell/crates/nu-command/src/commands/filters/drop/column.rs deleted file mode 100644 index 717f7acca..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/drop/column.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::prelude::*; -use nu_data::base::select_fields; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "drop column" - } - - fn signature(&self) -> Signature { - Signature::build("drop column").optional( - "columns", - SyntaxShape::Number, - "starting from the end, the number of columns to remove", - ) - } - - fn usage(&self) -> &str { - "Remove the last number of columns. If you want to remove columns by name, try 'reject'." - } - - fn run(&self, args: CommandArgs) -> Result { - drop(args) - } - - fn examples(&self) -> Vec { - use nu_protocol::Value; - - vec![Example { - description: "Remove the last column of a table", - example: "echo [[lib, extension]; [nu-lib, rs] [nu-core, rb]] | drop column", - result: Some(vec![ - row! { "lib".into() => Value::from("nu-lib") }, - row! { "lib".into() => Value::from("nu-core") }, - ]), - }] - } -} - -fn drop(args: CommandArgs) -> Result { - let columns: Option> = args.opt(0)?; - - let to_drop = if let Some(quantity) = columns { - *quantity as usize - } else { - 1 - }; - - Ok(args - .input - .map(move |item| { - let headers = item.data_descriptors(); - - let descs = match headers.len() { - 0 => &headers[..], - n if to_drop > n => &[], - n => &headers[..n - to_drop], - }; - - Ok(select_fields(&item, descs, item.tag())) - }) - .into_input_stream()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/drop/command.rs b/old_nushell/crates/nu-command/src/commands/filters/drop/command.rs deleted file mode 100644 index e5d80626c..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/drop/command.rs +++ /dev/null @@ -1,72 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "drop" - } - - fn signature(&self) -> Signature { - Signature::build("drop").optional( - "rows", - SyntaxShape::Number, - "starting from the back, the number of rows to remove", - ) - } - - fn usage(&self) -> &str { - "Remove the last number of rows or columns." - } - - fn run(&self, args: CommandArgs) -> Result { - drop(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Remove the last item of a list/table", - example: "echo [1 2 3] | drop", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - ]), - }, - Example { - description: "Remove the last 2 items of a list/table", - example: "echo [1 2 3] | drop 2", - result: Some(vec![UntaggedValue::int(1).into()]), - }, - ] - } -} - -fn drop(args: CommandArgs) -> Result { - let rows: Option> = args.opt(0)?; - let v: Vec<_> = args.input.into_vec(); - - let rows_to_drop = if let Some(quantity) = rows { - *quantity as usize - } else { - 1 - }; - - Ok(if rows_to_drop == 0 { - v.into_iter().map(Ok).into_input_stream() - } else { - let k = if v.len() < rows_to_drop { - 0 - } else { - v.len() - rows_to_drop - }; - - let iter = v.into_iter().map(Ok).take(k); - - iter.into_input_stream() - }) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/drop/mod.rs b/old_nushell/crates/nu-command/src/commands/filters/drop/mod.rs deleted file mode 100644 index 407d1c100..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/drop/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod column; -mod command; -mod nth; - -pub use column::SubCommand as DropColumn; -pub use command::Command as Drop; -pub use nth::SubCommand as DropNth; diff --git a/old_nushell/crates/nu-command/src/commands/filters/drop/nth.rs b/old_nushell/crates/nu-command/src/commands/filters/drop/nth.rs deleted file mode 100644 index 9e5b461e8..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/drop/nth.rs +++ /dev/null @@ -1,125 +0,0 @@ -use crate::prelude::*; -use itertools::Either; -use nu_engine::{FromValue, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{Range, Signature, SpannedTypeName, SyntaxShape, Value}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "drop nth" - } - - fn signature(&self) -> Signature { - Signature::build("drop nth") - .required( - "row number or row range", - // FIXME: we can make this accept either Int or Range when we can compose SyntaxShapes - SyntaxShape::Any, - "the number of the row to drop or a range to drop consecutive rows", - ) - .rest( - "rest", - SyntaxShape::Any, - "Optionally drop more rows (Ignored if first argument is a range)", - ) - } - - fn usage(&self) -> &str { - "Drops the selected rows." - } - - fn run(&self, args: CommandArgs) -> Result { - drop(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Drop the second row", - example: "echo [first second third] | drop nth 1", - result: Some(vec![Value::from("first"), Value::from("third")]), - }, - Example { - description: "Drop the first and third rows", - example: "echo [first second third] | drop nth 0 2", - result: Some(vec![Value::from("second")]), - }, - Example { - description: "Drop range rows from second to fourth", - example: "echo [first second third fourth fifth] | drop nth (1..3)", - result: Some(vec![Value::from("first"), Value::from("fifth")]), - }, - ] - } -} - -fn extract_int_or_range(args: &CommandArgs) -> Result, ShellError> { - let value = args.req::(0)?; - - let int_opt = value.as_u64().map(Either::Left).ok(); - let range_opt = FromValue::from_value(&value).map(Either::Right).ok(); - - int_opt - .or(range_opt) - .ok_or_else(|| ShellError::type_error("int or range", value.spanned_type_name())) -} - -fn drop(args: CommandArgs) -> Result { - let number_or_range = extract_int_or_range(&args)?; - let rows = match number_or_range { - Either::Left(row_number) => { - let and_rows: Vec> = args.rest(1)?; - - let mut rows: Vec<_> = and_rows.into_iter().map(|x| x.item as usize).collect(); - rows.push(row_number as usize); - rows.sort_unstable(); - rows - } - Either::Right(row_range) => { - let from = row_range.min_u64()? as usize; - let to = row_range.max_u64()? as usize; - - (from..=to).collect() - } - }; - - let input = args.input; - - Ok(DropNthIterator { - input, - rows, - current: 0, - } - .into_output_stream()) -} - -struct DropNthIterator { - input: InputStream, - rows: Vec, - current: usize, -} - -impl Iterator for DropNthIterator { - type Item = Value; - - fn next(&mut self) -> Option { - loop { - if let Some(row) = self.rows.get(0) { - if self.current == *row { - self.rows.remove(0); - self.current += 1; - let _ = self.input.next(); - continue; - } else { - self.current += 1; - return self.input.next(); - } - } else { - return self.input.next(); - } - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/each/command.rs b/old_nushell/crates/nu-command/src/commands/filters/each/command.rs deleted file mode 100644 index c3782233b..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/each/command.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ExternalRedirection}, - Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, -}; - -pub struct Each; - -impl WholeStreamCommand for Each { - fn name(&self) -> &str { - "each" - } - - fn signature(&self) -> Signature { - Signature::build("each") - .required("block", SyntaxShape::Block, "the block to run on each row") - .switch( - "numbered", - "returned a numbered item ($it.index and $it.item)", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Run a block on each row of the table." - } - - fn run(&self, args: CommandArgs) -> Result { - each(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Echo the sum of each row", - example: "echo [[1 2] [3 4]] | each { echo $it | math sum }", - result: None, - }, - Example { - description: "Echo the square of each integer", - example: "echo [1 2 3] | each { echo ($it * $it) }", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(9).into(), - ]), - }, - Example { - description: "Number each item and echo a message", - example: - "echo ['bob' 'fred'] | each --numbered { echo $\"($it.index) is ($it.item)\" }", - result: Some(vec![Value::from("0 is bob"), Value::from("1 is fred")]), - }, - Example { - description: "Name the block variable that each uses", - example: "[1, 2, 3] | each {|x| $x + 100}", - result: Some(vec![ - UntaggedValue::int(101).into(), - UntaggedValue::int(102).into(), - UntaggedValue::int(103).into(), - ]), - }, - ] - } -} - -pub fn process_row( - captured_block: Arc, - context: Arc, - input: Value, - external_redirection: ExternalRedirection, -) -> Result { - let input_clone = input.clone(); - // When we process a row, we need to know whether the block wants to have the contents of the row as - // a parameter to the block (so it gets assigned to a variable that can be used inside the block) or - // if it wants the contents as as an input stream - - let input_stream = if !captured_block.block.params.positional.is_empty() { - InputStream::empty() - } else { - vec![Ok(input_clone)].into_iter().into_input_stream() - }; - - context.scope.enter_scope(); - context.scope.add_vars(&captured_block.captured.entries); - - if let Some((arg, _)) = captured_block.block.params.positional.first() { - context.scope.add_var(arg.name(), input); - } else { - context.scope.add_var("$it", input); - } - - let result = run_block( - &captured_block.block, - &context, - input_stream, - external_redirection, - ); - - context.scope.exit_scope(); - - result -} - -pub(crate) fn make_indexed_item(index: usize, item: Value) -> Value { - let mut dict = TaggedDictBuilder::new(item.tag()); - dict.insert_untagged("index", UntaggedValue::int(index as i64)); - dict.insert_value("item", item); - - dict.into_value() -} - -fn each(args: CommandArgs) -> Result { - let context = Arc::new(args.context.clone()); - let external_redirection = args.call_info.args.external_redirection; - - let block: CapturedBlock = args.req(0)?; - let numbered: bool = args.has_flag("numbered"); - - let block = Arc::new(block); - - if numbered { - Ok(args - .input - .enumerate() - .flat_map(move |input| { - let block = block.clone(); - let context = context.clone(); - let row = make_indexed_item(input.0, input.1); - - match process_row(block, context, row, external_redirection) { - Ok(s) => s, - Err(e) => OutputStream::one(Value::error(e)), - } - }) - .into_output_stream()) - } else { - Ok(args - .input - .flat_map(move |input| { - let block = block.clone(); - let context = context.clone(); - - match process_row(block, context, input, external_redirection) { - Ok(s) => s, - Err(e) => OutputStream::one(Value::error(e)), - } - }) - .into_output_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::Each; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Each {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/each/group.rs b/old_nushell/crates/nu-command/src/commands/filters/each/group.rs deleted file mode 100644 index 2d82b3f97..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/each/group.rs +++ /dev/null @@ -1,142 +0,0 @@ -use crate::commands::filters::each::process_row; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ExternalRedirection}, - Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tagged; - -pub struct EachGroup; - -impl WholeStreamCommand for EachGroup { - fn name(&self) -> &str { - "each group" - } - - fn signature(&self) -> Signature { - Signature::build("each group") - .required("group_size", SyntaxShape::Int, "the size of each group") - .required( - "block", - SyntaxShape::Block, - "the block to run on each group", - ) - } - - fn usage(&self) -> &str { - "Runs a block on groups of `group_size` rows of a table at a time." - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Echo the sum of each pair", - example: "echo [1 2 3 4] | each group 2 { echo $it | math sum }", - result: None, - }] - } - - fn run(&self, args: CommandArgs) -> Result { - let context = Arc::new(args.context.clone()); - let external_redirection = args.call_info.args.external_redirection; - - let group_size: Tagged = args.req(0)?; - let block: CapturedBlock = args.req(1)?; - let block = Arc::new(block); - - let each_group_iterator = EachGroupIterator { - block, - context, - group_size: group_size.item, - input: args.input, - external_redirection, - }; - - Ok(each_group_iterator.flatten().map(Ok).into_input_stream()) - } -} - -struct EachGroupIterator { - block: Arc, - context: Arc, - group_size: usize, - input: InputStream, - external_redirection: ExternalRedirection, -} - -impl Iterator for EachGroupIterator { - type Item = OutputStream; - - fn next(&mut self) -> Option { - let mut group = vec![]; - let mut current_count = 0; - - for next in &mut self.input { - group.push(next); - - current_count += 1; - if current_count >= self.group_size { - break; - } - } - - if group.is_empty() { - return None; - } - - Some(run_block_on_vec( - group, - self.block.clone(), - self.context.clone(), - self.external_redirection, - )) - } -} - -pub(crate) fn run_block_on_vec( - input: Vec, - block: Arc, - context: Arc, - external_redirection: ExternalRedirection, -) -> OutputStream { - let value = Value { - value: UntaggedValue::Table(input), - tag: Tag::unknown(), - }; - - match process_row(block, context, value, external_redirection) { - Ok(s) => { - // We need to handle this differently depending on whether process_row - // returned just 1 value or if it returned multiple as a stream. - let vec = s.collect::>(); - - // If it returned just one value, just take that value - if vec.len() == 1 { - return OutputStream::one( - vec.into_iter() - .next() - .expect("This should be impossible, we just checked that vec.len() == 1."), - ); - } - - // If it returned multiple values, we need to put them into a table and - // return that. - OutputStream::one(UntaggedValue::Table(vec).into_untagged_value()) - } - Err(e) => OutputStream::one(Value::error(e)), - } -} - -#[cfg(test)] -mod tests { - use super::EachGroup; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(EachGroup {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/each/mod.rs b/old_nushell/crates/nu-command/src/commands/filters/each/mod.rs deleted file mode 100644 index cd656685f..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/each/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod command; -pub mod group; -pub mod window; - -pub(crate) use command::make_indexed_item; -pub use command::process_row; -pub use command::Each; -pub use group::EachGroup; -pub use window::EachWindow; diff --git a/old_nushell/crates/nu-command/src/commands/filters/each/window.rs b/old_nushell/crates/nu-command/src/commands/filters/each/window.rs deleted file mode 100644 index e5d855719..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/each/window.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::commands::filters::each::group::run_block_on_vec; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -//use itertools::Itertools; -use nu_errors::ShellError; -use nu_protocol::{hir::CapturedBlock, Primitive, Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -pub struct EachWindow; - -impl WholeStreamCommand for EachWindow { - fn name(&self) -> &str { - "each window" - } - - fn signature(&self) -> Signature { - Signature::build("each window") - .required("window_size", SyntaxShape::Int, "the size of each window") - .named( - "stride", - SyntaxShape::Int, - "the number of rows to slide over between windows", - Some('s'), - ) - .required( - "block", - SyntaxShape::Block, - "the block to run on each group", - ) - } - - fn usage(&self) -> &str { - "Runs a block on sliding windows of `window_size` rows of a table at a time." - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Echo the sum of each window", - example: "echo [1 2 3 4] | each window 2 { echo $it | math sum }", - result: None, - }] - } - - fn run(&self, mut args: CommandArgs) -> Result { - let context = Arc::new(args.context.clone()); - let external_redirection = args.call_info.args.external_redirection; - - let window_size: Tagged = args.req(0)?; - let block: CapturedBlock = args.req(1)?; - let stride: Option> = args.get_flag("stride")?; - - let block = Arc::new(block); - - let mut window: Vec<_> = args - .input - .by_ref() - .take(*window_size - 1) - .collect::>(); - - // `window` must start with dummy values, which will be removed on the first iteration - let stride = stride.map(|x| *x).unwrap_or(1); - window.insert(0, UntaggedValue::Primitive(Primitive::Nothing).into()); - - Ok(args - .input - .enumerate() - .flat_map(move |(i, input)| { - // This would probably be more efficient if `last` was a VecDeque - // But we can't have that because it needs to be put into a Table - window.remove(0); - window.push(input); - - let block = block.clone(); - let context = context.clone(); - let local_window = window.clone(); - - if i % stride == 0 { - Some(run_block_on_vec( - local_window, - block, - context, - external_redirection, - )) - } else { - None - } - }) - .flatten() - .map(Ok) - .into_input_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::EachWindow; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(EachWindow {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/empty.rs b/old_nushell/crates/nu-command/src/commands/filters/empty.rs deleted file mode 100644 index c84fdbad6..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/empty.rs +++ /dev/null @@ -1,238 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, hir::ExternalRedirection, ColumnPath, Primitive, ReturnSuccess, Signature, - SyntaxShape, UntaggedValue, Value, -}; - -use nu_value_ext::{as_string, ValueExt}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "empty?" - } - - fn signature(&self) -> Signature { - Signature::build("empty?") - .rest( - "rest", - SyntaxShape::ColumnPath, - "the names of the columns to check emptiness", - ) - .named( - "block", - SyntaxShape::Block, - "an optional block to replace if empty", - Some('b'), - ) - } - - fn usage(&self) -> &str { - "Check for empty values." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - is_empty(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Check if a value is empty", - example: "echo '' | empty?", - result: Some(vec![UntaggedValue::boolean(true).into()]), - }, - Example { - description: "more than one column", - example: "echo [[meal size]; [arepa small] [taco '']] | empty? meal size", - result: Some( - vec![ - UntaggedValue::row(indexmap! { - "meal".to_string() => Value::from(false), - "size".to_string() => Value::from(false), - }) - .into(), - UntaggedValue::row(indexmap! { - "meal".to_string() => Value::from(false), - "size".to_string() => Value::from(true), - }) - .into(), - ], - ), - },Example { - description: "use a block if setting the empty cell contents is wanted", - example: "echo [[2020/04/16 2020/07/10 2020/11/16]; ['' [27] [37]]] | empty? 2020/04/16 -b { [33 37] }", - result: Some( - vec![ - UntaggedValue::row(indexmap! { - "2020/04/16".to_string() => UntaggedValue::table(&[UntaggedValue::int(33).into(), UntaggedValue::int(37).into()]).into(), - "2020/07/10".to_string() => UntaggedValue::table(&[UntaggedValue::int(27).into()]).into(), - "2020/11/16".to_string() => UntaggedValue::table(&[UntaggedValue::int(37).into()]).into(), - }) - .into(), - ], - ), - }, - ] - } -} - -fn is_empty(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let context = args.context.clone(); - let block: Option = args.get_flag("block")?; - let columns: Vec = args.rest(0)?; - - let input = args.input; - - if input.is_empty() { - let stream = - vec![UntaggedValue::Primitive(Primitive::Nothing).into_value(&tag)].into_iter(); - - return Ok(InputStream::from_stream(stream) - .map(move |input| { - let columns = vec![]; - - match process_row(&context, input, &block, columns) { - Ok(s) => s, - Err(e) => ActionStream::one(Err(e)), - } - }) - .flatten() - .into_action_stream()); - } - - Ok(input - .map(move |input| { - let columns = columns.clone(); - - match process_row(&context, input, &block, columns) { - Ok(s) => s, - Err(e) => ActionStream::one(Err(e)), - } - }) - .flatten() - .into_action_stream()) -} - -fn process_row( - context: &EvaluationContext, - input: Value, - default_block: &Option, - column_paths: Vec, -) -> Result { - let mut out = Arc::new(None); - let results = Arc::make_mut(&mut out); - - if let Some(default_block) = &*default_block { - let for_block = input.clone(); - let input_stream = vec![Ok(for_block)].into_iter().into_input_stream(); - - context.scope.enter_scope(); - context.scope.add_vars(&default_block.captured.entries); - if let Some((arg, _)) = default_block.block.params.positional.first() { - context.scope.add_var(arg.name(), input.clone()); - } - - let stream = run_block( - &default_block.block, - context, - input_stream, - ExternalRedirection::Stdout, - ); - context.scope.exit_scope(); - - let mut stream = stream?; - *results = Some({ - let values = stream.drain_vec(); - - let errors = context.get_errors(); - - if let Some(error) = errors.first() { - return Err(error.clone()); - } - - if values.len() == 1 { - let value = values - .get(0) - .ok_or_else(|| ShellError::unexpected("No value."))?; - - Value { - value: value.value.clone(), - tag: input.tag.clone(), - } - } else if values.is_empty() { - UntaggedValue::nothing().into_value(&input.tag) - } else { - UntaggedValue::table(&values).into_value(&input.tag) - } - }); - } - - match input { - Value { - value: UntaggedValue::Row(ref r), - ref tag, - } => { - if column_paths.is_empty() { - Ok(ActionStream::one(ReturnSuccess::value({ - let is_empty = input.is_empty(); - - if default_block.is_some() { - if is_empty { - results - .clone() - .unwrap_or_else(|| UntaggedValue::boolean(true).into_value(tag)) - } else { - input.clone() - } - } else { - UntaggedValue::boolean(is_empty).into_value(tag) - } - }))) - } else { - let mut obj = input.clone(); - - for column in column_paths { - let path = UntaggedValue::Primitive(Primitive::ColumnPath(column.clone())) - .into_value(tag); - let data = r.get_data(&as_string(&path)?).borrow().clone(); - let is_empty = data.is_empty(); - - let default = if default_block.is_some() { - if is_empty { - results - .clone() - .unwrap_or_else(|| UntaggedValue::boolean(true).into_value(tag)) - } else { - data.clone() - } - } else { - UntaggedValue::boolean(is_empty).into_value(tag) - }; - - if let Ok(value) = - obj.swap_data_by_column_path(&column, Box::new(move |_| Ok(default))) - { - obj = value; - } - } - - Ok(ActionStream::one(ReturnSuccess::value(obj))) - } - } - other => Ok(ActionStream::one(ReturnSuccess::value({ - if other.is_empty() { - results - .clone() - .unwrap_or_else(|| UntaggedValue::boolean(true).into_value(other.tag)) - } else { - UntaggedValue::boolean(false).into_value(other.tag) - } - }))), - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/every.rs b/old_nushell/crates/nu-command/src/commands/filters/every.rs deleted file mode 100644 index aeac25e23..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/every.rs +++ /dev/null @@ -1,89 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; - -pub struct Every; - -impl WholeStreamCommand for Every { - fn name(&self) -> &str { - "every" - } - - fn signature(&self) -> Signature { - Signature::build(self.name()) - .required( - "stride", - SyntaxShape::Int, - "how many rows to skip between (and including) each row returned", - ) - .switch( - "skip", - "skip the rows that would be returned, instead of selecting them", - Some('s'), - ) - } - - fn usage(&self) -> &str { - "Show (or skip) every n-th row, starting from the first one." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - every(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get every second row", - example: "echo [1 2 3 4 5] | every 2", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(5).into(), - ]), - }, - Example { - description: "Skip every second row", - example: "echo [1 2 3 4 5] | every 2 --skip", - result: Some(vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(4).into(), - ]), - }, - ] - } -} - -fn every(args: CommandArgs) -> Result { - let stride: u64 = args.req(0)?; - let skip: bool = args.has_flag("skip"); - let input = args.input; - - Ok(input - .enumerate() - .filter_map(move |(i, value)| { - let stride_desired = if stride < 1 { 1 } else { stride } as usize; - let should_include = skip == (i % stride_desired != 0); - - if should_include { - Some(ReturnSuccess::value(value)) - } else { - None - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Every; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Every {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/first.rs b/old_nushell/crates/nu-command/src/commands/filters/first.rs deleted file mode 100644 index c592fda64..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/first.rs +++ /dev/null @@ -1,152 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -pub struct First; - -impl WholeStreamCommand for First { - fn name(&self) -> &str { - "first" - } - - fn signature(&self) -> Signature { - Signature::build("first").optional( - "rows", - SyntaxShape::Int, - "starting from the front, the number of rows to return", - ) - } - - fn usage(&self) -> &str { - "Show only the first number of rows." - } - - fn run(&self, args: CommandArgs) -> Result { - first(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Return the first item of a list/table", - example: "echo [1 2 3] | first", - result: Some(vec![UntaggedValue::int(1).into()]), - }, - Example { - description: "Return the first 2 items of a list/table", - example: "echo [1 2 3] | first 2", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - ]), - }, - ] - } -} - -fn first(args: CommandArgs) -> Result { - let rows: Option> = args.opt(0)?; - let tag = args.call_info.name_tag; - - let mut rows_desired = if let Some(quantity) = rows { - *quantity - } else { - 1 - }; - - let mut input_peek = args.input.peekable(); - match &mut input_peek.next_if(|val| val.is_binary()) { - Some(v) => match &v.value { - // We already know it's a binary so we don't have to match - // on the type of primitive - UntaggedValue::Primitive(_) => { - let bytes = match v.as_binary_vec() { - Ok(b) => b, - _ => { - return Err(ShellError::labeled_error( - "error converting data as_binary_vec", - "error conversion", - tag, - )) - } - }; - // if the current 8192 chunk fits inside our rows_desired - // carve it up and return it - if bytes.len() >= rows_desired { - // We only want to see a certain amount of the binary - // so let's grab those parts - let output_bytes = bytes[0..rows_desired].to_vec(); - Ok(OutputStream::one(UntaggedValue::binary(output_bytes))) - } else { - // if we want more rows that the current chunk size (8192) - // we must gradually get bigger chunks while testing - // if it's within the requested rows_desired size - let mut bigger: Vec = vec![]; - bigger.extend(bytes); - while bigger.len() < rows_desired { - match input_peek.next() { - Some(data) => match data.value.into_value(&tag).as_binary_vec() { - Ok(bits) => bigger.extend(bits), - _ => { - return Err(ShellError::labeled_error( - "error converting data as_binary_vec", - "error conversion", - tag, - )) - } - }, - _ => { - // We're at the end of our data so let's break out of this loop - // and set the rows_desired to the size of our data - rows_desired = bigger.len(); - break; - } - } - } - let output_bytes = bigger[0..rows_desired].to_vec(); - Ok(OutputStream::one(UntaggedValue::binary(output_bytes))) - } - } - UntaggedValue::Row(_) => Ok(input_peek.take(rows_desired).into_output_stream()), - UntaggedValue::Table(_) => Err(ShellError::labeled_error( - "unsure how to handle UntaggedValue::Table", - "found table", - tag, - )), - UntaggedValue::Error(_) => Err(ShellError::labeled_error( - "unsure how to handle UntaggedValue::Error", - "found error", - tag, - )), - UntaggedValue::Block(_) => Err(ShellError::labeled_error( - "unsure how to handled UntaggedValue::Block", - "found block", - tag, - )), - #[cfg(all(not(target_arch = "wasm32"), feature = "dataframe"))] - UntaggedValue::DataFrame(_) | UntaggedValue::FrameStruct(_) => { - Err(ShellError::labeled_error( - "unsure how to handled dataframe struct", - "found dataframe", - tag, - )) - } - }, - None => Ok(input_peek.take(rows_desired).into_output_stream()), - } -} - -#[cfg(test)] -mod tests { - use super::First; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(First {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/flatten.rs b/old_nushell/crates/nu-command/src/commands/filters/flatten.rs deleted file mode 100644 index fef4b5153..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/flatten.rs +++ /dev/null @@ -1,179 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - Dictionary, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, -}; -use nu_source::Tagged; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "flatten" - } - - fn signature(&self) -> Signature { - Signature::build("flatten").rest( - "rest", - SyntaxShape::String, - "optionally flatten data by column", - ) - } - - fn usage(&self) -> &str { - "Flatten the table." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - flatten(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "flatten a table", - example: "echo [[N, u, s, h, e, l, l]] | flatten | first", - result: Some(vec![Value::from("N")]), - }, - Example { - description: "flatten a column having a nested table", - example: "echo [[origin, people]; [Ecuador, (echo [[name, meal]; ['Andres', 'arepa']])]] | flatten | get meal", - result: Some(vec![Value::from("arepa")]), - }, - Example { - description: "restrict the flattening by passing column names", - example: "echo [[origin, crate, versions]; [World, (echo [[name]; ['nu-cli']]), ['0.21', '0.22']]] | flatten versions | last | get versions", - result: Some(vec![Value::from("0.22")]), - } - ] - } -} - -fn flatten(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let columns: Vec> = args.rest(0)?; - let input = args.input; - - Ok(input - .flat_map(move |item| flat_value(&columns, &item, &tag)) - .into_action_stream()) -} - -enum TableInside<'a> { - Entries(&'a str, &'a Tag, Vec<&'a Value>), -} - -fn flat_value( - columns: &[Tagged], - item: &Value, - name_tag: impl Into, -) -> Vec> { - let tag = item.tag.clone(); - let name_tag = name_tag.into(); - - let res = { - if item.is_row() { - let mut out = TaggedDictBuilder::new(tag); - let mut a_table = None; - let mut tables_explicitly_flattened = 0; - - for (column, value) in item.row_entries() { - let column_requested = columns.iter().find(|c| c.item == *column); - - if let Value { - value: UntaggedValue::Row(Dictionary { entries: mapa }), - .. - } = value - { - if column_requested.is_none() && !columns.is_empty() { - if out.contains_key(column) { - out.insert_value(format!("{}_{}", column, column), value.clone()); - } else { - out.insert_value(column, value.clone()); - } - continue; - } - - for (k, v) in mapa { - if out.contains_key(k) { - out.insert_value(format!("{}_{}", column, k), v.clone()); - } else { - out.insert_value(k, v.clone()); - } - } - } else if value.is_table() { - if tables_explicitly_flattened >= 1 && column_requested.is_some() { - let attempted = if let Some(name) = column_requested { - name.span() - } else { - name_tag.span - }; - - let already_flattened = - if let Some(TableInside::Entries(_, column_tag, _)) = a_table { - column_tag.span - } else { - name_tag.span - }; - - return vec![ReturnSuccess::value( - UntaggedValue::Error(ShellError::labeled_error_with_secondary( - "can only flatten one inner table at the same time", - "tried flattening more than one column with inner tables", - attempted, - "...but is flattened already", - already_flattened, - )) - .into_value(name_tag), - )]; - } - - if !columns.is_empty() { - if let Some(requested) = column_requested { - a_table = Some(TableInside::Entries( - &requested.item, - &requested.tag, - value.table_entries().collect(), - )); - - tables_explicitly_flattened += 1; - } else { - out.insert_value(column, value.clone()); - } - } else if a_table.is_none() { - a_table = Some(TableInside::Entries( - column, - &value.tag, - value.table_entries().collect(), - )) - } else { - out.insert_value(column, value.clone()); - } - } else { - out.insert_value(column, value.clone()); - } - } - - let mut expanded = vec![]; - - if let Some(TableInside::Entries(column, _, entries)) = a_table { - for entry in entries { - let mut base = out.clone(); - base.insert_value(column, entry.clone()); - expanded.push(base.into_value()); - } - } else { - expanded.push(out.into_value()); - } - - expanded - } else if item.is_table() { - item.table_entries().cloned().collect() - } else { - vec![item.clone()] - } - }; - - res.into_iter().map(ReturnSuccess::value).collect() -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/get.rs b/old_nushell/crates/nu-command/src/commands/filters/get.rs deleted file mode 100644 index 3926bcbb6..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/get.rs +++ /dev/null @@ -1,252 +0,0 @@ -use crate::prelude::*; -use indexmap::set::IndexSet; -use log::trace; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - did_you_mean, ColumnPath, Dictionary, PathMember, Primitive, ReturnSuccess, Signature, - SyntaxShape, UnspannedPathMember, UntaggedValue, Value, -}; -use nu_source::HasFallibleSpan; -use nu_value_ext::get_data_by_column_path; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "get" - } - - fn signature(&self) -> Signature { - Signature::build("get").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally return additional data by path", - ) - } - - fn usage(&self) -> &str { - "Open given cells as text." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - get(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Extract the name of files as a list", - example: "ls | get name", - result: None, - }, - Example { - description: "Extract the cpu list from the sys information", - example: "sys | get cpu", - result: None, - }, - ] - } -} - -pub fn get(args: CommandArgs) -> Result { - let column_paths: Vec = args.rest(0)?; - let mut input = args.input; - - if column_paths.is_empty() { - let vec = input.drain_vec(); - - let descs = nu_protocol::merge_descriptors(&vec); - - Ok(descs - .into_iter() - .map(ReturnSuccess::value) - .into_action_stream()) - } else { - trace!("get {:?}", column_paths); - let output_stream = input - .flat_map(move |item| { - column_paths - .iter() - .flat_map(move |path| get_output(&item, path)) - .collect::>() - }) - .into_action_stream(); - Ok(output_stream) - } -} - -fn get_output(item: &Value, path: &ColumnPath) -> Vec> { - match get_column_path(path, item) { - Ok(Value { - value: UntaggedValue::Primitive(Primitive::Nothing), - .. - }) => vec![], - Ok(Value { - value: UntaggedValue::Table(rows), - .. - }) => rows.into_iter().map(ReturnSuccess::value).collect(), - Ok(other) => vec![ReturnSuccess::value(other)], - Err(reason) => vec![ReturnSuccess::value( - UntaggedValue::Error(reason).into_untagged_value(), - )], - } -} - -pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result { - get_data_by_column_path(obj, path, move |obj_source, column_path_tried, error| { - let path_members_span = path.maybe_span().unwrap_or_else(Span::unknown); - - match &obj_source.value { - UntaggedValue::Table(rows) => { - return get_column_path_from_table_error( - rows, - column_path_tried, - &path_members_span, - ); - } - UntaggedValue::Row(columns) => { - if let Some(error) = get_column_from_row_error( - columns, - column_path_tried, - &path_members_span, - obj_source, - ) { - return error; - } - } - _ => {} - } - - if let Some(suggestions) = did_you_mean(obj_source, column_path_tried.as_string()) { - ShellError::labeled_error( - "Unknown column", - format!("did you mean '{}'?", suggestions[0]), - column_path_tried.span.since(path_members_span), - ) - } else { - error - } - }) -} - -pub fn get_column_path_from_table_error( - rows: &[Value], - column_path_tried: &PathMember, - path_members_span: &Span, -) -> ShellError { - match column_path_tried { - PathMember { - unspanned: UnspannedPathMember::String(column), - .. - } => { - let primary_label = format!("There isn't a column named '{}'", &column); - - let suggestions: IndexSet<_> = rows - .iter() - .filter_map(|r| did_you_mean(r, column_path_tried.as_string())) - .map(|s| s[0].to_owned()) - .collect(); - let mut existing_columns: IndexSet<_> = IndexSet::default(); - let mut names: Vec = vec![]; - - for row in rows { - for field in row.data_descriptors() { - if !existing_columns.contains(&field[..]) { - existing_columns.insert(field.clone()); - names.push(field); - } - } - } - - if names.is_empty() { - ShellError::labeled_error_with_secondary( - "Unknown column", - primary_label, - column_path_tried.span, - "Appears to contain rows. Try indexing instead.", - column_path_tried.span.since(path_members_span), - ) - } else { - ShellError::labeled_error_with_secondary( - "Unknown column", - primary_label, - column_path_tried.span, - format!( - "Perhaps you meant '{}'? Columns available: {}", - suggestions - .iter() - .map(|x| x.to_owned()) - .collect::>() - .join(","), - names.join(", ") - ), - column_path_tried.span.since(path_members_span), - ) - } - } - PathMember { - unspanned: UnspannedPathMember::Int(idx), - .. - } => { - let total = rows.len(); - - let secondary_label = if total == 1 { - "The table only has 1 row".to_owned() - } else { - format!("The table only has {} rows (0 to {})", total, total - 1) - }; - - ShellError::labeled_error_with_secondary( - "Row not found", - format!("There isn't a row indexed at {}", idx), - column_path_tried.span, - secondary_label, - column_path_tried.span.since(path_members_span), - ) - } - } -} - -pub fn get_column_from_row_error( - columns: &Dictionary, - column_path_tried: &PathMember, - path_members_span: &Span, - obj_source: &Value, -) -> Option { - match column_path_tried { - PathMember { - unspanned: UnspannedPathMember::String(column), - .. - } => { - let primary_label = format!("There isn't a column named '{}'", &column); - - did_you_mean(obj_source, column_path_tried.as_string()).map(|suggestions| { - ShellError::labeled_error_with_secondary( - "Unknown column", - primary_label, - column_path_tried.span, - format!( - "Perhaps you meant '{}'? Columns available: {}", - suggestions[0], - &obj_source.data_descriptors().join(", ") - ), - column_path_tried.span.since(path_members_span), - ) - }) - } - PathMember { - unspanned: UnspannedPathMember::Int(idx), - .. - } => Some(ShellError::labeled_error_with_secondary( - "No rows available", - format!("A row at '{}' can't be indexed.", &idx), - column_path_tried.span, - format!( - "Appears to contain columns. Columns available: {}", - columns.keys().join(", ") - ), - column_path_tried.span.since(path_members_span), - )), - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/group_by.rs b/old_nushell/crates/nu-command/src/commands/filters/group_by.rs deleted file mode 100644 index c764d7b09..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/group_by.rs +++ /dev/null @@ -1,325 +0,0 @@ -use crate::prelude::*; -use crate::utils::suggestions::suggestions; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::hir::ExternalRedirection; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use nu_value_ext::as_string; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "group-by" - } - - fn signature(&self) -> Signature { - Signature::build("group-by").optional( - "grouper", - SyntaxShape::Any, - "the grouper value to use", - ) - } - - fn usage(&self) -> &str { - "Create a new table grouped." - } - - fn run(&self, args: CommandArgs) -> Result { - group_by(args) - } - - #[allow(clippy::unwrap_used)] - fn examples(&self) -> Vec { - use nu_data::value::date_naive_from_str as date; - - vec![ - Example { - description: "group items by column named \"type\"", - example: r#"ls | group-by type"#, - result: Some(vec![UntaggedValue::row(indexmap! { - "File".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::string("Andres.txt").into(), - "type".to_string() => UntaggedValue::string("File").into(), - "chickens".to_string() => UntaggedValue::int(10).into(), - "modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(), - }).into(), - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::string("Darren.txt").into(), - "type".to_string() => UntaggedValue::string("File").into(), - "chickens".to_string() => UntaggedValue::int(20).into(), - "modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(), - }).into(), - ]).into(), - "Dir".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::string("Jonathan").into(), - "type".to_string() => UntaggedValue::string("Dir").into(), - "chickens".to_string() => UntaggedValue::int(5).into(), - "modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(), - }).into(), - UntaggedValue::row(indexmap! { - "name".to_string() => UntaggedValue::string("Yehuda").into(), - "type".to_string() => UntaggedValue::string("Dir").into(), - "chickens".to_string() => UntaggedValue::int(4).into(), - "modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(), - }).into(), - ]).into(), - }) - .into()]), - }, - Example { - description: "you can also group by raw values by leaving out the argument", - example: "echo [1 3 1 3 2 1 1] | group-by", - result: Some(vec![UntaggedValue::row(indexmap! { - "1".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - ]).into(), - - "3".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::int(3).into(), - UntaggedValue::int(3).into(), - ]).into(), - - "2".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::int(2).into(), - ]).into(), - }) - .into()]), - }, - Example { - description: - "use the block form to generate a grouping key when each row gets processed", - example: "echo [1 3 1 3 2 1 1] | group-by { ($it - 1) mod 3 }", - result: Some(vec![UntaggedValue::row(indexmap! { - "0".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(1).into(), - - ]).into(), - "2".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::int(3).into(), - UntaggedValue::int(3).into(), - ]).into(), - "1".to_string() => UntaggedValue::Table(vec![ - UntaggedValue::int(2).into(), - ]).into(), - }) - .into()]), - }, - ] - } -} - -enum Grouper { - ByColumn(Option>), - ByBlock, -} - -pub fn group_by(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let context = Arc::new(args.context.clone()); - - let grouper = args.opt(0)?; - let values: Vec = args.input.collect(); - let mut keys: Vec> = vec![]; - let mut group_strategy = Grouper::ByColumn(None); - - match grouper { - Some(Value { - value: UntaggedValue::Block(block_given), - .. - }) => { - let block = Arc::new(*block_given); - let error_key = "error"; - - for value in &values { - let run = block.clone(); - let context = context.clone(); - - match crate::commands::filters::each::process_row( - run, - context, - value.clone(), - ExternalRedirection::Stdout, - ) { - Ok(mut s) => { - let collection: Vec = s.drain_vec(); - - if collection.len() > 1 { - return Err(ShellError::labeled_error( - "expected one value from the block", - "requires a table with one value for grouping", - &name, - )); - } - - let value = match collection.get(0) { - Some(Value { - value: UntaggedValue::Error(_), - .. - }) - | None => UntaggedValue::string(error_key).into_value(&name), - Some(return_value) => return_value.clone(), - }; - - keys.push(as_string(&value)); - } - Err(_) => { - keys.push(Ok(error_key.into())); - } - } - } - - group_strategy = Grouper::ByBlock; - } - Some(other) => { - group_strategy = Grouper::ByColumn(Some(as_string(&other)?.tagged(&name))); - } - _ => {} - } - - if values.is_empty() { - return Err(ShellError::labeled_error( - "expected table from pipeline", - "requires a table input", - name, - )); - } - - let first = values[0].clone(); - - let name = if first.tag.anchor().is_some() { - first.tag - } else { - name - }; - - let values = UntaggedValue::table(&values).into_value(&name); - - let group_value = match group_strategy { - Grouper::ByBlock => { - let map = keys; - - let block = Box::new(move |idx: usize, row: &Value| match map.get(idx) { - Some(Ok(key)) => Ok(key.clone()), - Some(Err(reason)) => Err(reason.clone()), - None => as_string(row), - }); - - nu_data::utils::group(&values, &Some(block), name) - } - Grouper::ByColumn(column_name) => group(&column_name, &values, &name), - }; - - Ok(OutputStream::one(group_value?)) -} - -pub fn group( - column_name: &Option>, - values: &Value, - tag: impl Into, -) -> Result { - let name = tag.into(); - - let grouper = if let Some(column_name) = column_name { - Grouper::ByColumn(Some(column_name.clone())) - } else { - Grouper::ByColumn(None) - }; - - match grouper { - Grouper::ByColumn(Some(column_name)) => { - let block = Box::new(move |_, row: &Value| { - match row.get_data_by_key(column_name.borrow_spanned()) { - Some(group_key) => Ok(as_string(&group_key)?), - None => Err(suggestions(column_name.borrow_tagged(), row)), - } - }); - - nu_data::utils::group(values, &Some(block), &name) - } - Grouper::ByColumn(None) => { - let block = Box::new(move |_, row: &Value| as_string(row)); - - nu_data::utils::group(values, &Some(block), &name) - } - Grouper::ByBlock => Err(ShellError::unimplemented( - "Block not implemented: This should never happen.", - )), - } -} - -#[cfg(test)] -mod tests { - use super::group; - use nu_data::utils::helpers::committers; - use nu_errors::ShellError; - use nu_source::*; - use nu_test_support::value::{date, int, row, string, table}; - - #[test] - fn groups_table_by_date_column() -> Result<(), ShellError> { - let for_key = Some(String::from("date").tagged_unknown()); - let sample = table(&committers()); - - assert_eq!( - group(&for_key, &sample, Tag::unknown())?, - row(indexmap! { - "2019-07-23".into() => table(&[ - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-07-23"), "chickens".into() => int(10) }), - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-07-23"), "chickens".into() => int(5) }), - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-07-23"), "chickens".into() => int(2) }) - ]), - "2019-10-10".into() => table(&[ - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-10-10"), "chickens".into() => int(6) }), - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-10-10"), "chickens".into() => int(15) }), - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-10-10"), "chickens".into() => int(30) }) - ]), - "2019-09-24".into() => table(&[ - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-09-24"), "chickens".into() => int(20) }), - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-09-24"), "chickens".into() => int(4) }), - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-09-24"), "chickens".into() => int(10) }) - ]), - }) - ); - - Ok(()) - } - - #[test] - fn groups_table_by_country_column() -> Result<(), ShellError> { - let for_key = Some(String::from("country").tagged_unknown()); - let sample = table(&committers()); - - assert_eq!( - group(&for_key, &sample, Tag::unknown())?, - row(indexmap! { - "EC".into() => table(&[ - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-07-23"), "chickens".into() => int(10) }), - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-09-24"), "chickens".into() => int(20) }), - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-10-10"), "chickens".into() => int(30) }) - ]), - "NZ".into() => table(&[ - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-07-23"), "chickens".into() => int(5) }), - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-10-10"), "chickens".into() => int(15) }), - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-09-24"), "chickens".into() => int(10) }) - ]), - "US".into() => table(&[ - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-10-10"), "chickens".into() => int(6) }), - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-09-24"), "chickens".into() => int(4) }), - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-07-23"), "chickens".into() => int(2) }), - ]), - }) - ); - - Ok(()) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/group_by_date.rs b/old_nushell/crates/nu-command/src/commands/filters/group_by_date.rs deleted file mode 100644 index 3787f3f1d..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/group_by_date.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::prelude::*; -use crate::utils::suggestions::suggestions; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct GroupByDate; - -impl WholeStreamCommand for GroupByDate { - fn name(&self) -> &str { - "group-by date" - } - - fn signature(&self) -> Signature { - Signature::build("group-by date") - .optional( - "column_name", - SyntaxShape::String, - "the name of the column to group by", - ) - .named( - "format", - SyntaxShape::String, - "Specify date and time formatting", - Some('f'), - ) - } - - fn usage(&self) -> &str { - "creates a table grouped by date." - } - - fn run(&self, args: CommandArgs) -> Result { - group_by_date(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Group files by type", - example: "ls | group-by date --format '%d/%m/%Y'", - result: None, - }] - } -} - -enum Grouper { - ByDate(Option>), -} - -enum GroupByColumn { - Name(Option>), -} - -pub fn group_by_date(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let column_name: Option> = args.opt(0)?; - let format: Option> = args.get_flag("format")?; - - let values: Vec = args.input.collect(); - - if values.is_empty() { - Err(ShellError::labeled_error( - "Expected table from pipeline", - "requires a table input", - name, - )) - } else { - let values = UntaggedValue::table(&values).into_value(&name); - - let grouper_column = if let Some(column_name) = column_name { - GroupByColumn::Name(Some(column_name)) - } else { - GroupByColumn::Name(None) - }; - - let grouper_date = if let Some(date_format) = format { - Grouper::ByDate(Some(date_format)) - } else { - Grouper::ByDate(None) - }; - - let value_result = match (grouper_date, grouper_column) { - (Grouper::ByDate(None), GroupByColumn::Name(None)) => { - let block = Box::new(move |_, row: &Value| row.format("%Y-%m-%d")); - - nu_data::utils::group(&values, &Some(block), &name) - } - (Grouper::ByDate(None), GroupByColumn::Name(Some(column_name))) => { - let block = Box::new(move |_, row: &Value| { - let group_key = row - .get_data_by_key(column_name.borrow_spanned()) - .ok_or_else(|| suggestions(column_name.borrow_tagged(), row)); - - group_key?.format("%Y-%m-%d") - }); - - nu_data::utils::group(&values, &Some(block), &name) - } - (Grouper::ByDate(Some(fmt)), GroupByColumn::Name(None)) => { - let block = Box::new(move |_, row: &Value| row.format(&fmt)); - - nu_data::utils::group(&values, &Some(block), &name) - } - (Grouper::ByDate(Some(fmt)), GroupByColumn::Name(Some(column_name))) => { - let block = Box::new(move |_, row: &Value| { - let group_key = row - .get_data_by_key(column_name.borrow_spanned()) - .ok_or_else(|| suggestions(column_name.borrow_tagged(), row)); - - group_key?.format(&fmt) - }); - - nu_data::utils::group(&values, &Some(block), &name) - } - }; - - Ok(OutputStream::one(value_result?)) - } -} - -#[cfg(test)] -mod tests { - use super::GroupByDate; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(GroupByDate {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/headers.rs b/old_nushell/crates/nu-command/src/commands/filters/headers.rs deleted file mode 100644 index 85368173f..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/headers.rs +++ /dev/null @@ -1,119 +0,0 @@ -use crate::prelude::*; - -use indexmap::IndexMap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::Dictionary; -use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; - -pub struct Headers; - -impl WholeStreamCommand for Headers { - fn name(&self) -> &str { - "headers" - } - - fn signature(&self) -> Signature { - Signature::build("headers") - } - - fn usage(&self) -> &str { - "Use the first row of the table as column names." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - headers(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Create headers from a raw string", - example: r#"echo "a b c|1 2 3" | split row "|" | split column " " | headers"#, - result: None, - }, - Example { - description: "Don't panic on rows with different headers", - example: r#"echo "a b c|1 2 3|1 2 3 4" | split row "|" | split column " " | headers"#, - result: None, - }, - ] - } -} - -pub fn headers(args: CommandArgs) -> Result { - let input = args.input; - let rows: Vec = input.collect(); - - if rows.is_empty() { - return Err(ShellError::untagged_runtime_error( - "Couldn't find headers, was the input a properly formatted, non-empty table?", - )); - } - - //the headers are the first row in the table - let headers: Vec = match &rows[0].value { - UntaggedValue::Row(d) => { - Ok(d.entries - .iter() - .map(|(k, v)| { - match v.as_string() { - Ok(s) => s, - Err(_) => { - //If a cell that should contain a header name is empty, we name the column Column[index] - match d.entries.get_full(k) { - Some((index, _, _)) => format!("Column{}", index), - None => "unknownColumn".to_string(), - } - } - } - }) - .collect()) - } - _ => Err(ShellError::unexpected_eof( - "Could not get headers, is the table empty?", - rows[0].tag.span, - )), - }?; - - Ok(rows - .into_iter() - .skip(1) - .map(move |r| { - //Each row is a dictionary with the headers as keys - match &r.value { - UntaggedValue::Row(d) => { - let mut entries = IndexMap::new(); - for (i, header) in headers.iter().enumerate() { - let value = match d.entries.get_index(i) { - Some((_, value)) => value.clone(), - None => UntaggedValue::Primitive(Primitive::Nothing).into(), - }; - - entries.insert(header.clone(), value); - } - Ok(ReturnSuccess::Value( - UntaggedValue::Row(Dictionary { entries }).into_value(r.tag.clone()), - )) - } - _ => Err(ShellError::unexpected_eof( - "Couldn't iterate through rows, was the input a properly formatted table?", - r.tag.span, - )), - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Headers; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Headers {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/insert.rs b/old_nushell/crates/nu-command/src/commands/filters/insert.rs deleted file mode 100644 index d3399bb18..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/insert.rs +++ /dev/null @@ -1,174 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::hir::ExternalRedirection; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_value_ext::ValueExt; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "insert" - } - - fn signature(&self) -> Signature { - Signature::build("insert") - .required( - "column", - SyntaxShape::ColumnPath, - "the column name to insert", - ) - .required("value", SyntaxShape::Any, "the value to give the cell(s)") - } - - fn usage(&self) -> &str { - "Insert a new column with a given value." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - insert(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Insert a column with a value", - example: "echo [[author, commits]; ['Andrés', 1]] | insert branches 5", - result: Some(vec![UntaggedValue::row(indexmap! { - "author".to_string() => Value::from("Andrés"), - "commits".to_string() => UntaggedValue::int(1).into(), - "branches".to_string() => UntaggedValue::int(5).into(), - }) - .into()]), - },Example { - description: "Use in block form for more involved insertion logic", - example: "echo [[author, lucky_number]; ['Yehuda', 4]] | insert success { $it.lucky_number * 10 }", - result: Some(vec![UntaggedValue::row(indexmap! { - "author".to_string() => Value::from("Yehuda"), - "lucky_number".to_string() => UntaggedValue::int(4).into(), - "success".to_string() => UntaggedValue::int(40).into(), - }) - .into()]), - }] - } -} - -fn process_row( - context: Arc, - input: Value, - mut value: Arc, - field: Arc, -) -> Result { - let value = Arc::make_mut(&mut value); - - Ok(match value { - Value { - value: UntaggedValue::Block(block), - tag: block_tag, - } => { - let for_block = input.clone(); - let input_stream = vec![Ok(for_block)].into_iter().into_input_stream(); - - context.scope.enter_scope(); - context.scope.add_vars(&block.captured.entries); - if let Some((arg, _)) = block.block.params.positional.first() { - context.scope.add_var(arg.name(), input.clone()); - } - - let result = run_block( - &block.block, - &context, - input_stream, - ExternalRedirection::Stdout, - ); - - context.scope.exit_scope(); - - match result { - Ok(mut stream) => { - let values = stream.drain_vec(); - - let errors = context.get_errors(); - if let Some(error) = errors.first() { - return Err(error.clone()); - } - - let result = if values.len() == 1 { - let value = values - .get(0) - .ok_or_else(|| ShellError::unexpected("No value to insert with."))?; - - Value { - value: value.value.clone(), - tag: input.tag.clone(), - } - } else if values.is_empty() { - UntaggedValue::nothing().into_value(&input.tag) - } else { - UntaggedValue::table(&values).into_value(&input.tag) - }; - - match input { - obj @ Value { - value: UntaggedValue::Row(_), - .. - } => match obj.insert_data_at_column_path(&field, result) { - Ok(v) => ActionStream::one(ReturnSuccess::value(v)), - Err(e) => ActionStream::one(Err(e)), - }, - _ => ActionStream::one(Err(ShellError::labeled_error( - "Unrecognized type in stream", - "original value", - block_tag.clone(), - ))), - } - } - Err(e) => ActionStream::one(Err(e)), - } - } - value => match input { - Value { - value: UntaggedValue::Primitive(Primitive::Nothing), - .. - } => match context - .scope - .get_var("$it") - .unwrap_or_else(|| UntaggedValue::nothing().into_untagged_value()) - .insert_data_at_column_path(&field, value.clone()) - { - Ok(v) => ActionStream::one(ReturnSuccess::value(v)), - Err(e) => ActionStream::one(Err(e)), - }, - _ => match input.insert_data_at_column_path(&field, value.clone()) { - Ok(v) => ActionStream::one(ReturnSuccess::value(v)), - Err(e) => ActionStream::one(Err(e)), - }, - }, - }) -} - -fn insert(args: CommandArgs) -> Result { - let context = Arc::new(args.context.clone()); - let column: ColumnPath = args.req(0)?; - let value: Value = args.req(1)?; - let input = args.input; - - let value = Arc::new(value); - let column = Arc::new(column); - - Ok(input - .flat_map(move |input| { - let context = context.clone(); - let value = value.clone(); - let column = column.clone(); - - match process_row(context, input, value, column) { - Ok(s) => s, - Err(e) => ActionStream::one(Err(e)), - } - }) - .into_action_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/keep/command.rs b/old_nushell/crates/nu-command/src/commands/filters/keep/command.rs deleted file mode 100644 index 9d0a9bc69..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/keep/command.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "keep" - } - - fn signature(&self) -> Signature { - Signature::build("keep").optional( - "rows", - SyntaxShape::Int, - "Starting from the front, the number of rows to keep", - ) - } - - fn usage(&self) -> &str { - "Keep the number of rows only." - } - - fn run(&self, args: CommandArgs) -> Result { - keep(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Keep the first row", - example: "echo [1 2 3] | keep", - result: Some(vec![UntaggedValue::int(1).into()]), - }, - Example { - description: "Keep the first four rows", - example: "echo [1 2 3 4 5] | keep 4", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ]), - }, - ] - } -} - -fn keep(args: CommandArgs) -> Result { - let rows: Option> = args.opt(0)?; - - let rows_desired = if let Some(quantity) = rows { - *quantity - } else { - 1 - }; - - Ok(args.input.take(rows_desired).into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/keep/mod.rs b/old_nushell/crates/nu-command/src/commands/filters/keep/mod.rs deleted file mode 100644 index 56051b6de..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/keep/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod command; -mod until; -mod while_; - -pub use command::Command as Keep; -pub use until::SubCommand as KeepUntil; -pub use while_::SubCommand as KeepWhile; diff --git a/old_nushell/crates/nu-command/src/commands/filters/keep/until.rs b/old_nushell/crates/nu-command/src/commands/filters/keep/until.rs deleted file mode 100644 index e5e9d3aa9..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/keep/until.rs +++ /dev/null @@ -1,97 +0,0 @@ -use crate::prelude::*; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_parser::ParserScope; -use nu_protocol::{ - hir::{CapturedBlock, ClassifiedCommand}, - Signature, SyntaxShape, -}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "keep until" - } - - fn signature(&self) -> Signature { - Signature::build("keep until") - .required( - "condition", - SyntaxShape::RowCondition, - "The condition that must be met to stop keeping rows", - ) - .filter() - } - - fn usage(&self) -> &str { - "Keeps rows until the condition matches." - } - - fn run(&self, args: CommandArgs) -> Result { - let ctx = Arc::new(args.context.clone()); - let tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - let condition = { - if block.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - } - }; - - Ok(args - .input - .take_while(move |item| { - let condition = condition.clone(); - let ctx = ctx.clone(); - ctx.scope.enter_scope(); - ctx.scope.add_vars(&block.captured.entries); - if let Some((arg, _)) = block.block.params.positional.first() { - ctx.scope.add_var(arg.name(), item.clone()); - } - - let result = evaluate_baseline_expr(&condition, &ctx); - ctx.scope.exit_scope(); - - !matches!(result, Ok(ref v) if v.is_true()) - }) - .into_output_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/keep/while_.rs b/old_nushell/crates/nu-command/src/commands/filters/keep/while_.rs deleted file mode 100644 index ad4f98def..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/keep/while_.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::prelude::*; -use log::trace; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ClassifiedCommand}, - Signature, SyntaxShape, -}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "keep while" - } - - fn signature(&self) -> Signature { - Signature::build("keep while") - .required( - "condition", - SyntaxShape::RowCondition, - "The condition that must be met to keep rows", - ) - .filter() - } - - fn usage(&self) -> &str { - "Keeps rows while the condition matches." - } - - fn run(&self, args: CommandArgs) -> Result { - let ctx = Arc::new(args.context.clone()); - let tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - let condition = { - if block.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - } - }; - - Ok(args - .input - .take_while(move |item| { - let condition = condition.clone(); - let ctx = ctx.clone(); - - ctx.scope.enter_scope(); - ctx.scope.add_vars(&block.captured.entries); - if let Some((arg, _)) = block.block.params.positional.first() { - ctx.scope.add_var(arg.name(), item.clone()); - } - trace!("ITEM = {:?}", item); - - let result = evaluate_baseline_expr(&condition, &ctx); - ctx.scope.exit_scope(); - trace!("RESULT = {:?}", result); - - matches!(result, Ok(ref v) if v.is_true()) - }) - .into_output_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/last.rs b/old_nushell/crates/nu-command/src/commands/filters/last.rs deleted file mode 100644 index b7a035b34..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/last.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; - -pub struct Last; - -impl WholeStreamCommand for Last { - fn name(&self) -> &str { - "last" - } - - fn signature(&self) -> Signature { - Signature::build("last").optional( - "rows", - SyntaxShape::Number, - "starting from the back, the number of rows to return", - ) - } - - fn usage(&self) -> &str { - "Show only the last number of rows." - } - - fn run(&self, args: CommandArgs) -> Result { - last(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get the last row", - example: "echo [1 2 3] | last", - result: Some(vec![UntaggedValue::int(3).into()]), - }, - Example { - description: "Get the last three rows", - example: "echo [1 2 3 4 5] | last 3", - result: Some(vec![ - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(5).into(), - ]), - }, - ] - } -} - -fn last(args: CommandArgs) -> Result { - let rows: Option = args.opt(0)?; - let v: Vec<_> = args.input.into_vec(); - - let end_rows_desired = if let Some(quantity) = rows { - quantity - } else { - 1 - }; - - let beginning_rows_to_skip = if end_rows_desired < v.len() { - v.len() - end_rows_desired - } else { - 0 - }; - - let iter = v.into_iter().skip(beginning_rows_to_skip); - - Ok(OutputStream::from_stream(iter)) -} - -#[cfg(test)] -mod tests { - use super::Last; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Last {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/length.rs b/old_nushell/crates/nu-command/src/commands/filters/length.rs deleted file mode 100644 index a2abee100..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/length.rs +++ /dev/null @@ -1,108 +0,0 @@ -use crate::prelude::*; - -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct Length; - -impl WholeStreamCommand for Length { - fn name(&self) -> &str { - "length" - } - - fn signature(&self) -> Signature { - Signature::build("length").switch( - "column", - "Calculate number of columns in table", - Some('c'), - ) - } - - fn usage(&self) -> &str { - "Show the total number of rows or items." - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let column = args.has_flag("column"); - let input = args.input; - - Ok(CountIterator { - column, - input, - done: false, - tag, - } - .into_output_stream()) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Count the number of entries in a list", - example: "echo [1 2 3 4 5] | length", - result: Some(vec![UntaggedValue::int(5).into()]), - }, - Example { - description: "Count the number of columns in the calendar table", - example: "cal | length -c", - result: None, - }, - ] - } -} - -struct CountIterator { - column: bool, - input: InputStream, - done: bool, - tag: Tag, -} - -impl Iterator for CountIterator { - type Item = Value; - - fn next(&mut self) -> Option { - if self.done { - return None; - } - - self.done = true; - - let length = if self.column { - if let Some(first) = self.input.next() { - match &first.value { - UntaggedValue::Row(dictionary) => dictionary.length(), - _ => { - return Some(Value::error(ShellError::labeled_error( - "Cannot obtain column length", - "cannot obtain column length", - self.tag.clone(), - ))); - } - } - } else { - 0 - } - } else { - let input = &mut self.input; - input.count() - }; - - Some(UntaggedValue::int(length as i64).into_value(self.tag.clone())) - } -} - -#[cfg(test)] -mod tests { - use super::Length; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Length {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/merge.rs b/old_nushell/crates/nu-command/src/commands/filters/merge.rs deleted file mode 100644 index 7bc087fc2..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/merge.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::prelude::*; -use nu_data::value::merge_values; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; - -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, hir::ExternalRedirection, ReturnSuccess, Signature, SyntaxShape, - UntaggedValue, Value, -}; -pub struct Merge; - -impl WholeStreamCommand for Merge { - fn name(&self) -> &str { - "merge" - } - - fn signature(&self) -> Signature { - Signature::build("merge").required( - "block", - SyntaxShape::Block, - "the block to run and merge into the table", - ) - } - - fn usage(&self) -> &str { - "Merge a table." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - merge(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Merge a 1-based index column with some ls output", - example: "ls | select name | keep 3 | merge { echo [1 2 3] | wrap index }", - result: None, - }] - } -} - -fn merge(args: CommandArgs) -> Result { - let context = &args.context; - let name_tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - let input = args.input; - - context.scope.enter_scope(); - context.scope.add_vars(&block.captured.entries); - let result = run_block( - &block.block, - context, - InputStream::empty(), - ExternalRedirection::Stdout, - ); - context.scope.exit_scope(); - - let table: Option> = match result { - Ok(mut stream) => Some(stream.drain_vec()), - Err(err) => { - return Err(err); - } - }; - - let table = table.unwrap_or_else(|| { - vec![Value { - value: UntaggedValue::row(IndexMap::default()), - tag: name_tag, - }] - }); - - Ok(input - .enumerate() - .map(move |(idx, value)| { - let other = table.get(idx); - - match other { - Some(replacement) => match merge_values(&value.value, &replacement.value) { - Ok(merged_value) => ReturnSuccess::value(merged_value.into_value(&value.tag)), - Err(_) => { - let message = format!("The row at {:?} types mismatch", idx); - Err(ShellError::labeled_error( - "Could not merge", - &message, - &value.tag, - )) - } - }, - None => ReturnSuccess::value(value), - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Merge; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Merge {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/mod.rs b/old_nushell/crates/nu-command/src/commands/filters/mod.rs deleted file mode 100644 index e44c5f7c7..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/mod.rs +++ /dev/null @@ -1,85 +0,0 @@ -mod all; -mod any; -mod append; -mod collect; -mod compact; -mod default; -mod drop; -mod each; -mod empty; -mod every; -mod first; -mod flatten; -pub(crate) mod get; -mod group_by; -mod group_by_date; -mod headers; -mod insert; -mod keep; -mod last; -mod length; -mod merge; -mod move_; -mod nth; -mod pivot; -mod prepend; -mod range; -mod reduce; -mod reject; -mod rename; -mod reverse; -mod roll; -mod rotate; -mod select; -mod shuffle; -mod skip; -pub(crate) mod sort_by; -mod uniq; -mod update; -mod update_cells; -mod where_; -mod wrap; -mod zip_; - -pub use all::Command as All; -pub use any::Command as Any; -pub use append::Command as Append; -pub use collect::Command as Collect; -pub use compact::Compact; -pub use default::Default; -pub use drop::*; -pub use each::*; -pub use empty::Command as Empty; -pub use every::Every; -pub use first::First; -pub use flatten::Command as Flatten; -pub use get::Command as Get; -pub use group_by::Command as GroupBy; -pub use group_by_date::GroupByDate; -pub use headers::Headers; -pub use insert::Command as Insert; -pub use keep::*; -pub use last::Last; -pub use length::Length; -pub use merge::Merge; -pub use move_::Command as MoveColumn; -pub use nth::Nth; -pub use pivot::Pivot; -pub use prepend::Prepend; -pub use range::Range; -pub use reduce::Reduce; -pub use reject::Reject; -pub use rename::Rename; -pub use reverse::Reverse; -pub use roll::{Roll, RollColumn, RollUp}; -pub use rotate::{Rotate, RotateCounterClockwise}; -pub use select::Command as Select; -pub use shuffle::Shuffle; -pub use skip::{Skip, SkipUntil, SkipWhile}; -pub use sort_by::SortBy; -pub use uniq::Uniq; -pub use update::Command as Update; -pub use update_cells::SubCommand as UpdateCells; -pub use where_::Command as Where; -pub use wrap::Wrap; -pub use zip_::Command as Zip; diff --git a/old_nushell/crates/nu-command/src/commands/filters/move_.rs b/old_nushell/crates/nu-command/src/commands/filters/move_.rs deleted file mode 100644 index a7daf5423..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/move_.rs +++ /dev/null @@ -1,315 +0,0 @@ -use crate::prelude::*; -use nu_data::base::select_fields; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value}; -use nu_source::HasFallibleSpan; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "move" - } - - fn signature(&self) -> Signature { - Signature::build("move") - .rest("rest", SyntaxShape::ColumnPath, "the columns to move") - .named( - "after", - SyntaxShape::ColumnPath, - "the column that will precede the columns moved", - None, - ) - .named( - "before", - SyntaxShape::ColumnPath, - "the column that will be next the columns moved", - None, - ) - } - - fn usage(&self) -> &str { - "Move columns." - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - use nu_test_support::value::*; - - vec![ - Example { - description: "Move the column \"type\" before the column \"name\"", - example: r#"ls | move type --before name | first"#, - result: Some(vec![row! { - "type".into() => string("File"), - "name".into() => string("Andres.txt"), - "chickens".into() => int(10), - "modified".into() => date("2019-07-23") - }]), - }, - Example { - description: "or move the column \"chickens\" after \"name\"", - example: r#"ls | move chickens --after name | first"#, - result: Some(vec![row! { - "name".into() => string("Andres.txt"), - "chickens".into() => int(10), - "type".into() => string("File"), - "modified".into() => date("2019-07-23") - }]), - }, - Example { - description: "you can selectively move many columns in either direction", - example: r#"ls | move name chickens --after type | first"#, - result: Some(vec![row! { - "type".into() => string("File"), - "name".into() => string("Andres.txt"), - "chickens".into() => int(10), - "modified".into() => date("2019-07-23") - }]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let mut columns: Vec = args.rest(0)?; - let before: Option = args.get_flag("before")?; - let after: Option = args.get_flag("after")?; - - if columns.is_empty() { - return Err(ShellError::labeled_error( - "expected columns", - "expected columns", - name, - )); - } - - if columns.iter().any(|c| c.members().len() > 1) { - return Err(ShellError::labeled_error( - "expected columns", - "expected columns", - name, - )); - } - - if vec![&after, &before] - .iter() - .map(|o| if o.is_some() { 1 } else { 0 }) - .sum::() - > 1 - { - return Err(ShellError::labeled_error( - "can't move column(s)", - "pick exactly one (before, after)", - name, - )); - } - - if let Some(after) = after { - let member = columns.remove(0); - - Ok(args - .input - .map(move |item| { - let member = vec![member.clone()]; - let column_paths = vec![&member, &columns] - .into_iter() - .flatten() - .collect::>(); - - let after_span = after.maybe_span().unwrap_or_else(Span::unknown); - - if after.members().len() == 1 { - let keys = column_paths - .iter() - .filter_map(|c| c.last()) - .map(|c| c.as_string()) - .collect::>(); - - if let Some(column) = after.last() { - if !keys.contains(&column.as_string()) { - move_after(&item, &keys, &after) - } else { - let msg = - format!("can't move column {} after itself", column.as_string()); - Err(ShellError::labeled_error( - "can't move column", - msg, - after_span, - )) - } - } else { - Err(ShellError::labeled_error( - "expected column", - "expected column", - after_span, - )) - } - } else { - Err(ShellError::labeled_error( - "expected column", - "expected column", - after_span, - )) - } - }) - .into_input_stream()) - } else if let Some(before) = before { - let member = columns.remove(0); - - Ok(args - .input - .map(move |item| { - let member = vec![member.clone()]; - let column_paths = vec![&member, &columns] - .into_iter() - .flatten() - .collect::>(); - - let before_span = before.maybe_span().unwrap_or_else(Span::unknown); - - if before.members().len() == 1 { - let keys = column_paths - .iter() - .filter_map(|c| c.last()) - .map(|c| c.as_string()) - .collect::>(); - - if let Some(column) = before.last() { - if !keys.contains(&column.as_string()) { - move_before(&item, &keys, &before) - } else { - let msg = - format!("can't move column {} before itself", column.as_string()); - Err(ShellError::labeled_error( - "can't move column", - msg, - before_span, - )) - } - } else { - Err(ShellError::labeled_error( - "expected column", - "expected column", - before_span, - )) - } - } else { - Err(ShellError::labeled_error( - "expected column", - "expected column", - before_span, - )) - } - }) - .into_input_stream()) - } else { - Err(ShellError::labeled_error( - "no columns given", - "no columns given", - name, - )) - } -} - -fn move_after(table: &Value, columns: &[String], from: &ColumnPath) -> Result { - let from_fields = from.maybe_span().unwrap_or_else(Span::unknown); - let from = if let Some((last, _)) = from.split_last() { - last.as_string() - } else { - return Err(ShellError::labeled_error( - "unknown column", - "unknown column", - from_fields, - )); - }; - - let columns_moved = table.data_descriptors().into_iter().map(|name| { - if columns.contains(&name) { - None - } else { - Some(name) - } - }); - - let mut reordered_columns = vec![]; - let mut insert = false; - let mut inserted = false; - - for name in columns_moved { - if let Some(name) = name { - reordered_columns.push(Some(name.clone())); - - if !inserted && name == from { - insert = true; - } - } else { - reordered_columns.push(None); - } - - if insert { - for column in columns { - reordered_columns.push(Some(column.clone())); - } - inserted = true; - } - } - - Ok(select_fields( - table, - &reordered_columns.into_iter().flatten().collect::>(), - &table.tag, - )) -} - -fn move_before(table: &Value, columns: &[String], from: &ColumnPath) -> Result { - let from_fields = from.maybe_span().unwrap_or_else(Span::unknown); - let from = if let Some((last, _)) = from.split_last() { - last.as_string() - } else { - return Err(ShellError::labeled_error( - "unknown column", - "unknown column", - from_fields, - )); - }; - - let columns_moved = table.data_descriptors().into_iter().map(|name| { - if columns.contains(&name) { - None - } else { - Some(name) - } - }); - - let mut reordered_columns = vec![]; - let mut inserted = false; - - for name in columns_moved { - if let Some(name) = name { - if !inserted && name == from { - for column in columns { - reordered_columns.push(Some(column.clone())); - } - - inserted = true; - } - - reordered_columns.push(Some(name.clone())); - } else { - reordered_columns.push(None); - } - } - - Ok(select_fields( - table, - &reordered_columns.into_iter().flatten().collect::>(), - &table.tag, - )) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/nth.rs b/old_nushell/crates/nu-command/src/commands/filters/nth.rs deleted file mode 100644 index 510477dac..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/nth.rs +++ /dev/null @@ -1,114 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; -use nu_source::Tagged; - -pub struct Nth; - -impl WholeStreamCommand for Nth { - fn name(&self) -> &str { - "nth" - } - - fn signature(&self) -> Signature { - Signature::build("nth") - .required( - "row number", - SyntaxShape::Int, - "the number of the row to return", - ) - .rest("rest", SyntaxShape::Any, "Optionally return more rows") - .switch("skip", "Skip the rows instead of selecting them", Some('s')) - } - - fn usage(&self) -> &str { - "Return or skip only the selected rows." - } - - fn run(&self, args: CommandArgs) -> Result { - nth(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get the second row", - example: "echo [first second third] | nth 1", - result: Some(vec![Value::from("second")]), - }, - Example { - description: "Get the first and third rows", - example: "echo [first second third] | nth 0 2", - result: Some(vec![Value::from("first"), Value::from("third")]), - }, - Example { - description: "Skip the first and third rows", - example: "echo [first second third] | nth --skip 0 2", - result: Some(vec![Value::from("second")]), - }, - ] - } -} - -fn nth(args: CommandArgs) -> Result { - let row_number: Tagged = args.req(0)?; - let and_rows: Vec> = args.rest(1)?; - let skip = args.has_flag("skip"); - let input = args.input; - - let mut rows: Vec<_> = and_rows.into_iter().map(|x| x.item as usize).collect(); - rows.push(row_number.item as usize); - rows.sort_unstable(); - - Ok(NthIterator { - input, - rows, - skip, - current: 0, - } - .into_output_stream()) -} - -struct NthIterator { - input: InputStream, - rows: Vec, - skip: bool, - current: usize, -} - -impl Iterator for NthIterator { - type Item = Value; - - fn next(&mut self) -> Option { - loop { - if !self.skip { - if let Some(row) = self.rows.get(0) { - if self.current == *row { - self.rows.remove(0); - self.current += 1; - return self.input.next(); - } else { - self.current += 1; - let _ = self.input.next(); - continue; - } - } else { - return None; - } - } else if let Some(row) = self.rows.get(0) { - if self.current == *row { - self.rows.remove(0); - self.current += 1; - let _ = self.input.next(); - continue; - } else { - self.current += 1; - return self.input.next(); - } - } else { - return self.input.next(); - } - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/pivot.rs b/old_nushell/crates/nu-command/src/commands/filters/pivot.rs deleted file mode 100644 index 2ae659e21..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/pivot.rs +++ /dev/null @@ -1,164 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - merge_descriptors, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, -}; -use nu_source::{SpannedItem, Tagged}; -use nu_value_ext::ValueExt; - -pub struct Pivot; - -#[derive(Deserialize)] -pub struct PivotArgs { - rest: Vec>, - #[serde(rename(deserialize = "header-row"))] - header_row: bool, - #[serde(rename(deserialize = "ignore-titles"))] - ignore_titles: bool, -} - -impl WholeStreamCommand for Pivot { - fn name(&self) -> &str { - "pivot" - } - - fn signature(&self) -> Signature { - Signature::build("pivot") - .switch( - "header-row", - "treat the first row as column names", - Some('r'), - ) - .switch( - "ignore-titles", - "don't pivot the column names into values", - Some('i'), - ) - .rest( - "rest", - SyntaxShape::String, - "the names to give columns once pivoted", - ) - } - - fn usage(&self) -> &str { - "Pivots the table contents so rows become columns and columns become rows." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - pivot(args) - } -} - -pub fn pivot(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - //let (args, input): (PivotArgs, _) = args.process()?; - let pivot_args = PivotArgs { - header_row: args.has_flag("header-row"), - ignore_titles: args.has_flag("ignore-titles"), - rest: args.rest(0)?, - }; - let input = args.input.into_vec(); - let args = pivot_args; - - let descs = merge_descriptors(&input); - - let mut headers: Vec = vec![]; - - if !args.rest.is_empty() && args.header_row { - return Err(ShellError::labeled_error( - "Can not provide header names and use header row", - "using header row", - name, - )); - } - - if args.header_row { - for i in input.clone() { - if let Some(desc) = descs.get(0) { - match &i.get_data_by_key(desc[..].spanned_unknown()) { - Some(x) => { - if let Ok(s) = x.as_string() { - headers.push(s.to_string()); - } else { - return Err(ShellError::labeled_error( - "Header row needs string headers", - "used non-string headers", - name, - )); - } - } - _ => { - return Err(ShellError::labeled_error( - "Header row is incomplete and can't be used", - "using incomplete header row", - name, - )); - } - } - } else { - return Err(ShellError::labeled_error( - "Header row is incomplete and can't be used", - "using incomplete header row", - name, - )); - } - } - } else { - for i in 0..=input.len() { - if let Some(name) = args.rest.get(i) { - headers.push(name.to_string()) - } else { - headers.push(format!("Column{}", i)); - } - } - } - - let descs: Vec<_> = if args.header_row { - descs.into_iter().skip(1).collect() - } else { - descs - }; - - Ok((descs.into_iter().map(move |desc| { - let mut column_num: usize = 0; - let mut dict = TaggedDictBuilder::new(&name); - - if !args.ignore_titles && !args.header_row { - dict.insert_untagged( - headers[column_num].clone(), - UntaggedValue::string(desc.clone()), - ); - column_num += 1 - } - - for i in input.clone() { - match &i.get_data_by_key(desc[..].spanned_unknown()) { - Some(x) => { - dict.insert_value(headers[column_num].clone(), x.clone()); - } - _ => { - dict.insert_untagged(headers[column_num].clone(), UntaggedValue::nothing()); - } - } - column_num += 1; - } - - ReturnSuccess::value(dict.into_value()) - })) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Pivot; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Pivot {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/prepend.rs b/old_nushell/crates/nu-command/src/commands/filters/prepend.rs deleted file mode 100644 index 8dd98a68d..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/prepend.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct Prepend; - -impl WholeStreamCommand for Prepend { - fn name(&self) -> &str { - "prepend" - } - - fn signature(&self) -> Signature { - Signature::build("prepend").required( - "row value", - SyntaxShape::Any, - "the value of the row to prepend to the table", - ) - } - - fn usage(&self) -> &str { - "Prepend the given row to the front of the table." - } - - fn run(&self, args: CommandArgs) -> Result { - prepend(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Add something to the beginning of a list or table", - example: "echo [2 3 4] | prepend 1", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ]), - }] - } -} - -fn prepend(args: CommandArgs) -> Result { - let row: Value = args.req(0)?; - let input = args.input; - - let bos = vec![row].into_iter(); - - Ok(bos.chain(input).into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Prepend; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Prepend {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/range.rs b/old_nushell/crates/nu-command/src/commands/filters/range.rs deleted file mode 100644 index 93feadb7c..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/range.rs +++ /dev/null @@ -1,114 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; - -struct RangeArgs { - range: nu_protocol::Range, -} - -pub struct Range; - -impl WholeStreamCommand for Range { - fn name(&self) -> &str { - "range" - } - - fn signature(&self) -> Signature { - Signature::build("range").required( - "rows", - SyntaxShape::Range, - "range of rows to return: Eg) 4..7 (=> from 4 to 7)", - ) - } - - fn usage(&self) -> &str { - "Return only the selected rows." - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Return rows 1 through 3", - example: "echo [1 2 3 4 5] | range 1..3", - result: Some(vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ]), - }, - Example { - description: "Return the third row from the end, through to the end", - example: "echo [1 2 3 4 5] | range (-3..)", - result: Some(vec![ - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(5).into(), - ]), - }, - ] - } - - fn run(&self, args: CommandArgs) -> Result { - range(args) - } -} - -fn range(args: CommandArgs) -> Result { - let cmd_args = RangeArgs { - range: args.req(0)?, - }; - - let from_raw = cmd_args.range.min_i64()?; - let to_raw = cmd_args.range.max_i64()?; - // only collect the input if we have any negative indices - if from_raw < 0 || to_raw < 0 { - let input = args.input.into_vec(); - let input_size = input.len() as i64; - - let from = if from_raw < 0 { - (input_size + from_raw) as usize - } else { - from_raw as usize - }; - - let to = if to_raw < 0 { - (input_size + to_raw) as usize - } else if to_raw > input.len() as i64 { - input.len() - } else { - to_raw as usize - }; - - if from > to { - Ok(OutputStream::one(Value::nothing())) - } else { - Ok(OutputStream::from(input[from..to].to_vec())) - } - } else { - let from = from_raw as usize; - let to = to_raw as usize; - if from > to { - Ok(OutputStream::one(Value::nothing())) - } else { - Ok(args - .input - .skip(from) - .take(to - from + 1) - .into_output_stream()) - } - } -} - -#[cfg(test)] -mod tests { - use super::Range; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Range {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/reduce.rs b/old_nushell/crates/nu-command/src/commands/filters/reduce.rs deleted file mode 100644 index bacb0601b..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/reduce.rs +++ /dev/null @@ -1,223 +0,0 @@ -use super::each; -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_engine::{CommandArgs, Example}; -use nu_errors::ShellError; -use nu_parser::ParserScope; -use nu_protocol::{ - hir::CapturedBlock, hir::ExternalRedirection, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_stream::ActionStream; - -pub struct Reduce; - -#[derive(Deserialize)] -pub struct ReduceArgs { - block: CapturedBlock, - fold: Option, - numbered: bool, -} - -impl WholeStreamCommand for Reduce { - fn name(&self) -> &str { - "reduce" - } - - fn signature(&self) -> Signature { - Signature::build("reduce") - .named( - "fold", - SyntaxShape::Any, - "reduce with initial value", - Some('f'), - ) - .required("block", SyntaxShape::Block, "reducing function") - .switch( - "numbered", - "returned a numbered item ($it.index and $it.item)", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Aggregate a list table to a single value using an accumulator block." - } - - fn extra_usage(&self) -> &str { - "Block must be (A, A) -> A unless --fold is selected, in which case it may be A, B -> A." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - reduce(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Simple summation (equivalent to math sum)", - example: "echo 1 2 3 4 | reduce { $acc + $it }", - result: Some(vec![UntaggedValue::int(10).into()]), - }, - Example { - description: "Summation from starting value using fold", - example: "echo 1 2 3 4 | reduce -f (-1) { $acc + $it }", - result: Some(vec![UntaggedValue::int(9).into()]), - }, - Example { - description: "Folding with rows", - example: " | reduce -f 1.6 { $acc * (echo $it.a | str to-int) + (echo $it.b | str to-int) }", - result: None, - }, - Example { - description: "Numbered reduce to find index of longest word", - example: "echo one longest three bar | reduce -n { if ($it.item | str length) > ($acc.item | str length) {echo $it} {echo $acc}} | get index", - result: None, - }, - ] - } -} - -fn process_row( - block: Arc, - context: &EvaluationContext, - row: Value, -) -> Result { - let row_clone = row.clone(); - let input_stream = vec![Ok(row_clone)].into_iter().into_input_stream(); - - context.scope.enter_scope(); - context.scope.add_vars(&block.captured.entries); - - if let Some((arg, _)) = block.block.params.positional.first() { - context.scope.add_var(arg.name(), row); - } else { - context.scope.add_var("$it", row); - } - - let result = run_block( - &block.block, - context, - input_stream, - ExternalRedirection::Stdout, - ); - context.scope.exit_scope(); - - result -} - -fn reduce(args: CommandArgs) -> Result { - let span = args.call_info.name_tag.span; - let context = Arc::new(args.context.clone()); - let reduce_args = ReduceArgs { - block: args.req(0)?, - fold: args.get_flag("fold")?, - numbered: args.has_flag("numbered"), - }; - let mut input = args.input; - - let block = Arc::new(reduce_args.block); - let (ioffset, start) = if !input.is_empty() { - match reduce_args.fold { - None => { - let first = input.next().expect("non-empty stream"); - - (1, first) - } - Some(acc) => (0, acc), - } - } else { - return Err(ShellError::labeled_error( - "Expected input", - "needs input", - span, - )); - }; - - if reduce_args.numbered { - // process_row returns Result, so we must fold with one - let initial = Ok(InputStream::one(each::make_indexed_item( - ioffset - 1, - start, - ))); - - Ok(input - .enumerate() - .fold(initial, move |acc, input| { - let context = context.clone(); - let block = Arc::clone(&block); - let row = each::make_indexed_item(input.0 + ioffset, input.1); - - let values = acc?.drain_vec(); - - let f = if values.len() == 1 { - let value = values - .get(0) - .ok_or_else(|| ShellError::unexpected("No value to update with"))?; - value.clone() - } else if values.is_empty() { - UntaggedValue::nothing().into_untagged_value() - } else { - UntaggedValue::table(&values).into_untagged_value() - }; - - context.scope.enter_scope(); - context.scope.add_var("$acc", f); - let result = process_row(block, &context, row); - context.scope.exit_scope(); - - // we make sure that result is an indexed item - result.and_then(|mut acc| { - let values = acc.drain_vec(); - let value = values - .get(0) - .ok_or_else(|| ShellError::unexpected("No value to update with"))?; - Ok(InputStream::one(match value.value { - UntaggedValue::Primitive(_) => each::make_indexed_item(0, value.clone()), - _ => value.clone(), - })) - }) - })? - .into_action_stream()) - } else { - let initial = Ok(InputStream::one(start)); - Ok(input - .fold(initial, move |acc, row| { - let block = Arc::clone(&block); - let context = context.clone(); - - let values = acc?.drain_vec(); - - let f = if values.len() == 1 { - let value = values - .get(0) - .ok_or_else(|| ShellError::unexpected("No value to update with"))?; - value.clone() - } else if values.is_empty() { - UntaggedValue::nothing().into_untagged_value() - } else { - UntaggedValue::table(&values).into_untagged_value() - }; - - context.scope.enter_scope(); - context.scope.add_var("$acc", f); - let result = process_row(block, &context, row); - context.scope.exit_scope(); - result - })? - .into_action_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::Reduce; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Reduce {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/reject.rs b/old_nushell/crates/nu-command/src/commands/filters/reject.rs deleted file mode 100644 index 0e91aba1d..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/reject.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::prelude::*; -use nu_data::base::reject_fields; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; -use nu_source::Tagged; - -pub struct Reject; - -impl WholeStreamCommand for Reject { - fn name(&self) -> &str { - "reject" - } - - fn signature(&self) -> Signature { - Signature::build("reject").rest( - "rest", - SyntaxShape::String, - "the names of columns to remove", - ) - } - - fn usage(&self) -> &str { - "Remove the given columns from the table. If you want to remove rows, try 'drop'." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - reject(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Lists the files in a directory without showing the modified column", - example: "ls | reject modified", - result: None, - }] - } -} - -fn reject(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let fields: Vec> = args.rest(0)?; - - if fields.is_empty() { - return Err(ShellError::labeled_error( - "Reject requires fields", - "needs parameter", - name, - )); - } - - let fields: Vec<_> = fields.iter().map(|f| f.item.clone()).collect(); - - Ok(args - .input - .map(move |item| ReturnSuccess::value(reject_fields(&item, &fields, &item.tag))) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Reject; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Reject {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/rename.rs b/old_nushell/crates/nu-command/src/commands/filters/rename.rs deleted file mode 100644 index d6ffbdb32..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/rename.rs +++ /dev/null @@ -1,120 +0,0 @@ -use crate::prelude::*; -use indexmap::indexmap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct Rename; - -impl WholeStreamCommand for Rename { - fn name(&self) -> &str { - "rename" - } - - fn signature(&self) -> Signature { - Signature::build("rename") - .required( - "column_name", - SyntaxShape::String, - "the new name for the first column", - ) - .rest( - "rest", - SyntaxShape::String, - "the new name for additional columns", - ) - } - - fn usage(&self) -> &str { - "Creates a new table with columns renamed." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - rename(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Rename a column", - example: "echo [[a, b]; [1, 2]] | rename my_column", - result: Some(vec![UntaggedValue::row(indexmap! { - "my_column".to_string() => UntaggedValue::int(1).into(), - "b".to_string() => UntaggedValue::int(2).into(), - }) - .into()]), - }, - Example { - description: "Rename many columns", - example: "echo [[a, b, c]; [1, 2, 3]] | rename eggs ham bacon", - result: Some(vec![UntaggedValue::row(indexmap! { - "eggs".to_string() => UntaggedValue::int(1).into(), - "ham".to_string() => UntaggedValue::int(2).into(), - "bacon".to_string() => UntaggedValue::int(3).into(), - }) - .into()]), - }, - ] - } -} - -pub fn rename(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let column_name: Tagged = args.req(0)?; - let rest: Vec> = args.rest(1)?; - let input = args.input; - - let mut new_column_names = vec![vec![column_name]]; - new_column_names.push(rest); - - let new_column_names = new_column_names.into_iter().flatten().collect::>(); - - Ok(input - .map(move |item| { - if let Value { - value: UntaggedValue::Row(row), - tag, - } = item - { - let mut renamed_row = IndexMap::new(); - - for (idx, (key, value)) in row.entries.iter().enumerate() { - let key = if idx < new_column_names.len() { - &new_column_names[idx].item - } else { - key - }; - - renamed_row.insert(key.clone(), value.clone()); - } - - let out = UntaggedValue::Row(renamed_row.into()).into_value(tag); - - ReturnSuccess::value(out) - } else { - ReturnSuccess::value( - UntaggedValue::Error(ShellError::labeled_error( - "no column names available", - "can't rename", - &name, - )) - .into_untagged_value(), - ) - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Rename; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Rename {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/reverse.rs b/old_nushell/crates/nu-command/src/commands/filters/reverse.rs deleted file mode 100644 index dbd7ee939..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/reverse.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; - -pub struct Reverse; - -impl WholeStreamCommand for Reverse { - fn name(&self) -> &str { - "reverse" - } - - fn signature(&self) -> Signature { - Signature::build("reverse") - } - - fn usage(&self) -> &str { - "Reverses the table." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - reverse(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Sort list of numbers in descending file size", - example: "echo [3 1 2 19 0] | reverse", - result: Some(vec![ - UntaggedValue::int(0).into(), - UntaggedValue::int(19).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(1).into(), - UntaggedValue::int(3).into(), - ]), - }] - } -} - -#[allow(clippy::needless_collect)] -fn reverse(args: CommandArgs) -> Result { - // Clippy warning should be ignored - // This collect is needed to apply rev - let input = args.input.collect::>(); - Ok((input.into_iter().rev().map(ReturnSuccess::value)).into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Reverse; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Reverse {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/roll/column.rs b/old_nushell/crates/nu-command/src/commands/filters/roll/column.rs deleted file mode 100644 index 6650babd0..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/roll/column.rs +++ /dev/null @@ -1,111 +0,0 @@ -use crate::prelude::*; -use nu_data::base::select_fields; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tagged; - -use super::support::{rotate, Direction}; - -pub struct SubCommand; - -pub struct Arguments { - by: Option>, - opposite: bool, - cells_only: bool, -} - -impl Arguments { - fn direction(&self) -> Direction { - if self.opposite { - return Direction::Left; - } - - Direction::Right - } - - fn move_headers(&self) -> bool { - !self.cells_only - } -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "roll column" - } - - fn signature(&self) -> Signature { - Signature::build("roll column") - .optional("by", SyntaxShape::Int, "the number of times to roll") - .switch("opposite", "roll in the opposite direction", Some('o')) - .switch("cells-only", "only roll the cells", Some('c')) - } - - fn usage(&self) -> &str { - "Rolls the table columns" - } - - fn run(&self, args: CommandArgs) -> Result { - roll(args) - } -} - -pub fn roll(args: CommandArgs) -> Result { - let options = Arguments { - by: args.opt(0)?, - opposite: args.has_flag("opposite"), - cells_only: args.has_flag("cells-only"), - }; - - Ok(args - .input - .flat_map(move |value| { - let tag = value.tag(); - - roll_by(value, &options) - .unwrap_or_else(|| vec![UntaggedValue::nothing().into_value(tag)]) - }) - .into_output_stream()) -} - -fn roll_by(value: Value, options: &Arguments) -> Option> { - let tag = value.tag(); - let direction = options.direction(); - - if value.is_row() { - let columns = value.data_descriptors(); - if options.move_headers() { - if let Some(fields) = rotate(columns, &options.by, direction) { - return Some(vec![select_fields(&value, &fields, &tag)]); - } - } else { - let values_rotated = rotate( - value - .row_entries() - .map(|(_, value)| value.clone()) - .collect::>(), - &options.by, - direction, - ); - - if let Some(ref values) = values_rotated { - let mut out = TaggedDictBuilder::new(&tag); - - for (k, v) in columns.iter().zip(values) { - out.insert_value(k, v.clone()); - } - - return Some(vec![out.into_value()]); - } - } - None - } else if value.is_table() { - rotate( - value.table_entries().cloned().collect(), - &options.by, - direction, - ) - } else { - Some(vec![value]) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/roll/command.rs b/old_nushell/crates/nu-command/src/commands/filters/roll/command.rs deleted file mode 100644 index 7cda6350b..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/roll/command.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -use super::support::{rotate, Direction}; - -pub struct Command; - -pub struct Arguments { - by: Option>, -} - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "roll" - } - - fn signature(&self) -> Signature { - Signature::build("roll").optional("by", SyntaxShape::Int, "the number of times to roll") - } - - fn usage(&self) -> &str { - "Rolls the table rows." - } - - fn run(&self, args: CommandArgs) -> Result { - roll(args) - } -} - -pub fn roll(mut args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let options = Arguments { by: args.opt(0)? }; - - let values = args.input.drain_vec(); - - Ok(roll_down(values, &options) - .unwrap_or_else(|| vec![UntaggedValue::nothing().into_value(&name)]) - .into_iter() - .into_output_stream()) -} - -fn roll_down(values: Vec, Arguments { by: ref n }: &Arguments) -> Option> { - rotate(values, n, Direction::Down) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/roll/mod.rs b/old_nushell/crates/nu-command/src/commands/filters/roll/mod.rs deleted file mode 100644 index a74a70df8..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/roll/mod.rs +++ /dev/null @@ -1,42 +0,0 @@ -mod column; -mod command; -mod up; - -pub use column::SubCommand as RollColumn; -pub use command::Command as Roll; -pub use up::SubCommand as RollUp; - -mod support { - - pub enum Direction { - Left, - Right, - Down, - Up, - } - - pub fn rotate( - mut collection: Vec, - n: &Option>, - direction: Direction, - ) -> Option> { - if collection.is_empty() { - return None; - } - - let values = collection.as_mut_slice(); - - let rotations = if let Some(n) = n { - n.item as usize % values.len() - } else { - 1 - }; - - match direction { - Direction::Up | Direction::Right => values.rotate_left(rotations), - Direction::Down | Direction::Left => values.rotate_right(rotations), - } - - Some(values.to_vec()) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/roll/up.rs b/old_nushell/crates/nu-command/src/commands/filters/roll/up.rs deleted file mode 100644 index 47d26c05b..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/roll/up.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -use super::support::{rotate, Direction}; - -pub struct SubCommand; - -#[derive(Deserialize)] -pub struct Arguments { - by: Option>, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "roll up" - } - - fn signature(&self) -> Signature { - Signature::build("roll up").optional("by", SyntaxShape::Int, "the number of times to roll") - } - - fn usage(&self) -> &str { - "Rolls the table rows" - } - - fn run(&self, args: CommandArgs) -> Result { - roll(args) - } -} - -pub fn roll(mut args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let options = Arguments { by: args.opt(0)? }; - - let values = args.input.drain_vec(); - - Ok(roll_up(values, &options) - .unwrap_or_else(|| vec![UntaggedValue::nothing().into_value(&name)]) - .into_iter() - .into_output_stream()) -} - -fn roll_up(values: Vec, Arguments { by: ref n }: &Arguments) -> Option> { - rotate(values, n, Direction::Up) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/rotate/command.rs b/old_nushell/crates/nu-command/src/commands/filters/rotate/command.rs deleted file mode 100644 index 2d2516c36..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/rotate/command.rs +++ /dev/null @@ -1,113 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - merge_descriptors, ColumnPath, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, - UntaggedValue, -}; -use nu_source::{SpannedItem, Tagged}; -use nu_value_ext::ValueExt; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "rotate" - } - - fn signature(&self) -> Signature { - Signature::build("rotate").rest( - "rest", - SyntaxShape::String, - "the names to give columns once rotated", - ) - } - - fn usage(&self) -> &str { - "Rotates the table by 90 degrees clockwise." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - rotate(args) - } -} - -pub fn rotate(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let rest: Vec> = args.rest(0)?; - let input = args.input.into_vec(); - - let total_rows = input.len(); - let descs = merge_descriptors(&input); - let total_descriptors = descs.len(); - - let descs = descs.into_iter().rev().collect::>(); - - if total_rows == 0 { - return Ok(ActionStream::empty()); - } - - let mut headers: Vec = vec![]; - - for i in 0..=total_rows { - headers.push(format!("Column{}", i)); - } - - let first = input[0].clone(); - - let name = if first.tag.anchor().is_some() { - first.tag - } else { - name - }; - - let values = - UntaggedValue::table(&input.into_iter().rev().collect::>()).into_value(&name); - - let values = nu_data::utils::group( - &values, - &Some(Box::new(move |row_number: usize, _| { - Ok(match headers.get(row_number) { - Some(name) => name.clone(), - None => String::new(), - }) - })), - &name, - )?; - - Ok(((0..total_descriptors) - .map(move |row_number| { - let mut row = TaggedDictBuilder::new(&name); - - for (current_numbered_column, (column_name, _)) in values.row_entries().enumerate() { - let raw_column_path = - format!("{}.0.{}", column_name, descs[row_number]).spanned_unknown(); - let path = ColumnPath::build(&raw_column_path); - - match &values.get_data_by_column_path(&path, Box::new(move |_, _, error| error)) { - Ok(x) => { - row.insert_value( - rest.get(current_numbered_column) - .map(|c| c.item.clone()) - .unwrap_or_else(|| column_name.to_string()), - x.clone(), - ); - } - Err(_) => {} - } - } - - row.insert_value( - rest.get(total_rows) - .map(|c| c.item.clone()) - .unwrap_or_else(|| format!("Column{}", total_rows)), - UntaggedValue::string(&descs[row_number]).into_untagged_value(), - ); - - ReturnSuccess::value(row.into_value()) - }) - .rev() - .collect::>()) - .into_iter() - .into_action_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/rotate/counter_clockwise.rs b/old_nushell/crates/nu-command/src/commands/filters/rotate/counter_clockwise.rs deleted file mode 100644 index dc95cb398..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/rotate/counter_clockwise.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - merge_descriptors, ColumnPath, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, - UntaggedValue, -}; -use nu_source::{SpannedItem, Tagged}; -use nu_value_ext::ValueExt; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "rotate counter-clockwise" - } - - fn signature(&self) -> Signature { - Signature::build("rotate counter-clockwise").rest( - "rest", - SyntaxShape::String, - "the names to give columns once rotated", - ) - } - - fn usage(&self) -> &str { - "Rotates the table by 90 degrees counter clockwise." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - rotate(args) - } -} - -pub fn rotate(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let rest: Vec> = args.rest(0)?; - - let input = args.input.into_vec(); - let descs = merge_descriptors(&input); - let total_rows = input.len(); - - if total_rows == 0 { - return Ok(ActionStream::empty()); - } - - let mut headers: Vec = vec![]; - for i in 0..=total_rows { - headers.push(format!("Column{}", i + 1)); - } - - let first = input[0].clone(); - - let name = if first.tag.anchor().is_some() { - first.tag - } else { - name - }; - - let values = UntaggedValue::table(&input).into_value(&name); - - let values = nu_data::utils::group( - &values, - &Some(Box::new(move |row_number: usize, _| { - Ok(match headers.get(row_number) { - Some(name) => name.clone(), - None => String::new(), - }) - })), - &name, - )?; - - Ok(((0..descs.len()) - .rev() - .map(move |row_number| { - let mut row = TaggedDictBuilder::new(&name); - - row.insert_value( - rest.get(0) - .map(|c| c.item.clone()) - .unwrap_or_else(|| String::from("Column0")), - UntaggedValue::string(descs.get(row_number).unwrap_or(&String::new())) - .into_untagged_value(), - ); - - for (current_numbered_column, (column_name, _)) in values.row_entries().enumerate() { - let raw_column_path = - format!("{}.0.{}", column_name, &descs[row_number]).spanned_unknown(); - let path = ColumnPath::build(&raw_column_path); - - match &values.get_data_by_column_path(&path, Box::new(move |_, _, error| error)) { - Ok(x) => { - row.insert_value( - rest.get(current_numbered_column + 1) - .map(|c| c.item.clone()) - .unwrap_or_else(|| column_name.to_string()), - x.clone(), - ); - } - Err(_) => {} - } - } - - ReturnSuccess::value(row.into_value()) - }) - .collect::>()) - .into_iter() - .into_action_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/rotate/mod.rs b/old_nushell/crates/nu-command/src/commands/filters/rotate/mod.rs deleted file mode 100644 index 16b4d8c06..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/rotate/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod command; -mod counter_clockwise; - -pub use command::Command as Rotate; -pub use counter_clockwise::SubCommand as RotateCounterClockwise; diff --git a/old_nushell/crates/nu-command/src/commands/filters/select.rs b/old_nushell/crates/nu-command/src/commands/filters/select.rs deleted file mode 100644 index 41e1ff126..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/select.rs +++ /dev/null @@ -1,275 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - ColumnPath, PathMember, Primitive, Signature, SyntaxShape, TaggedDictBuilder, - UnspannedPathMember, UntaggedValue, Value, -}; -use nu_value_ext::{as_string, get_data_by_column_path}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "select" - } - - fn signature(&self) -> Signature { - Signature::build("select") - .named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - .rest( - "rest", - SyntaxShape::ColumnPath, - "the columns to select from the table", - ) - } - - fn usage(&self) -> &str { - "Down-select table to only these columns." - } - - fn run(&self, args: CommandArgs) -> Result { - let mut columns = args.rest(0)?; - columns.extend(column_paths_from_args(&args)?); - let input = args.input; - let name = args.call_info.name_tag; - select(name, columns, input) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Select just the name column", - example: "ls | select name", - result: None, - }, - Example { - description: "Select the name and size columns", - example: "ls | select name size", - result: None, - }, - Example { - description: "Select columns dynamically", - example: "[[a b]; [1 2]] | select -c [a]", - result: Some(vec![UntaggedValue::row(indexmap! { - "a".to_string() => UntaggedValue::int(1).into(), - }) - .into()]), - }, - ] - } -} - -fn column_paths_from_args(args: &CommandArgs) -> Result, ShellError> { - let column_paths: Option> = args.get_flag("columns")?; - let has_columns = column_paths.is_some(); - let column_paths = match column_paths { - Some(cols) => { - let mut c = Vec::new(); - for col in cols { - let colpath = ColumnPath::build(&col.convert_to_string().spanned_unknown()); - if !colpath.is_empty() { - c.push(colpath) - } - } - c - } - None => Vec::new(), - }; - - if has_columns && column_paths.is_empty() { - let colval: Option = args.get_flag("columns")?; - let colspan = match colval { - Some(v) => v.tag.span, - None => Span::unknown(), - }; - return Err(ShellError::labeled_error( - "Requires a list of columns", - "must be a list of columns", - colspan, - )); - } - - Ok(column_paths) -} - -fn select( - name: Tag, - columns: Vec, - input: InputStream, -) -> Result { - if columns.is_empty() { - return Err(ShellError::labeled_error( - "Select requires columns to select", - "needs parameter", - name, - )); - } - - let mut bring_back: indexmap::IndexMap> = indexmap::IndexMap::new(); - - for value in input { - for path in &columns { - let fetcher = get_data_by_column_path( - &value, - path, - move |obj_source, path_member_tried, error| { - if let PathMember { - unspanned: UnspannedPathMember::String(column), - .. - } = path_member_tried - { - return ShellError::labeled_error_with_secondary( - "No data to fetch.", - format!("Couldn't select column \"{}\"", column), - path_member_tried.span, - "How about exploring it with \"get\"? Check the input is appropriate originating from here", - obj_source.tag.span); - } - - error - }, - ); - - let field = path.clone(); - let key = as_string( - &UntaggedValue::Primitive(Primitive::ColumnPath(field.clone())) - .into_untagged_value(), - )?; - - match fetcher { - Ok(results) => match results.value { - UntaggedValue::Table(records) => { - for x in records { - let mut out = TaggedDictBuilder::new(name.clone()); - out.insert_untagged(&key, x.value.clone()); - let group = bring_back.entry(key.clone()).or_insert(vec![]); - group.push(out.into_value()); - } - } - x => { - let mut out = TaggedDictBuilder::new(name.clone()); - out.insert_untagged(&key, x.clone()); - let group = bring_back.entry(key.clone()).or_insert(vec![]); - group.push(out.into_value()); - } - }, - Err(reason) => { - // At the moment, we can't add switches, named flags - // and the like while already using .rest since it - // breaks the parser. - // - // We allow flexibility for now and skip the error - // if a given column isn't present. - let strict: Option = None; - - if strict.is_some() { - return Err(reason); - } - - // No value for column 'key' found, insert nothing to make sure all rows contain all keys. - bring_back - .entry(key.clone()) - .or_insert(vec![]) - .push(UntaggedValue::nothing().into()); - } - } - } - } - - let mut max = 0; - - if let Some(max_column) = bring_back.values().max() { - max = max_column.len(); - } - - let keys = bring_back.keys().cloned().collect::>(); - - Ok(((0..max).map(move |current| { - let mut out = TaggedDictBuilder::new(name.clone()); - - for k in &keys { - let new_key = k.replace(".", "_"); - let nothing = UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(); - let subsets = bring_back.get(k); - - match subsets { - Some(set) => match set.get(current) { - Some(row) => out.insert_untagged(new_key, row.get_data(k).borrow().clone()), - None => out.insert_untagged(new_key, nothing.clone()), - }, - None => out.insert_untagged(new_key, nothing.clone()), - } - } - - out.into_value() - })) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use nu_protocol::ColumnPath; - use nu_source::Span; - use nu_source::SpannedItem; - use nu_source::Tag; - use nu_stream::InputStream; - use nu_test_support::value::nothing; - use nu_test_support::value::row; - use nu_test_support::value::string; - - use super::select; - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } - - #[test] - fn select_using_sparse_table() { - // Create a sparse table with 3 rows: - // col_foo | col_bar - // ----------------- - // foo | - // | bar - // foo | - let input = vec![ - row(indexmap! {"col_foo".into() => string("foo")}), - row(indexmap! {"col_bar".into() => string("bar")}), - row(indexmap! {"col_foo".into() => string("foo")}), - ]; - - let expected = vec![ - row( - indexmap! {"col_none".into() => nothing(), "col_foo".into() => string("foo"), "col_bar".into() => nothing()}, - ), - row( - indexmap! {"col_none".into() => nothing(), "col_foo".into() => nothing(), "col_bar".into() => string("bar")}, - ), - row( - indexmap! {"col_none".into() => nothing(), "col_foo".into() => string("foo"), "col_bar".into() => nothing()}, - ), - ]; - - let actual = select( - Tag::unknown(), - vec![ - ColumnPath::build(&"col_none".to_string().spanned(Span::unknown())), - ColumnPath::build(&"col_foo".to_string().spanned(Span::unknown())), - ColumnPath::build(&"col_bar".to_string().spanned(Span::unknown())), - ], - input.into(), - ); - - assert_eq!(Ok(expected), actual.map(InputStream::into_vec)); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/shuffle.rs b/old_nushell/crates/nu-command/src/commands/filters/shuffle.rs deleted file mode 100644 index 970f42270..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/shuffle.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Value}; - -use rand::seq::SliceRandom; -use rand::thread_rng; - -pub struct Shuffle; - -impl WholeStreamCommand for Shuffle { - fn name(&self) -> &str { - "shuffle" - } - - fn usage(&self) -> &str { - "Shuffle rows randomly." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(shuffle(args)) - } -} - -fn shuffle(args: CommandArgs) -> ActionStream { - let input = args.input; - let mut values: Vec = input.collect(); - - values.shuffle(&mut thread_rng()); - - values - .into_iter() - .map(ReturnSuccess::value) - .into_action_stream() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Shuffle; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Shuffle {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/skip/command.rs b/old_nushell/crates/nu-command/src/commands/filters/skip/command.rs deleted file mode 100644 index aa3be0d71..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/skip/command.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "skip" - } - - fn signature(&self) -> Signature { - Signature::build("skip").optional("rows", SyntaxShape::Int, "How many rows to skip") - } - - fn usage(&self) -> &str { - "Skip some number of rows." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - skip(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Skip the first 5 rows", - example: "echo [1 2 3 4 5 6 7] | skip 5", - result: Some(vec![ - UntaggedValue::int(6).into(), - UntaggedValue::int(7).into(), - ]), - }] - } -} - -fn skip(args: CommandArgs) -> Result { - let rows: Option> = args.opt(0)?; - let input = args.input; - - let rows_desired = if let Some(quantity) = rows { - *quantity - } else { - 1 - }; - - Ok(input.skip(rows_desired).into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/skip/mod.rs b/old_nushell/crates/nu-command/src/commands/filters/skip/mod.rs deleted file mode 100644 index f384eabbd..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/skip/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod command; -mod until; -mod while_; - -pub use command::Command as Skip; -pub use until::SubCommand as SkipUntil; -pub use while_::SubCommand as SkipWhile; diff --git a/old_nushell/crates/nu-command/src/commands/filters/skip/until.rs b/old_nushell/crates/nu-command/src/commands/filters/skip/until.rs deleted file mode 100644 index 33a347940..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/skip/until.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::prelude::*; -use log::trace; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ClassifiedCommand}, - Signature, SyntaxShape, -}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "skip until" - } - - fn signature(&self) -> Signature { - Signature::build("skip until") - .required( - "condition", - SyntaxShape::RowCondition, - "The condition that must be met to stop skipping", - ) - .filter() - } - - fn usage(&self) -> &str { - "Skips rows until the condition matches." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let ctx = Arc::new(args.context.clone()); - let tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - let condition = { - if block.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - } - }; - - Ok(args - .input - .skip_while(move |item| { - let condition = condition.clone(); - let ctx = ctx.clone(); - - ctx.scope.enter_scope(); - ctx.scope.add_vars(&block.captured.entries); - if let Some((arg, _)) = block.block.params.positional.first() { - ctx.scope.add_var(arg.name(), item.clone()); - } - trace!("ITEM = {:?}", item); - - let result = evaluate_baseline_expr(&condition, &ctx); - ctx.scope.exit_scope(); - trace!("RESULT = {:?}", result); - - !matches!(result, Ok(ref v) if v.is_true()) - }) - .into_action_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/skip/while_.rs b/old_nushell/crates/nu-command/src/commands/filters/skip/while_.rs deleted file mode 100644 index ed8b35529..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/skip/while_.rs +++ /dev/null @@ -1,101 +0,0 @@ -use crate::prelude::*; -use log::trace; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ClassifiedCommand}, - Signature, SyntaxShape, -}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "skip while" - } - - fn signature(&self) -> Signature { - Signature::build("skip while") - .required( - "condition", - SyntaxShape::RowCondition, - "The condition that must be met to continue skipping", - ) - .filter() - } - - fn usage(&self) -> &str { - "Skips rows while the condition matches." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let ctx = Arc::new(args.context.clone()); - let tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - let condition = { - if block.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - } - }; - - Ok(args - .input - .skip_while(move |item| { - let item = item.clone(); - let condition = condition.clone(); - let ctx = ctx.clone(); - - ctx.scope.enter_scope(); - ctx.scope.add_vars(&block.captured.entries); - if let Some((arg, _)) = block.block.params.positional.first() { - ctx.scope.add_var(arg.name(), item.clone()); - } - trace!("ITEM = {:?}", item); - - let result = evaluate_baseline_expr(&condition, &ctx); - ctx.scope.exit_scope(); - trace!("RESULT = {:?}", result); - - matches!(result, Ok(ref v) if v.is_true()) - }) - .into_action_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/sort_by.rs b/old_nushell/crates/nu-command/src/commands/filters/sort_by.rs deleted file mode 100644 index 30b6869c4..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/sort_by.rs +++ /dev/null @@ -1,226 +0,0 @@ -use crate::prelude::*; -use nu_data::base::coerce_compare; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use nu_value_ext::ValueExt; - -pub struct SortBy; - -impl WholeStreamCommand for SortBy { - fn name(&self) -> &str { - "sort-by" - } - - fn signature(&self) -> Signature { - Signature::build("sort-by") - .switch( - "insensitive", - "Sort string-based columns case-insensitively", - Some('i'), - ) - .switch("reverse", "Sort in reverse order", Some('r')) - .rest("rest", SyntaxShape::String, "the column(s) to sort by") - } - - fn usage(&self) -> &str { - "Sort by the given columns, in increasing order." - } - - fn run(&self, args: CommandArgs) -> Result { - sort_by(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Sort list by increasing value", - example: "echo [4 2 3 1] | sort-by", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ]), - }, - Example { - description: "Sort list by decreasing value", - example: "echo [2 3 4 1] | sort-by -r", - result: Some(vec![ - UntaggedValue::int(4).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(1).into(), - ]), - }, - Example { - description: "Sort output by increasing file size", - example: "ls | sort-by size", - result: None, - }, - Example { - description: "Sort output by type, and then by file size for each type", - example: "ls | sort-by type size", - result: None, - }, - Example { - description: "Sort strings (case-sensitive)", - example: "echo [airplane Truck Car] | sort-by", - result: Some(vec![ - UntaggedValue::string("Car").into(), - UntaggedValue::string("Truck").into(), - UntaggedValue::string("airplane").into(), - ]), - }, - Example { - description: "Sort strings (reversed case-sensitive)", - example: "echo [airplane Truck Car] | sort-by -r", - result: Some(vec![ - UntaggedValue::string("airplane").into(), - UntaggedValue::string("Truck").into(), - UntaggedValue::string("Car").into(), - ]), - }, - Example { - description: "Sort strings (case-insensitive)", - example: "echo [airplane Truck Car] | sort-by -i", - result: Some(vec![ - UntaggedValue::string("airplane").into(), - UntaggedValue::string("Car").into(), - UntaggedValue::string("Truck").into(), - ]), - }, - Example { - description: "Sort strings (reversed case-insensitive)", - example: "echo [airplane Truck Car] | sort-by -i -r", - result: Some(vec![ - UntaggedValue::string("Truck").into(), - UntaggedValue::string("Car").into(), - UntaggedValue::string("airplane").into(), - ]), - }, - ] - } -} - -fn sort_by(mut args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let rest: Vec> = args.rest(0)?; - let insensitive = args.has_flag("insensitive"); - let reverse = args.has_flag("reverse"); - let mut vec = args.input.drain_vec(); - - sort(&mut vec, &rest, &tag, insensitive)?; - - if reverse { - vec.reverse() - } - - Ok(vec.into_iter().into_output_stream()) -} - -pub fn sort( - vec: &mut [Value], - keys: &[Tagged], - tag: impl Into, - insensitive: bool, -) -> Result<(), ShellError> { - let tag = tag.into(); - - if vec.is_empty() { - return Err(ShellError::labeled_error( - "no values to work with", - "no values to work with", - tag, - )); - } - - for sort_arg in keys { - let match_test = &vec[0].get_data_by_key(sort_arg.borrow_spanned()); - if match_test.is_none() { - return Err(ShellError::labeled_error( - "Can not find column to sort by", - "invalid column", - sort_arg.borrow_spanned().span, - )); - } - } - - match &vec[0] { - Value { - value: UntaggedValue::Primitive(_), - .. - } => { - let should_sort_case_insensitively = insensitive && vec.iter().all(|x| x.is_string()); - - if let Some(values) = vec - .windows(2) - .map(|elem| coerce_compare(&elem[0], &elem[1])) - .find(|elem| elem.is_err()) - { - let (type_1, type_2) = values - .err() - .expect("An error occurred in the checking of types"); - return Err(ShellError::labeled_error( - "Not all values can be compared", - format!( - "Unable to sort values, as \"{}\" cannot compare against \"{}\"", - type_1, type_2 - ), - tag, - )); - } - - vec.sort_by(|a, b| { - if should_sort_case_insensitively { - let lowercase_a_string = a.expect_string().to_ascii_lowercase(); - let lowercase_b_string = b.expect_string().to_ascii_lowercase(); - - lowercase_a_string.cmp(&lowercase_b_string) - } else { - coerce_compare(a, b).expect("Unimplemented BUG: What about primitives that don't have an order defined?").compare() - } - }); - } - _ => { - let calc_key = |item: &Value| { - keys.iter() - .map(|f| { - let mut value_option = item.get_data_by_key(f.borrow_spanned()); - - if insensitive { - if let Some(value) = &value_option { - if let Ok(string_value) = value.as_string() { - value_option = Some( - UntaggedValue::string(string_value.to_ascii_lowercase()) - .into_value(value.tag.clone()), - ) - } - } - } - - value_option - }) - .collect::>>() - }; - vec.sort_by_cached_key(calc_key); - } - }; - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SortBy; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SortBy {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/uniq.rs b/old_nushell/crates/nu-command/src/commands/filters/uniq.rs deleted file mode 100644 index 16cf98a76..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/uniq.rs +++ /dev/null @@ -1,200 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Uniq; - -impl WholeStreamCommand for Uniq { - fn name(&self) -> &str { - "uniq" - } - - fn signature(&self) -> Signature { - Signature::build("uniq") - .switch("count", "Count the unique rows", Some('c')) - .switch( - "repeated", - "Count the rows that has more than one value", - Some('d'), - ) - .switch( - "ignore-case", - "Ignore differences in case when comparing", - Some('i'), - ) - .switch("unique", "Only return unique values", Some('u')) - } - - fn usage(&self) -> &str { - "Return the unique rows." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - uniq(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Remove duplicate rows of a list/table", - example: "echo [2 3 3 4] | uniq", - result: Some(vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ]), - }, - Example { - description: "Only print duplicate lines, one for each group", - example: "echo [1 2 2] | uniq -d", - result: Some(vec![UntaggedValue::int(2).into()]), - }, - Example { - description: "Only print unique lines lines", - example: "echo [1 2 2] | uniq -u", - result: Some(vec![UntaggedValue::int(1).into()]), - }, - Example { - description: "Ignore differences in case when comparing", - example: "echo ['hello' 'goodbye' 'Hello'] | uniq -i", - result: Some(vec![ - UntaggedValue::string("hello").into(), - UntaggedValue::string("goodbye").into(), - ]), - }, - Example { - description: "Remove duplicate rows and show counts of a list/table", - example: "echo [1 2 2] | uniq -c", - result: Some(vec![ - UntaggedValue::row(indexmap! { - "value".to_string() => UntaggedValue::int(1).into(), - "count".to_string() => UntaggedValue::int(1).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "value".to_string() => UntaggedValue::int(2).into(), - "count".to_string() => UntaggedValue::int(2).into(), - }) - .into(), - ]), - }, - ] - } -} - -fn to_lowercase(value: nu_protocol::Value) -> nu_protocol::Value { - use nu_protocol::value::StringExt; - - if value.is_string() { - value - .value - .expect_string() - .to_lowercase() - .to_string_value(value.tag) - } else { - value - } -} - -fn uniq(args: CommandArgs) -> Result { - let should_show_count = args.has_flag("count"); - let show_repeated = args.has_flag("repeated"); - let ignore_case = args.has_flag("ignore-case"); - let only_uniques = args.has_flag("unique"); - let input = args.input; - let uniq_values = { - let mut counter = IndexMap::::new(); - for line in input.into_vec() { - let item = if ignore_case { - to_lowercase(line) - } else { - line - }; - *counter.entry(item).or_insert(0) += 1; - } - counter - }; - - let mut values = if show_repeated { - uniq_values.into_iter().filter(|i| i.1 > 1).collect::<_>() - } else { - uniq_values - }; - - if only_uniques { - values = values.into_iter().filter(|i| i.1 == 1).collect::<_>(); - } - - let mut values_vec_deque = VecDeque::new(); - - if should_show_count { - for item in values { - use nu_protocol::Value; - let value = { - match item.0.value { - UntaggedValue::Row(mut row) => { - row.entries.insert( - "count".to_string(), - UntaggedValue::int(item.1 as i64).into_untagged_value(), - ); - Value { - value: UntaggedValue::Row(row), - tag: item.0.tag, - } - } - UntaggedValue::Primitive(p) => { - let mut map = IndexMap::::new(); - map.insert( - "value".to_string(), - UntaggedValue::Primitive(p).into_untagged_value(), - ); - map.insert( - "count".to_string(), - UntaggedValue::int(item.1 as i64).into_untagged_value(), - ); - Value { - value: UntaggedValue::row(map), - tag: item.0.tag, - } - } - UntaggedValue::Table(_) => { - return Err(ShellError::labeled_error( - "uniq -c cannot operate on tables.", - "source", - item.0.tag.span, - )) - } - #[cfg(feature = "dataframe")] - UntaggedValue::DataFrame(_) | UntaggedValue::FrameStruct(_) => { - return Err(ShellError::labeled_error( - "uniq -c cannot operate on data structs", - "source", - item.0.tag.span, - )) - } - UntaggedValue::Error(_) | UntaggedValue::Block(_) => item.0, - } - }; - values_vec_deque.push_back(value); - } - } else { - for item in values { - values_vec_deque.push_back(item.0); - } - } - - Ok(values_vec_deque.into_iter().into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Uniq; - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Uniq {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/update.rs b/old_nushell/crates/nu-command/src/commands/filters/update.rs deleted file mode 100644 index a3bf26a90..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/update.rs +++ /dev/null @@ -1,196 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::hir::ExternalRedirection; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::HasFallibleSpan; -use nu_value_ext::ValueExt; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "update" - } - - fn signature(&self) -> Signature { - Signature::build("update") - .required( - "field", - SyntaxShape::ColumnPath, - "the name of the column to update", - ) - .required( - "replacement value", - SyntaxShape::Any, - "the new value to give the cell(s)", - ) - } - - fn usage(&self) -> &str { - "Update an existing column to have a new value." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - update(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Update a column value", - example: "echo [[name, stars]; ['nu', 5]] | update name 'Nushell'", - result: Some(vec![UntaggedValue::row(indexmap! { - "name".to_string() => Value::from("Nushell"), - "stars".to_string() => UntaggedValue::int(5).into(), - }) - .into()]), - },Example { - description: "Use in block form for more involved updating logic", - example: "echo [[project, authors]; ['nu', ['Andrés', 'Jonathan', 'Yehuda']]] | update authors { get authors | str collect ',' }", - result: Some(vec![UntaggedValue::row(indexmap! { - "project".to_string() => Value::from("nu"), - "authors".to_string() => Value::from("Andrés,Jonathan,Yehuda"), - }) - .into()]), - }] - } -} - -fn process_row( - context: Arc, - input: Value, - mut replacement: Arc, - field: Arc, - tag: Arc, -) -> Result { - let replacement = Arc::make_mut(&mut replacement); - - Ok(match replacement { - Value { - value: UntaggedValue::Block(captured_block), - tag: block_tag, - } => { - let for_block = input.clone(); - let input_stream = vec![Ok(for_block)].into_iter().into_input_stream(); - - context.scope.enter_scope(); - if let Some((arg, _)) = captured_block.block.params.positional.first() { - context.scope.add_var(arg.name(), input.clone()); - } - - context.scope.add_vars(&captured_block.captured.entries); - - let result = run_block( - &captured_block.block, - &context, - input_stream, - ExternalRedirection::Stdout, - ); - - context.scope.exit_scope(); - - match result { - Ok(mut stream) => { - let values = stream.drain_vec(); - - let errors = context.get_errors(); - if let Some(error) = errors.first() { - return Err(error.clone()); - } - - let result = if values.len() == 1 { - let value = values - .get(0) - .ok_or_else(|| ShellError::unexpected("No value to update with."))?; - - Value { - value: value.value.clone(), - tag: input.tag.clone(), - } - } else if values.is_empty() { - UntaggedValue::nothing().into_value(&input.tag) - } else { - UntaggedValue::table(&values).into_value(&input.tag) - }; - - match input { - obj @ Value { - value: UntaggedValue::Row(_), - .. - } => match obj.replace_data_at_column_path(&field, result) { - Some(v) => ActionStream::one(ReturnSuccess::value(v)), - None => ActionStream::one(Err(ShellError::labeled_error( - "update could not find place to insert column", - "column name", - obj.tag, - ))), - }, - _ => ActionStream::one(Err(ShellError::labeled_error( - "Unrecognized type in stream", - "original value", - block_tag.clone(), - ))), - } - } - Err(e) => ActionStream::one(Err(e)), - } - } - replacement => match input { - Value { - value: UntaggedValue::Primitive(Primitive::Nothing), - .. - } => match context - .scope - .get_var("$it") - .unwrap_or_else(|| UntaggedValue::nothing().into_untagged_value()) - .replace_data_at_column_path(&field, replacement.clone()) - { - Some(v) => ActionStream::one(ReturnSuccess::value(v)), - None => ActionStream::one(Err(ShellError::labeled_error( - "update could not find place to insert column", - "column name", - field.maybe_span().unwrap_or(tag.span), - ))), - }, - Value { value: _, ref tag } => { - match input.replace_data_at_column_path(&field, replacement.clone()) { - Some(v) => ActionStream::one(ReturnSuccess::value(v)), - None => ActionStream::one(Err(ShellError::labeled_error( - "update could not find place to insert column", - "column name", - field.maybe_span().unwrap_or(tag.span), - ))), - } - } - }, - }) -} - -fn update(args: CommandArgs) -> Result { - let name_tag = Arc::new(args.call_info.name_tag.clone()); - let context = Arc::new(args.context.clone()); - - let field: ColumnPath = args.req(0)?; - let replacement: Value = args.req(1)?; - let input = args.input; - - let replacement = Arc::new(replacement); - let field = Arc::new(field); - - Ok(input - .flat_map(move |input| { - let tag = name_tag.clone(); - let context = context.clone(); - let replacement = replacement.clone(); - let field = field.clone(); - - match process_row(context, input, replacement, field, tag) { - Ok(s) => s, - Err(e) => ActionStream::one(Err(e)), - } - }) - .into_action_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/update_cells.rs b/old_nushell/crates/nu-command/src/commands/filters/update_cells.rs deleted file mode 100644 index c3de86975..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/update_cells.rs +++ /dev/null @@ -1,211 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ExternalRedirection}, - Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, -}; -use std::collections::HashSet; -use std::iter::FromIterator; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "update cells" - } - - fn signature(&self) -> Signature { - Signature::build("update cells") - .required( - "block", - SyntaxShape::Block, - "the block to run an update for each cell", - ) - .named( - "columns", - SyntaxShape::Table, - "list of columns to update", - Some('c'), - ) - } - - fn usage(&self) -> &str { - "Update the table cells." - } - - fn run(&self, args: CommandArgs) -> Result { - update_cells(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Update the zero value cells to empty strings.", - example: r#"[ - [2021-04-16, 2021-06-10, 2021-09-18, 2021-10-15, 2021-11-16, 2021-11-17, 2021-11-18]; - [ 37, 0, 0, 0, 37, 0, 0] -] | update cells {|value| - if ($value | into int) == 0 { - "" - } { - $value - } -}"#, - result: Some(vec![UntaggedValue::row(indexmap! { - "2021-04-16".to_string() => UntaggedValue::int(37).into(), - "2021-06-10".to_string() => Value::from(""), - "2021-09-18".to_string() => Value::from(""), - "2021-10-15".to_string() => Value::from(""), - "2021-11-16".to_string() => UntaggedValue::int(37).into(), - "2021-11-17".to_string() => Value::from(""), - "2021-11-18".to_string() => Value::from(""), - }) - .into()]), - }, - Example { - description: "Update the zero value cells to empty strings in 2 last columns.", - example: r#"[ - [2021-04-16, 2021-06-10, 2021-09-18, 2021-10-15, 2021-11-16, 2021-11-17, 2021-11-18]; - [ 37, 0, 0, 0, 37, 0, 0] -] | update cells -c ["2021-11-18", "2021-11-17"] {|value| - if ($value | into int) == 0 { - "" - } { - $value - } -}"#, - result: Some(vec![UntaggedValue::row(indexmap! { - "2021-04-16".to_string() => UntaggedValue::int(37).into(), - "2021-06-10".to_string() => UntaggedValue::int(0).into(), - "2021-09-18".to_string() => UntaggedValue::int(0).into(), - "2021-10-15".to_string() => UntaggedValue::int(0).into(), - "2021-11-16".to_string() => UntaggedValue::int(37).into(), - "2021-11-17".to_string() => Value::from(""), - "2021-11-18".to_string() => Value::from(""), - }) - .into()]), - }, - ] - } -} - -fn update_cells(args: CommandArgs) -> Result { - let context = Arc::new(args.context.clone()); - let external_redirection = args.call_info.args.external_redirection; - - let block: CapturedBlock = args.req(0)?; - let block = Arc::new(block); - - let columns = args - .get_flag("columns")? - .map(|x: Value| HashSet::from_iter(x.table_entries().map(|val| val.convert_to_string()))); - let columns = Arc::new(columns); - - Ok(args - .input - .flat_map(move |input| { - let block = block.clone(); - let context = context.clone(); - - if input.is_row() { - OutputStream::one(process_cells( - block, - columns.clone(), - context, - input, - external_redirection, - )) - } else { - match process_input(block, context, input, external_redirection) { - Ok(s) => s, - Err(e) => OutputStream::one(Value::error(e)), - } - } - }) - .into_output_stream()) -} - -pub fn process_input( - captured_block: Arc, - context: Arc, - input: Value, - external_redirection: ExternalRedirection, -) -> Result { - let input_clone = input.clone(); - // When we process a row, we need to know whether the block wants to have the contents of the row as - // a parameter to the block (so it gets assigned to a variable that can be used inside the block) or - // if it wants the contents as as an input stream - - let input_stream = if !captured_block.block.params.positional.is_empty() { - InputStream::empty() - } else { - vec![Ok(input_clone)].into_iter().into_input_stream() - }; - - context.scope.enter_scope(); - context.scope.add_vars(&captured_block.captured.entries); - - if let Some((arg, _)) = captured_block.block.params.positional.first() { - context.scope.add_var(arg.name(), input); - } else { - context.scope.add_var("$it", input); - } - - let result = run_block( - &captured_block.block, - &context, - input_stream, - external_redirection, - ); - - context.scope.exit_scope(); - - result -} - -pub fn process_cells( - captured_block: Arc, - columns: Arc>>, - context: Arc, - input: Value, - external_redirection: ExternalRedirection, -) -> Value { - TaggedDictBuilder::build(input.tag(), |row| { - input.row_entries().for_each(|(column, cell_value)| { - match &*columns { - Some(col) if !col.contains(column) => { - row.insert_value(column, cell_value.clone()); - return; - } - _ => {} - }; - let cell_processed = process_input( - captured_block.clone(), - context.clone(), - cell_value.clone(), - external_redirection, - ) - .map(|it| it.into_vec()) - .map_err(Value::error); - - match cell_processed { - Ok(value) => { - match value.get(0) { - Some(one) => { - row.insert_value(column, one.clone()); - } - None => { - row.insert_untagged(column, UntaggedValue::nothing()); - } - }; - } - Err(reason) => { - row.insert_value(column, reason); - } - } - }); - }) -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/where_.rs b/old_nushell/crates/nu-command/src/commands/filters/where_.rs deleted file mode 100644 index e081f1d80..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/where_.rs +++ /dev/null @@ -1,154 +0,0 @@ -use crate::prelude::*; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, - hir::{ClassifiedCommand, SpannedExpression}, - Signature, SyntaxShape, Value, -}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "where" - } - - fn signature(&self) -> Signature { - Signature::build("where").required( - "condition", - SyntaxShape::RowCondition, - "the condition that must match", - ) - } - - fn usage(&self) -> &str { - "Filter table to match the condition." - } - - fn run(&self, args: CommandArgs) -> Result { - where_command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "List all files in the current directory with sizes greater than 2kb", - example: "ls | where size > 2kb", - result: None, - }, - Example { - description: "List only the files in the current directory", - example: "ls | where type == File", - result: None, - }, - Example { - description: "List all files with names that contain \"Car\"", - example: "ls | where name =~ \"Car\"", - result: None, - }, - Example { - description: "List all files that were modified in the last two weeks", - example: "ls | where modified <= 2wk", - result: None, - }, - ] - } -} -fn where_command(args: CommandArgs) -> Result { - let context = Arc::new(args.context.clone()); - let tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - - let condition = { - if block.block.block.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - match block.block.block[0].pipelines.get(0) { - Some(item) => match item.list.get(0) { - Some(ClassifiedCommand::Expr(expr)) => expr.clone(), - _ => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - }, - None => { - return Err(ShellError::labeled_error( - "Expected a condition", - "expected a condition", - tag, - )); - } - } - }; - - Ok(WhereIterator { - condition, - context, - input: args.input, - block, - } - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} - -struct WhereIterator { - condition: Box, - context: Arc, - input: InputStream, - block: CapturedBlock, -} - -impl Iterator for WhereIterator { - type Item = Value; - - fn next(&mut self) -> Option { - for x in &mut self.input { - self.context.scope.enter_scope(); - self.context.scope.add_vars(&self.block.captured.entries); - - if let Some((arg, _)) = self.block.block.params.positional.first() { - self.context.scope.add_var(arg.name(), x.clone()); - } - - //FIXME: should we use the scope that's brought in as well? - let condition = evaluate_baseline_expr(&self.condition, &self.context); - self.context.scope.exit_scope(); - - match condition { - Ok(condition) => match condition.as_bool() { - Ok(b) => { - if b { - return Some(x); - } - } - Err(e) => return Some(Value::error(e)), - }, - Err(e) => return Some(Value::error(e)), - } - } - - None - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/wrap.rs b/old_nushell/crates/nu-command/src/commands/filters/wrap.rs deleted file mode 100644 index 90f42334d..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/wrap.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::prelude::*; -use indexmap::{indexmap, IndexMap}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -const DEFAULT_COLUMN_NAME: &str = "Column"; - -pub struct Wrap; - -impl WholeStreamCommand for Wrap { - fn name(&self) -> &str { - "wrap" - } - - fn signature(&self) -> Signature { - Signature::build("wrap").optional( - "column", - SyntaxShape::String, - "the name of the new column", - ) - } - - fn usage(&self) -> &str { - "Wraps the given data in a table." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - wrap(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Wrap a list into a table with the default column name", - example: "echo [1 2 3] | wrap", - result: Some(vec![ - UntaggedValue::row(indexmap! { - DEFAULT_COLUMN_NAME.to_string() => UntaggedValue::int(1).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - DEFAULT_COLUMN_NAME.to_string() => UntaggedValue::int(2).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - DEFAULT_COLUMN_NAME.to_string() => UntaggedValue::int(3).into(), - }) - .into(), - ]), - }, - Example { - description: "Wrap a list into a table with a given column name", - example: "echo [1 2 3] | wrap MyColumn", - result: Some(vec![ - UntaggedValue::row(indexmap! { - "MyColumn".to_string() => UntaggedValue::int(1).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "MyColumn".to_string() => UntaggedValue::int(2).into(), - }) - .into(), - UntaggedValue::row(indexmap! { - "MyColumn".to_string() => UntaggedValue::int(3).into(), - }) - .into(), - ]), - }, - ] - } -} - -fn wrap(args: CommandArgs) -> Result { - let column: Option> = args.opt(0)?; - - let mut result_table = vec![]; - let mut are_all_rows = true; - - for value in args.input { - match value { - Value { - value: UntaggedValue::Row(_), - .. - } => { - result_table.push(value); - } - _ => { - are_all_rows = false; - - let mut index_map = IndexMap::new(); - index_map.insert( - match &column { - Some(key) => key.item.clone(), - None => DEFAULT_COLUMN_NAME.to_string(), - }, - value, - ); - - result_table.push(UntaggedValue::row(index_map).into_value(Tag::unknown())); - } - } - } - - if are_all_rows { - let mut index_map = IndexMap::new(); - index_map.insert( - match &column { - Some(key) => key.item.clone(), - None => DEFAULT_COLUMN_NAME.to_string(), - }, - UntaggedValue::table(&result_table).into_value(Tag::unknown()), - ); - - let row = UntaggedValue::row(index_map).into_untagged_value(); - - Ok(ActionStream::one(ReturnSuccess::value(row))) - } else { - Ok((result_table.into_iter().map(ReturnSuccess::value)).into_action_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Wrap; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Wrap {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/filters/zip_.rs b/old_nushell/crates/nu-command/src/commands/filters/zip_.rs deleted file mode 100644 index 8ce5af6dc..000000000 --- a/old_nushell/crates/nu-command/src/commands/filters/zip_.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::prelude::*; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::did_you_mean; -use nu_protocol::TaggedDictBuilder; -use nu_protocol::{ - hir::CapturedBlock, hir::ExternalRedirection, ColumnPath, PathMember, Signature, SyntaxShape, - UnspannedPathMember, UntaggedValue, Value, -}; -use nu_value_ext::get_data_by_column_path; - -use nu_source::HasFallibleSpan; -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "zip" - } - - fn signature(&self) -> Signature { - Signature::build("zip").required( - "block", - SyntaxShape::Block, - "the block to run and zip into the table", - ) - } - - fn usage(&self) -> &str { - "Zip two tables." - } - - fn run(&self, args: CommandArgs) -> Result { - command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Zip two lists", - example: "[0 2 4 6 8] | zip { [1 3 5 7 9] } | each { $it }", - result: None, - }, - Example { - description: "Zip two tables", - example: "[[symbol]; ['('] ['['] ['{']] | zip { [[symbol]; [')'] [']'] ['}']] } | each { get symbol | $'($in.0)nushell($in.1)' }", - result: Some(vec![ - Value::from("(nushell)"), - Value::from("[nushell]"), - Value::from("{nushell}") - ]) - }] - } -} - -fn command(args: CommandArgs) -> Result { - let context = &args.context; - let name_tag = args.call_info.name_tag.clone(); - - let block: CapturedBlock = args.req(0)?; - let block_span = &block.block.span.clone(); - let input = args.input; - - context.scope.enter_scope(); - context.scope.add_vars(&block.captured.entries); - let result = run_block( - &block.block, - context, - InputStream::empty(), - ExternalRedirection::Stdout, - ); - context.scope.exit_scope(); - - Ok(OutputStream::from_stream(zip( - input, - result, - name_tag, - *block_span, - )?)) -} - -fn zip<'a>( - l: impl Iterator + 'a + Sync + Send, - r: Result, - command_tag: Tag, - secondary_command_span: Span, -) -> Result + 'a + Sync + Send>, ShellError> { - Ok(Box::new(l.zip(r?).map(move |(s1, s2)| match (s1, s2) { - ( - left_row @ Value { - value: UntaggedValue::Row(_), - .. - }, - mut right_row @ Value { - value: UntaggedValue::Row(_), - .. - }, - ) => { - let mut zipped_row = TaggedDictBuilder::new(left_row.tag()); - - right_row.tag = Tag::new(right_row.tag.anchor(), secondary_command_span); - - for column in left_row.data_descriptors() { - let path = ColumnPath::build(&(column.to_string()).spanned(right_row.tag.span)); - zipped_row.insert_value(column, zip_row(&path, &left_row, &right_row)); - } - - zipped_row.into_value() - } - (s1, s2) => { - let mut name_tag = command_tag.clone(); - name_tag.anchor = s1.tag.anchor(); - UntaggedValue::table(&vec![s1, s2]).into_value(&name_tag) - } - }))) -} - -fn zip_row(path: &ColumnPath, left: &Value, right: &Value) -> UntaggedValue { - UntaggedValue::table(&vec![ - get_column(path, left) - .unwrap_or_else(|err| UntaggedValue::Error(err).into_untagged_value()), - get_column(path, right) - .unwrap_or_else(|err| UntaggedValue::Error(err).into_untagged_value()), - ]) -} - -pub fn get_column(path: &ColumnPath, value: &Value) -> Result { - get_data_by_column_path(value, path, move |obj_source, column_path_tried, error| { - let path_members_span = path.maybe_span().unwrap_or_else(Span::unknown); - - if obj_source.is_row() { - if let Some(error) = error_message(column_path_tried, &path_members_span, obj_source) { - return error; - } - } - - error - }) -} - -fn error_message( - column_tried: &PathMember, - path_members_span: &Span, - obj_source: &Value, -) -> Option { - match column_tried { - PathMember { - unspanned: UnspannedPathMember::String(column), - .. - } => { - let primary_label = format!("There isn't a column named '{}' from this table", &column); - - did_you_mean(obj_source, column_tried.as_string()).map(|suggestions| { - ShellError::labeled_error_with_secondary( - "Unknown column", - primary_label, - obj_source.tag.span, - format!( - "Perhaps you meant '{}'? Columns available: {}", - suggestions[0], - &obj_source.data_descriptors().join(", ") - ), - column_tried.span.since(path_members_span), - ) - }) - } - _ => None, - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/command.rs b/old_nushell/crates/nu-command/src/commands/formats/from/command.rs deleted file mode 100644 index 5d6d68af9..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/command.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct From; - -impl WholeStreamCommand for From { - fn name(&self) -> &str { - "from" - } - - fn signature(&self) -> Signature { - Signature::build("from") - } - - fn usage(&self) -> &str { - "Parse content (string or binary) as a table (input format based on subcommand, like csv, ini, json, toml)." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&From, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::From; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(From {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/csv.rs b/old_nushell/crates/nu-command/src/commands/formats/from/csv.rs deleted file mode 100644 index 2c27bf8b1..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/csv.rs +++ /dev/null @@ -1,107 +0,0 @@ -use super::delimited::from_delimited_data; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct FromCsv; - -impl WholeStreamCommand for FromCsv { - fn name(&self) -> &str { - "from csv" - } - - fn signature(&self) -> Signature { - Signature::build("from csv") - .named( - "separator", - SyntaxShape::String, - "a character to separate columns, defaults to ','", - Some('s'), - ) - .switch( - "noheaders", - "don't treat the first row as column names", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Parse text as .csv and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_csv(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert comma-separated data to a table", - example: "open data.txt | from csv", - result: None, - }, - Example { - description: "Convert comma-separated data to a table, ignoring headers", - example: "open data.txt | from csv --noheaders", - result: None, - }, - Example { - description: "Convert comma-separated data to a table, ignoring headers", - example: "open data.txt | from csv -n", - result: None, - }, - Example { - description: "Convert semicolon-separated data to a table", - example: "open data.txt | from csv --separator ';'", - result: None, - }, - ] - } -} - -fn from_csv(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let noheaders = args.has_flag("noheaders"); - let separator: Option = args.get_flag("separator")?; - let input = args.input; - - let sep = match separator { - Some(Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - tag, - .. - }) => { - if s == r"\t" { - '\t' - } else { - let vec_s: Vec = s.chars().collect(); - if vec_s.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a single separator char from --separator", - "requires a single character string input", - tag, - )); - }; - vec_s[0] - } - } - _ => ',', - }; - - from_delimited_data(noheaders, sep, "CSV", input, name) -} - -#[cfg(test)] -mod tests { - use super::FromCsv; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromCsv {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/delimited.rs b/old_nushell/crates/nu-command/src/commands/formats/from/delimited.rs deleted file mode 100644 index 28b5df27e..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/delimited.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::prelude::*; -use csv::{ErrorKind, ReaderBuilder}; -use nu_errors::ShellError; -use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; - -fn from_delimited_string_to_value( - s: String, - noheaders: bool, - separator: char, - tag: impl Into, -) -> Result { - let mut reader = ReaderBuilder::new() - .has_headers(!noheaders) - .delimiter(separator as u8) - .from_reader(s.as_bytes()); - let tag = tag.into(); - let span = tag.span; - - let headers = if noheaders { - (1..=reader.headers()?.len()) - .map(|i| format!("Column{}", i)) - .collect::>() - } else { - reader.headers()?.iter().map(String::from).collect() - }; - - let mut rows = vec![]; - for row in reader.records() { - let mut tagged_row = TaggedDictBuilder::new(&tag); - for (value, header) in row?.iter().zip(&headers) { - if let Ok(i) = value.parse::() { - tagged_row.insert_value(header, UntaggedValue::int(i).into_value(&tag)) - } else if let Ok(f) = value.parse::() { - tagged_row.insert_value( - header, - UntaggedValue::decimal_from_float(f, span).into_value(&tag), - ) - } else { - tagged_row.insert_value(header, UntaggedValue::string(value).into_value(&tag)) - } - } - rows.push(tagged_row.into_value()); - } - - Ok(UntaggedValue::Table(rows).into_value(&tag)) -} - -pub fn from_delimited_data( - noheaders: bool, - sep: char, - format_name: &'static str, - input: InputStream, - name: Tag, -) -> Result { - let name_tag = name; - let concat_string = input.collect_string(name_tag.clone())?; - let sample_lines = concat_string.item.lines().take(3).collect_vec().join("\n"); - - match from_delimited_string_to_value(concat_string.item, noheaders, sep, name_tag.clone()) { - Ok(x) => match x { - Value { - value: UntaggedValue::Table(list), - .. - } => Ok(list.into_iter().into_output_stream()), - x => Ok(OutputStream::one(x)), - }, - Err(err) => { - let line_one = match pretty_csv_error(err) { - Some(pretty) => format!( - "Could not parse as {} split by '{}' ({})", - format_name, sep, pretty - ), - None => format!("Could not parse as {} split by '{}'", format_name, sep), - }; - let line_two = format!( - "input cannot be parsed as {} split by '{}'. Input's first lines:\n{}", - format_name, sep, sample_lines - ); - - Err(ShellError::labeled_error_with_secondary( - line_one, - line_two, - name_tag, - "value originates from here", - concat_string.tag, - )) - } - } -} - -fn pretty_csv_error(err: csv::Error) -> Option { - match err.kind() { - ErrorKind::UnequalLengths { - pos, - expected_len, - len, - } => { - if let Some(pos) = pos { - Some(format!( - "Line {}: expected {} fields, found {}", - pos.line(), - expected_len, - len - )) - } else { - Some(format!("Expected {} fields, found {}", expected_len, len)) - } - } - ErrorKind::Seek => Some("Internal error while parsing csv".to_string()), - _ => None, - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/eml.rs b/old_nushell/crates/nu-command/src/commands/formats/from/eml.rs deleted file mode 100644 index 68bbee84c..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/eml.rs +++ /dev/null @@ -1,125 +0,0 @@ -use crate::prelude::*; -use ::eml_parser::eml::*; -use ::eml_parser::EmlParser; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue}; -use nu_source::Tagged; - -pub struct FromEml; - -const DEFAULT_BODY_PREVIEW: usize = 50; - -impl WholeStreamCommand for FromEml { - fn name(&self) -> &str { - "from eml" - } - - fn signature(&self) -> Signature { - Signature::build("from eml").named( - "preview-body", - SyntaxShape::Int, - "How many bytes of the body to preview", - Some('b'), - ) - } - - fn usage(&self) -> &str { - "Parse text as .eml and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_eml(args) - } -} - -fn emailaddress_to_value(tag: &Tag, email_address: &EmailAddress) -> TaggedDictBuilder { - let mut dict = TaggedDictBuilder::with_capacity(tag, 2); - let (n, a) = match email_address { - EmailAddress::AddressOnly { address } => { - (UntaggedValue::nothing(), UntaggedValue::string(address)) - } - EmailAddress::NameAndEmailAddress { name, address } => { - (UntaggedValue::string(name), UntaggedValue::string(address)) - } - }; - - dict.insert_untagged("Name", n); - dict.insert_untagged("Address", a); - - dict -} - -fn headerfieldvalue_to_value(tag: &Tag, value: &HeaderFieldValue) -> UntaggedValue { - use HeaderFieldValue::*; - - match value { - SingleEmailAddress(address) => emailaddress_to_value(tag, address).into_untagged_value(), - MultipleEmailAddresses(addresses) => UntaggedValue::Table( - addresses - .iter() - .map(|a| emailaddress_to_value(tag, a).into_value()) - .collect(), - ), - Unstructured(s) => UntaggedValue::string(s), - Empty => UntaggedValue::nothing(), - } -} - -fn from_eml(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let preview_body: Option> = args.get_flag("preview-body")?; - - let value = args.input.collect_string(tag.clone())?; - - let body_preview = preview_body.map(|b| b.item).unwrap_or(DEFAULT_BODY_PREVIEW); - - let eml = EmlParser::from_string(value.item) - .with_body_preview(body_preview) - .parse() - .map_err(|_| { - ShellError::labeled_error( - "Could not parse .eml file", - "could not parse .eml file", - &tag, - ) - })?; - - let mut dict = TaggedDictBuilder::new(&tag); - - if let Some(subj) = eml.subject { - dict.insert_untagged("Subject", UntaggedValue::string(subj)); - } - - if let Some(from) = eml.from { - dict.insert_untagged("From", headerfieldvalue_to_value(&tag, &from)); - } - - if let Some(to) = eml.to { - dict.insert_untagged("To", headerfieldvalue_to_value(&tag, &to)); - } - - for HeaderField { name, value } in &eml.headers { - dict.insert_untagged(name, headerfieldvalue_to_value(&tag, value)); - } - - if let Some(body) = eml.body { - dict.insert_untagged("Body", UntaggedValue::string(body)); - } - - Ok(OutputStream::one(dict.into_value())) -} - -#[cfg(test)] -mod tests { - use super::FromEml; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromEml {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/ics.rs b/old_nushell/crates/nu-command/src/commands/formats/from/ics.rs deleted file mode 100644 index 2770cb14e..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/ics.rs +++ /dev/null @@ -1,250 +0,0 @@ -extern crate ical; -use crate::prelude::*; -use ical::parser::ical::component::*; -use ical::property::Property; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value}; -use std::io::BufReader; - -pub struct FromIcs; - -impl WholeStreamCommand for FromIcs { - fn name(&self) -> &str { - "from ics" - } - - fn signature(&self) -> Signature { - Signature::build("from ics") - } - - fn usage(&self) -> &str { - "Parse text as .ics and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_ics(args) - } -} - -fn from_ics(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - - let input_string = input.collect_string(tag.clone())?.item; - let input_bytes = input_string.as_bytes(); - let buf_reader = BufReader::new(input_bytes); - let parser = ical::IcalParser::new(buf_reader); - - // TODO: it should be possible to make this a stream, but the some of the lifetime requirements make this tricky. - // Pre-computing for now - let mut output = vec![]; - - for calendar in parser { - match calendar { - Ok(c) => output.push(calendar_to_value(c, tag.clone())), - Err(_) => output.push(Value::error(ShellError::labeled_error( - "Could not parse as .ics", - "input cannot be parsed as .ics", - tag.clone(), - ))), - } - } - - Ok(output.into_iter().into_output_stream()) -} - -fn calendar_to_value(calendar: IcalCalendar, tag: Tag) -> Value { - let mut row = TaggedDictBuilder::new(tag.clone()); - - row.insert_untagged( - "properties", - properties_to_value(calendar.properties, tag.clone()), - ); - row.insert_untagged("events", events_to_value(calendar.events, tag.clone())); - row.insert_untagged("alarms", alarms_to_value(calendar.alarms, tag.clone())); - row.insert_untagged("to-Dos", todos_to_value(calendar.todos, tag.clone())); - row.insert_untagged( - "journals", - journals_to_value(calendar.journals, tag.clone()), - ); - row.insert_untagged( - "free-busys", - free_busys_to_value(calendar.free_busys, tag.clone()), - ); - row.insert_untagged("timezones", timezones_to_value(calendar.timezones, tag)); - - row.into_value() -} - -fn events_to_value(events: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &events - .into_iter() - .map(|event| { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged( - "properties", - properties_to_value(event.properties, tag.clone()), - ); - row.insert_untagged("alarms", alarms_to_value(event.alarms, tag.clone())); - row.into_value() - }) - .collect::>(), - ) -} - -fn alarms_to_value(alarms: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &alarms - .into_iter() - .map(|alarm| { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged( - "properties", - properties_to_value(alarm.properties, tag.clone()), - ); - row.into_value() - }) - .collect::>(), - ) -} - -fn todos_to_value(todos: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &todos - .into_iter() - .map(|todo| { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged( - "properties", - properties_to_value(todo.properties, tag.clone()), - ); - row.insert_untagged("alarms", alarms_to_value(todo.alarms, tag.clone())); - row.into_value() - }) - .collect::>(), - ) -} - -fn journals_to_value(journals: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &journals - .into_iter() - .map(|journal| { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged( - "properties", - properties_to_value(journal.properties, tag.clone()), - ); - row.into_value() - }) - .collect::>(), - ) -} - -fn free_busys_to_value(free_busys: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &free_busys - .into_iter() - .map(|free_busy| { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged( - "properties", - properties_to_value(free_busy.properties, tag.clone()), - ); - row.into_value() - }) - .collect::>(), - ) -} - -fn timezones_to_value(timezones: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &timezones - .into_iter() - .map(|timezone| { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged( - "properties", - properties_to_value(timezone.properties, tag.clone()), - ); - row.insert_untagged( - "transitions", - timezone_transitions_to_value(timezone.transitions, tag.clone()), - ); - row.into_value() - }) - .collect::>(), - ) -} - -fn timezone_transitions_to_value( - transitions: Vec, - tag: Tag, -) -> UntaggedValue { - UntaggedValue::table( - &transitions - .into_iter() - .map(|transition| { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged( - "properties", - properties_to_value(transition.properties, tag.clone()), - ); - row.into_value() - }) - .collect::>(), - ) -} - -fn properties_to_value(properties: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &properties - .into_iter() - .map(|prop| { - let mut row = TaggedDictBuilder::new(tag.clone()); - - let name = UntaggedValue::string(prop.name); - let value = match prop.value { - Some(val) => UntaggedValue::string(val), - None => UntaggedValue::Primitive(Primitive::Nothing), - }; - let params = match prop.params { - Some(param_list) => params_to_value(param_list, tag.clone()).into(), - None => UntaggedValue::Primitive(Primitive::Nothing), - }; - - row.insert_untagged("name", name); - row.insert_untagged("value", value); - row.insert_untagged("params", params); - row.into_value() - }) - .collect::>(), - ) -} - -fn params_to_value(params: Vec<(String, Vec)>, tag: Tag) -> Value { - let mut row = TaggedDictBuilder::new(tag); - - for (param_name, param_values) in params { - let values: Vec = param_values.into_iter().map(|val| val.into()).collect(); - let values = UntaggedValue::table(&values); - row.insert_untagged(param_name, values); - } - - row.into_value() -} - -#[cfg(test)] -mod tests { - use super::FromIcs; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromIcs {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/ini.rs b/old_nushell/crates/nu-command/src/commands/formats/from/ini.rs deleted file mode 100644 index 950f8f064..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/ini.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; -use std::collections::HashMap; - -#[derive(Debug, thiserror::Error)] -pub enum DeserializationError { - #[error("Failed to parse input as INI")] - Ini(#[from] serde_ini::de::Error), - - #[error("Failed to convert to a nushell value")] - Nu(#[from] nu_serde::Error), -} - -pub struct FromIni; - -impl WholeStreamCommand for FromIni { - fn name(&self) -> &str { - "from ini" - } - - fn signature(&self) -> Signature { - Signature::build("from ini") - } - - fn usage(&self) -> &str { - "Parse text as .ini and create table" - } - - fn run(&self, args: CommandArgs) -> Result { - from_ini(args) - } -} - -pub fn from_ini_string_to_value( - s: String, - tag: impl Into, -) -> Result { - let v: HashMap> = serde_ini::from_str(&s)?; - - Ok(nu_serde::to_value(v, tag)?) -} - -fn from_ini(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - let concat_string = input.collect_string(tag.clone())?; - - match from_ini_string_to_value(concat_string.item, tag.clone()) { - Ok(x) => match x { - Value { - value: UntaggedValue::Table(list), - .. - } => Ok(list.into_iter().into_output_stream()), - x => Ok(OutputStream::one(x)), - }, - Err(DeserializationError::Ini(e)) => Err(ShellError::labeled_error_with_secondary( - format!("Could not parse as INI: {}", e), - "input cannot be parsed as INI", - &tag, - "value originates from here", - concat_string.tag, - )), - Err(DeserializationError::Nu(e)) => Err(ShellError::labeled_error_with_secondary( - format!("Could not convert to nushell value: {}", e), - "input cannot be converted to nushell", - &tag, - "value originates from here", - concat_string.tag, - )), - } -} - -#[cfg(test)] -mod tests { - use super::FromIni; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromIni {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/json.rs b/old_nushell/crates/nu-command/src/commands/formats/from/json.rs deleted file mode 100644 index 7d0c3f65d..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/json.rs +++ /dev/null @@ -1,149 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -#[derive(Debug, thiserror::Error)] -pub enum DeserializationError { - #[error("Failed to parse input as JSON")] - Json(#[from] nu_json::Error), - - #[error("Failed to convert JSON to a nushell value")] - Nu(#[from] Box), -} - -pub struct FromJson; - -impl WholeStreamCommand for FromJson { - fn name(&self) -> &str { - "from json" - } - - fn signature(&self) -> Signature { - Signature::build("from json").switch( - "objects", - "treat each line as a separate value", - Some('o'), - ) - } - - fn usage(&self) -> &str { - "Parse text as .json and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_json(args) - } -} - -pub fn from_json_string_to_value( - s: String, - tag: impl Into, -) -> Result { - let v: nu_json::Value = nu_json::from_str(&s)?; - - Ok(nu_serde::to_value(v, tag).map_err(Box::new)?) -} - -fn from_json(args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - - let objects = args.has_flag("objects"); - - let concat_string = args.input.collect_string(name_tag.clone())?; - - if objects { - #[allow(clippy::needless_collect)] - let lines: Vec<_> = concat_string.item.lines().map(|x| x.to_string()).collect(); - Ok(lines - .into_iter() - .filter_map(move |json_str| { - if json_str.is_empty() { - return None; - } - - match from_json_string_to_value(json_str, &name_tag) { - Ok(x) => Some(x), - Err(DeserializationError::Nu(e)) => { - let mut message = "Could not convert JSON to nushell value (".to_string(); - message.push_str(&e.to_string()); - message.push(')'); - Some(Value::error(ShellError::labeled_error_with_secondary( - message, - "input cannot be converted to nushell values", - name_tag.clone(), - "value originates from here", - concat_string.tag.clone(), - ))) - } - Err(DeserializationError::Json(e)) => { - let mut message = "Could not parse as JSON (".to_string(); - message.push_str(&e.to_string()); - message.push(')'); - - Some(Value::error(ShellError::labeled_error_with_secondary( - message, - "input cannot be parsed as JSON", - name_tag.clone(), - "value originates from here", - concat_string.tag.clone(), - ))) - } - } - }) - .into_output_stream()) - } else { - match from_json_string_to_value(concat_string.item, name_tag.clone()) { - Ok(x) => match x { - Value { - value: UntaggedValue::Table(list), - .. - } => Ok(list.into_iter().into_output_stream()), - - x => Ok(OutputStream::one(x)), - }, - Err(DeserializationError::Json(e)) => { - let mut message = "Could not parse as JSON (".to_string(); - message.push_str(&e.to_string()); - message.push(')'); - - Ok(OutputStream::one(Value::error( - ShellError::labeled_error_with_secondary( - message, - "input cannot be parsed as JSON", - name_tag, - "value originates from here", - concat_string.tag, - ), - ))) - } - Err(DeserializationError::Nu(e)) => { - let mut message = "Could not convert JSON to nushell value (".to_string(); - message.push_str(&e.to_string()); - message.push(')'); - Ok(OutputStream::one(Value::error( - ShellError::labeled_error_with_secondary( - message, - "input cannot be converted to nushell values", - name_tag, - "value originates from here", - concat_string.tag, - ), - ))) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::FromJson; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromJson {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/mod.rs b/old_nushell/crates/nu-command/src/commands/formats/from/mod.rs deleted file mode 100644 index fe91fdb63..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -mod command; -pub(crate) mod csv; -mod delimited; -mod eml; -mod ics; -mod ini; -mod json; -mod ods; -mod ssv; -pub(crate) mod toml; -mod tsv; -pub(crate) mod url; -mod vcf; -mod xlsx; -mod xml; -mod yaml; - -pub use self::csv::FromCsv; -pub use self::toml::FromToml; -pub use self::url::FromUrl; -pub use command::From; -pub use eml::FromEml; -pub use ics::FromIcs; -pub use ini::FromIni; -pub use json::FromJson; -pub use ods::FromOds; -pub use ssv::FromSsv; -pub use tsv::FromTsv; -pub use vcf::FromVcf; -pub use xlsx::FromXlsx; -pub use xml::FromXml; -pub use yaml::{FromYaml, FromYml}; diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/ods.rs b/old_nushell/crates/nu-command/src/commands/formats/from/ods.rs deleted file mode 100644 index 5187d5f08..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/ods.rs +++ /dev/null @@ -1,120 +0,0 @@ -use crate::prelude::*; -use calamine::*; -use nu_data::TaggedListBuilder; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value}; -use std::io::Cursor; - -pub struct FromOds; - -impl WholeStreamCommand for FromOds { - fn name(&self) -> &str { - "from ods" - } - - fn signature(&self) -> Signature { - Signature::build("from ods").named( - "sheets", - SyntaxShape::Table, - "Only convert specified sheets", - Some('s'), - ) - } - - fn usage(&self) -> &str { - "Parse OpenDocument Spreadsheet(.ods) data and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_ods(args) - } -} - -// Adapted from crates/nu-command/src/commands/dataframe/utils.rs -fn convert_columns(columns: &[Value]) -> Result, ShellError> { - let res = columns - .iter() - .map(|value| match &value.value { - UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()), - _ => Err(ShellError::labeled_error( - "Incorrect column format", - "Only string as column name", - &value.tag, - )), - }) - .collect::, _>>()?; - - Ok(res) -} - -fn from_ods(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let span = tag.span; - - let mut sel_sheets = vec![]; - - if let Some(columns) = args.get_flag::>("sheets")? { - sel_sheets = convert_columns(columns.as_slice())?; - } - - let bytes = args.input.collect_binary(tag.clone())?; - let buf: Cursor> = Cursor::new(bytes.item); - let mut ods = Ods::<_>::new(buf).map_err(|_| { - ShellError::labeled_error("Could not load ods file", "could not load ods file", &tag) - })?; - - let mut dict = TaggedDictBuilder::new(&tag); - - let mut sheet_names = ods.sheet_names().to_owned(); - if !sel_sheets.is_empty() { - sheet_names.retain(|e| sel_sheets.contains(e)); - } - - for sheet_name in &sheet_names { - let mut sheet_output = TaggedListBuilder::new(&tag); - - if let Some(Ok(current_sheet)) = ods.worksheet_range(sheet_name) { - for row in current_sheet.rows() { - let mut row_output = TaggedDictBuilder::new(&tag); - for (i, cell) in row.iter().enumerate() { - let value = match cell { - DataType::Empty => UntaggedValue::nothing(), - DataType::String(s) => UntaggedValue::string(s), - DataType::Float(f) => UntaggedValue::decimal_from_float(*f, span), - DataType::Int(i) => UntaggedValue::int(*i), - DataType::Bool(b) => UntaggedValue::boolean(*b), - _ => UntaggedValue::nothing(), - }; - - row_output.insert_untagged(&format!("Column{}", i), value); - } - - sheet_output.push_untagged(row_output.into_untagged_value()); - } - - dict.insert_untagged(sheet_name, sheet_output.into_untagged_value()); - } else { - return Err(ShellError::labeled_error( - "Could not load sheet", - "could not load sheet", - &tag, - )); - } - } - - Ok(OutputStream::one(dict.into_value())) -} - -#[cfg(test)] -mod tests { - use super::FromOds; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromOds {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/ssv.rs b/old_nushell/crates/nu-command/src/commands/formats/from/ssv.rs deleted file mode 100644 index 2ede8a8e4..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/ssv.rs +++ /dev/null @@ -1,480 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct FromSsv; - -const STRING_REPRESENTATION: &str = "from ssv"; -const DEFAULT_MINIMUM_SPACES: usize = 2; - -impl WholeStreamCommand for FromSsv { - fn name(&self) -> &str { - STRING_REPRESENTATION - } - - fn signature(&self) -> Signature { - Signature::build(STRING_REPRESENTATION) - .switch( - "noheaders", - "don't treat the first row as column names", - Some('n'), - ) - .switch("aligned-columns", "assume columns are aligned", Some('a')) - .named( - "minimum-spaces", - SyntaxShape::Int, - "the minimum spaces to separate columns", - Some('m'), - ) - } - - fn usage(&self) -> &str { - "Parse text as space-separated values and create a table. The default minimum number of spaces counted as a separator is 2." - } - - fn run(&self, args: CommandArgs) -> Result { - from_ssv(args) - } -} - -enum HeaderOptions<'a> { - WithHeaders(&'a str), - WithoutHeaders, -} - -fn parse_aligned_columns<'a>( - lines: impl Iterator, - headers: HeaderOptions, - separator: &str, -) -> Vec> { - fn construct<'a>( - lines: impl Iterator, - headers: Vec<(String, usize)>, - ) -> Vec> { - lines - .map(|l| { - headers - .iter() - .enumerate() - .map(|(i, (header_name, start_position))| { - let val = match headers.get(i + 1) { - Some((_, end)) => { - if *end < l.len() { - l.get(*start_position..*end) - } else { - l.get(*start_position..) - } - } - None => l.get(*start_position..), - } - .unwrap_or("") - .trim() - .into(); - (header_name.clone(), val) - }) - .collect() - }) - .collect() - } - - let find_indices = |line: &str| { - let values = line - .split(&separator) - .map(str::trim) - .filter(|s| !s.is_empty()); - values - .fold( - (0, vec![]), - |(current_pos, mut indices), value| match line[current_pos..].find(value) { - None => (current_pos, indices), - Some(index) => { - let absolute_index = current_pos + index; - indices.push(absolute_index); - (absolute_index + value.len(), indices) - } - }, - ) - .1 - }; - - let parse_with_headers = |lines, headers_raw: &str| { - let indices = find_indices(headers_raw); - let headers = headers_raw - .split(&separator) - .map(str::trim) - .filter(|s| !s.is_empty()) - .map(String::from) - .zip(indices); - - let columns = headers.collect::>(); - - construct(lines, columns) - }; - - let parse_without_headers = |ls: Vec<&str>| { - let mut indices = ls - .iter() - .flat_map(|s| find_indices(*s)) - .collect::>(); - - indices.sort_unstable(); - indices.dedup(); - - let headers: Vec<(String, usize)> = indices - .iter() - .enumerate() - .map(|(i, position)| (format!("Column{}", i + 1), *position)) - .collect(); - - construct(ls.iter().map(|s| s.to_owned()), headers) - }; - - match headers { - HeaderOptions::WithHeaders(headers_raw) => parse_with_headers(lines, headers_raw), - HeaderOptions::WithoutHeaders => parse_without_headers(lines.collect()), - } -} - -fn parse_separated_columns<'a>( - lines: impl Iterator, - headers: HeaderOptions, - separator: &str, -) -> Vec> { - fn collect<'a>( - headers: Vec, - rows: impl Iterator, - separator: &str, - ) -> Vec> { - rows.map(|r| { - headers - .iter() - .zip(r.split(separator).map(str::trim).filter(|s| !s.is_empty())) - .map(|(a, b)| (a.to_owned(), b.to_owned())) - .collect() - }) - .collect() - } - - let parse_with_headers = |lines, headers_raw: &str| { - let headers = headers_raw - .split(&separator) - .map(str::trim) - .map(str::to_owned) - .filter(|s| !s.is_empty()) - .collect(); - collect(headers, lines, separator) - }; - - let parse_without_headers = |ls: Vec<&str>| { - let num_columns = ls.iter().map(|r| r.len()).max().unwrap_or(0); - - let headers = (1..=num_columns) - .map(|i| format!("Column{}", i)) - .collect::>(); - collect(headers, ls.into_iter(), separator) - }; - - match headers { - HeaderOptions::WithHeaders(headers_raw) => parse_with_headers(lines, headers_raw), - HeaderOptions::WithoutHeaders => parse_without_headers(lines.collect()), - } -} - -fn string_to_table( - s: &str, - noheaders: bool, - aligned_columns: bool, - split_at: usize, -) -> Vec> { - let mut lines = s.lines().filter(|l| !l.trim().is_empty()); - let separator = " ".repeat(std::cmp::max(split_at, 1)); - - let (ls, header_options) = if noheaders { - (lines, HeaderOptions::WithoutHeaders) - } else { - match lines.next() { - Some(header) => (lines, HeaderOptions::WithHeaders(header)), - None => return vec![], - } - }; - - let f = if aligned_columns { - parse_aligned_columns - } else { - parse_separated_columns - }; - - f(ls, header_options, &separator) -} - -fn from_ssv_string_to_value( - s: &str, - noheaders: bool, - aligned_columns: bool, - split_at: usize, - tag: impl Into, -) -> Value { - let tag = tag.into(); - let rows = string_to_table(s, noheaders, aligned_columns, split_at) - .iter() - .map(|row| { - let mut tagged_dict = TaggedDictBuilder::new(&tag); - for (col, entry) in row { - tagged_dict.insert_value( - col, - UntaggedValue::Primitive(Primitive::String(String::from(entry))) - .into_value(&tag), - ) - } - tagged_dict.into_value() - }) - .collect(); - - UntaggedValue::Table(rows).into_value(&tag) -} - -fn from_ssv(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let noheaders = args.has_flag("noheaders"); - let aligned_columns = args.has_flag("aligned-columns"); - let minimum_spaces: Option> = args.get_flag("minimum-spaces")?; - - let concat_string = args.input.collect_string(name.clone())?; - let split_at = match minimum_spaces { - Some(number) => number.item, - None => DEFAULT_MINIMUM_SPACES, - }; - - Ok( - match from_ssv_string_to_value( - &concat_string.item, - noheaders, - aligned_columns, - split_at, - name, - ) { - Value { - value: UntaggedValue::Table(list), - .. - } => list.into_iter().into_output_stream(), - x => OutputStream::one(x), - }, - ) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::*; - - fn owned(x: &str, y: &str) -> (String, String) { - (String::from(x), String::from(y)) - } - - #[test] - fn it_trims_empty_and_whitespace_only_lines() { - let input = r#" - - a b - - 1 2 - - 3 4 - "#; - let result = string_to_table(input, false, true, 1); - assert_eq!( - result, - vec![ - vec![owned("a", "1"), owned("b", "2")], - vec![owned("a", "3"), owned("b", "4")] - ] - ); - } - - #[test] - fn it_deals_with_single_column_input() { - let input = r#" - a - 1 - 2 - "#; - let result = string_to_table(input, false, true, 1); - assert_eq!(result, vec![vec![owned("a", "1")], vec![owned("a", "2")]]); - } - - #[test] - fn it_uses_first_row_as_data_when_noheaders() { - let input = r#" - a b - 1 2 - 3 4 - "#; - let result = string_to_table(input, true, true, 1); - assert_eq!( - result, - vec![ - vec![owned("Column1", "a"), owned("Column2", "b")], - vec![owned("Column1", "1"), owned("Column2", "2")], - vec![owned("Column1", "3"), owned("Column2", "4")] - ] - ); - } - - #[test] - fn it_allows_a_predefined_number_of_spaces() { - let input = r#" - column a column b - entry 1 entry number 2 - 3 four - "#; - - let result = string_to_table(input, false, true, 3); - assert_eq!( - result, - vec![ - vec![ - owned("column a", "entry 1"), - owned("column b", "entry number 2") - ], - vec![owned("column a", "3"), owned("column b", "four")] - ] - ); - } - - #[test] - fn it_trims_remaining_separator_space() { - let input = r#" - colA colB colC - val1 val2 val3 - "#; - - let trimmed = |s: &str| s.trim() == s; - - let result = string_to_table(input, false, true, 2); - assert!(result - .iter() - .all(|row| row.iter().all(|(a, b)| trimmed(a) && trimmed(b)))); - } - - #[test] - fn it_keeps_empty_columns() { - let input = r#" - colA col B col C - val2 val3 - val4 val 5 val 6 - val7 val8 - "#; - - let result = string_to_table(input, false, true, 2); - assert_eq!( - result, - vec![ - vec![ - owned("colA", ""), - owned("col B", "val2"), - owned("col C", "val3") - ], - vec![ - owned("colA", "val4"), - owned("col B", "val 5"), - owned("col C", "val 6") - ], - vec![ - owned("colA", "val7"), - owned("col B", ""), - owned("col C", "val8") - ], - ] - ); - } - - #[test] - fn it_can_produce_an_empty_stream_for_header_only_input() { - let input = "colA col B"; - - let result = string_to_table(input, false, true, 2); - let expected: Vec> = vec![]; - assert_eq!(expected, result); - } - - #[test] - fn it_uses_the_full_final_column() { - let input = r#" - colA col B - val1 val2 trailing value that should be included - "#; - - let result = string_to_table(input, false, true, 2); - assert_eq!( - result, - vec![vec![ - owned("colA", "val1"), - owned("col B", "val2 trailing value that should be included"), - ]] - ); - } - - #[test] - fn it_handles_empty_values_when_noheaders_and_aligned_columns() { - let input = r#" - a multi-word value b d - 1 3-3 4 - last - "#; - - let result = string_to_table(input, true, true, 2); - assert_eq!( - result, - vec![ - vec![ - owned("Column1", "a multi-word value"), - owned("Column2", "b"), - owned("Column3", ""), - owned("Column4", "d"), - owned("Column5", "") - ], - vec![ - owned("Column1", "1"), - owned("Column2", ""), - owned("Column3", "3-3"), - owned("Column4", "4"), - owned("Column5", "") - ], - vec![ - owned("Column1", ""), - owned("Column2", ""), - owned("Column3", ""), - owned("Column4", ""), - owned("Column5", "last") - ], - ] - ); - } - - #[test] - fn input_is_parsed_correctly_if_either_option_works() { - let input = r#" - docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP - kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP - kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP - "#; - - let aligned_columns_noheaders = string_to_table(input, true, true, 2); - let separator_noheaders = string_to_table(input, true, false, 2); - let aligned_columns_with_headers = string_to_table(input, false, true, 2); - let separator_with_headers = string_to_table(input, false, false, 2); - assert_eq!(aligned_columns_noheaders, separator_noheaders); - assert_eq!(aligned_columns_with_headers, separator_with_headers); - } - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use super::FromSsv; - use crate::examples::test as test_examples; - - test_examples(FromSsv {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/toml.rs b/old_nushell/crates/nu-command/src/commands/formats/from/toml.rs deleted file mode 100644 index f65cd3d98..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/toml.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -#[derive(Debug, thiserror::Error)] -pub enum DeserializationError { - #[error("Failed to parse input as TOML")] - Toml(#[from] toml::de::Error), - - #[error("Failed to convert to a nushell value")] - Nu(#[from] Box), -} - -pub struct FromToml; - -impl WholeStreamCommand for FromToml { - fn name(&self) -> &str { - "from toml" - } - - fn signature(&self) -> Signature { - Signature::build("from toml") - } - - fn usage(&self) -> &str { - "Parse text as .toml and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_toml(args) - } -} - -pub fn from_toml_string_to_value( - s: String, - tag: impl Into, -) -> Result { - let v: toml::Value = s.parse::()?; - - Ok(nu_serde::to_value(v, tag).map_err(Box::new)?) -} - -pub fn from_toml(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - - let concat_string = input.collect_string(tag.clone())?; - Ok( - match from_toml_string_to_value(concat_string.item, tag.clone()) { - Ok(x) => match x { - Value { - value: UntaggedValue::Table(list), - .. - } => list.into_iter().into_output_stream(), - x => OutputStream::one(x), - }, - Err(_) => { - return Err(ShellError::labeled_error_with_secondary( - "Could not parse as TOML", - "input cannot be parsed as TOML", - &tag, - "value originates from here", - concat_string.tag, - )) - } - }, - ) -} - -#[cfg(test)] -mod tests { - use super::FromToml; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromToml {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/tsv.rs b/old_nushell/crates/nu-command/src/commands/formats/from/tsv.rs deleted file mode 100644 index 4c9c8b610..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/tsv.rs +++ /dev/null @@ -1,50 +0,0 @@ -use super::delimited::from_delimited_data; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::Signature; - -pub struct FromTsv; - -impl WholeStreamCommand for FromTsv { - fn name(&self) -> &str { - "from tsv" - } - - fn signature(&self) -> Signature { - Signature::build("from tsv").switch( - "noheaders", - "don't treat the first row as column names", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Parse text as .tsv and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_tsv(args) - } -} - -fn from_tsv(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let noheaders = args.has_flag("noheaders"); - let input = args.input; - - from_delimited_data(noheaders, '\t', "TSV", input, name) -} - -#[cfg(test)] -mod tests { - use super::FromTsv; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromTsv {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/url.rs b/old_nushell/crates/nu-command/src/commands/formats/from/url.rs deleted file mode 100644 index f3c9e9bac..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/url.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, TaggedDictBuilder, UntaggedValue}; - -pub struct FromUrl; - -impl WholeStreamCommand for FromUrl { - fn name(&self) -> &str { - "from url" - } - - fn signature(&self) -> Signature { - Signature::build("from url") - } - - fn usage(&self) -> &str { - "Parse url-encoded string as a table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_url(args) - } -} - -fn from_url(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - - let concat_string = input.collect_string(tag.clone())?; - - let result = serde_urlencoded::from_str::>(&concat_string.item); - - match result { - Ok(result) => { - let mut row = TaggedDictBuilder::new(tag); - - for (k, v) in result { - row.insert_untagged(k, UntaggedValue::string(v)); - } - - Ok(OutputStream::one(row.into_value())) - } - _ => Err(ShellError::labeled_error_with_secondary( - "String not compatible with url-encoding", - "input not url-encoded", - tag, - "value originates from here", - concat_string.tag, - )), - } -} - -#[cfg(test)] -mod tests { - use super::FromUrl; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromUrl {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/vcf.rs b/old_nushell/crates/nu-command/src/commands/formats/from/vcf.rs deleted file mode 100644 index f5b7d1f24..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/vcf.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::prelude::*; -use ical::parser::vcard::component::*; -use ical::property::Property; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value}; - -pub struct FromVcf; - -impl WholeStreamCommand for FromVcf { - fn name(&self) -> &str { - "from vcf" - } - - fn signature(&self) -> Signature { - Signature::build("from vcf") - } - - fn usage(&self) -> &str { - "Parse text as .vcf and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_vcf(args) - } -} - -fn from_vcf(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - - let input_string = input.collect_string(tag.clone())?.item; - let input_bytes = input_string.into_bytes(); - let cursor = std::io::Cursor::new(input_bytes); - let parser = ical::VcardParser::new(cursor); - - let iter = parser.map(move |contact| match contact { - Ok(c) => contact_to_value(c, tag.clone()), - Err(_) => Value::error(ShellError::labeled_error( - "Could not parse as .vcf", - "input cannot be parsed as .vcf", - tag.clone(), - )), - }); - - let collected: Vec<_> = iter.collect(); - - Ok(collected.into_iter().into_output_stream()) -} - -fn contact_to_value(contact: VcardContact, tag: Tag) -> Value { - let mut row = TaggedDictBuilder::new(tag.clone()); - row.insert_untagged("properties", properties_to_value(contact.properties, tag)); - row.into_value() -} - -fn properties_to_value(properties: Vec, tag: Tag) -> UntaggedValue { - UntaggedValue::table( - &properties - .into_iter() - .map(|prop| { - let mut row = TaggedDictBuilder::new(tag.clone()); - - let name = UntaggedValue::string(prop.name); - let value = match prop.value { - Some(val) => UntaggedValue::string(val), - None => UntaggedValue::Primitive(Primitive::Nothing), - }; - let params = match prop.params { - Some(param_list) => params_to_value(param_list, tag.clone()).into(), - None => UntaggedValue::Primitive(Primitive::Nothing), - }; - - row.insert_untagged("name", name); - row.insert_untagged("value", value); - row.insert_untagged("params", params); - row.into_value() - }) - .collect::>(), - ) -} - -fn params_to_value(params: Vec<(String, Vec)>, tag: Tag) -> Value { - let mut row = TaggedDictBuilder::new(tag); - - for (param_name, param_values) in params { - let values: Vec = param_values.into_iter().map(|val| val.into()).collect(); - let values = UntaggedValue::table(&values); - row.insert_untagged(param_name, values); - } - - row.into_value() -} - -#[cfg(test)] -mod tests { - use super::FromVcf; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromVcf {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/xlsx.rs b/old_nushell/crates/nu-command/src/commands/formats/from/xlsx.rs deleted file mode 100644 index 0bf2c0d6b..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/xlsx.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::prelude::*; -use calamine::*; -use nu_data::TaggedListBuilder; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value}; -use std::io::Cursor; - -pub struct FromXlsx; - -impl WholeStreamCommand for FromXlsx { - fn name(&self) -> &str { - "from xlsx" - } - - fn signature(&self) -> Signature { - Signature::build("from xlsx") - .switch( - "noheaders", - "don't treat the first row as column names", - Some('n'), - ) - .named( - "sheets", - SyntaxShape::Table, - "Only convert specified sheets", - Some('s'), - ) - } - - fn usage(&self) -> &str { - "Parse binary Excel(.xlsx) data and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_xlsx(args) - } -} - -// Adapted from crates/nu-command/src/commands/dataframe/utils.rs -fn convert_columns(columns: &[Value]) -> Result, ShellError> { - let res = columns - .iter() - .map(|value| match &value.value { - UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()), - _ => Err(ShellError::labeled_error( - "Incorrect column format", - "Only string as column name", - &value.tag, - )), - }) - .collect::, _>>()?; - - Ok(res) -} - -fn from_xlsx(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let span = tag.span; - - let mut sel_sheets = vec![]; - - if let Some(columns) = args.get_flag::>("sheets")? { - sel_sheets = convert_columns(columns.as_slice())?; - } - - let value = args.input.collect_binary(tag.clone())?; - - let buf: Cursor> = Cursor::new(value.item); - let mut xls = Xlsx::<_>::new(buf).map_err(|_| { - ShellError::labeled_error("Could not load xlsx file", "could not load xlsx file", &tag) - })?; - - let mut dict = TaggedDictBuilder::new(&tag); - - let mut sheet_names = xls.sheet_names().to_owned(); - if !sel_sheets.is_empty() { - sheet_names.retain(|e| sel_sheets.contains(e)); - } - - for sheet_name in &sheet_names { - let mut sheet_output = TaggedListBuilder::new(&tag); - - if let Some(Ok(current_sheet)) = xls.worksheet_range(sheet_name) { - for row in current_sheet.rows() { - let mut row_output = TaggedDictBuilder::new(&tag); - for (i, cell) in row.iter().enumerate() { - let value = match cell { - DataType::Empty => UntaggedValue::nothing(), - DataType::String(s) => UntaggedValue::string(s), - DataType::Float(f) => UntaggedValue::decimal_from_float(*f, span), - DataType::Int(i) => UntaggedValue::int(*i), - DataType::Bool(b) => UntaggedValue::boolean(*b), - _ => UntaggedValue::nothing(), - }; - - row_output.insert_untagged(&format!("Column{}", i), value); - } - - sheet_output.push_untagged(row_output.into_untagged_value()); - } - - dict.insert_untagged(sheet_name, sheet_output.into_untagged_value()); - } else { - return Err(ShellError::labeled_error( - "Could not load sheet", - "could not load sheet", - &tag, - )); - } - } - - Ok(OutputStream::one(dict.into_value())) -} - -#[cfg(test)] -mod tests { - use super::FromXlsx; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromXlsx {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/xml.rs b/old_nushell/crates/nu-command/src/commands/formats/from/xml.rs deleted file mode 100644 index 34a94c6fc..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/xml.rs +++ /dev/null @@ -1,302 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value}; - -pub struct FromXml; - -impl WholeStreamCommand for FromXml { - fn name(&self) -> &str { - "from xml" - } - - fn signature(&self) -> Signature { - Signature::build("from xml") - } - - fn usage(&self) -> &str { - "Parse text as .xml and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_xml(args) - } -} - -fn from_attributes_to_value(attributes: &[roxmltree::Attribute], tag: impl Into) -> Value { - let tag = tag.into(); - - let mut collected = TaggedDictBuilder::new(tag); - for a in attributes { - collected.insert_untagged(String::from(a.name()), UntaggedValue::string(a.value())); - } - - collected.into_value() -} - -fn from_node_to_value(n: &roxmltree::Node, tag: impl Into) -> Value { - let tag = tag.into(); - - if n.is_element() { - let name = n.tag_name().name().trim().to_string(); - - let mut children_values = vec![]; - for c in n.children() { - children_values.push(from_node_to_value(&c, &tag)); - } - - let children_values: Vec = children_values - .into_iter() - .filter(|x| match x { - Value { - value: UntaggedValue::Primitive(Primitive::String(f)), - .. - } => { - !f.trim().is_empty() // non-whitespace characters? - } - _ => true, - }) - .collect(); - - let mut collected = TaggedDictBuilder::new(&tag); - - let attribute_value: Value = from_attributes_to_value(n.attributes(), &tag); - - let mut row = TaggedDictBuilder::new(&tag); - row.insert_untagged( - String::from("children"), - UntaggedValue::Table(children_values), - ); - row.insert_untagged(String::from("attributes"), attribute_value); - collected.insert_untagged(name, row.into_value()); - - collected.into_value() - } else if n.is_comment() { - UntaggedValue::string("").into_value(tag) - } else if n.is_pi() { - UntaggedValue::string("").into_value(tag) - } else if n.is_text() { - match n.text() { - Some(text) => UntaggedValue::string(text).into_value(tag), - None => UntaggedValue::string("").into_value(tag), - } - } else { - UntaggedValue::string("").into_value(tag) - } -} - -fn from_document_to_value(d: &roxmltree::Document, tag: impl Into) -> Value { - from_node_to_value(&d.root_element(), tag) -} - -pub fn from_xml_string_to_value(s: String, tag: impl Into) -> Result { - let parsed = roxmltree::Document::parse(&s)?; - Ok(from_document_to_value(&parsed, tag)) -} - -fn from_xml(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - - let concat_string = input.collect_string(tag.clone())?; - - Ok( - match from_xml_string_to_value(concat_string.item, tag.clone()) { - Ok(x) => match x { - Value { - value: UntaggedValue::Table(list), - .. - } => list.into_iter().into_output_stream(), - x => OutputStream::one(x), - }, - Err(_) => { - return Err(ShellError::labeled_error_with_secondary( - "Could not parse as XML", - "input cannot be parsed as XML", - &tag, - "value originates from here", - &concat_string.tag, - )) - } - }, - ) -} - -#[cfg(test)] -mod tests { - use super::*; - - use indexmap::IndexMap; - use nu_protocol::{UntaggedValue, Value}; - - fn string(input: impl Into) -> Value { - UntaggedValue::string(input.into()).into_untagged_value() - } - - fn row(entries: IndexMap) -> Value { - UntaggedValue::row(entries).into_untagged_value() - } - - fn table(list: &[Value]) -> Value { - UntaggedValue::table(list).into_untagged_value() - } - - fn parse(xml: &str) -> Result { - from_xml_string_to_value(xml.to_string(), Tag::unknown()) - } - - #[test] - fn parses_empty_element() -> Result<(), roxmltree::Error> { - let source = ""; - - assert_eq!( - parse(source)?, - row(indexmap! { - "nu".into() => row(indexmap! { - "children".into() => table(&[]), - "attributes".into() => row(indexmap! {}) - }) - }) - ); - - Ok(()) - } - - #[test] - fn parses_element_with_text() -> Result<(), roxmltree::Error> { - let source = "La era de los tres caballeros"; - - assert_eq!( - parse(source)?, - row(indexmap! { - "nu".into() => row(indexmap! { - "children".into() => table(&[string("La era de los tres caballeros")]), - "attributes".into() => row(indexmap! {}) - }) - }) - ); - - Ok(()) - } - - #[test] - fn parses_element_with_elements() -> Result<(), roxmltree::Error> { - let source = "\ - - Andrés - Jonathan - Yehuda -"; - - assert_eq!( - parse(source)?, - row(indexmap! { - "nu".into() => row(indexmap! { - "children".into() => table(&[ - row(indexmap! { - "dev".into() => row(indexmap! { - "children".into() => table(&[string("Andrés")]), - "attributes".into() => row(indexmap! {}) - }) - }), - row(indexmap! { - "dev".into() => row(indexmap! { - "children".into() => table(&[string("Jonathan")]), - "attributes".into() => row(indexmap! {}) - }) - }), - row(indexmap! { - "dev".into() => row(indexmap! { - "children".into() => table(&[string("Yehuda")]), - "attributes".into() => row(indexmap! {}) - }) - }) - ]), - "attributes".into() => row(indexmap! {}) - }) - }) - ); - - Ok(()) - } - - #[test] - fn parses_element_with_attribute() -> Result<(), roxmltree::Error> { - let source = "\ - -"; - - assert_eq!( - parse(source)?, - row(indexmap! { - "nu".into() => row(indexmap! { - "children".into() => table(&[]), - "attributes".into() => row(indexmap! { - "version".into() => string("2.0") - }) - }) - }) - ); - - Ok(()) - } - - #[test] - fn parses_element_with_attribute_and_element() -> Result<(), roxmltree::Error> { - let source = "\ - - 2.0 -"; - - assert_eq!( - parse(source)?, - row(indexmap! { - "nu".into() => row(indexmap! { - "children".into() => table(&[ - row(indexmap! { - "version".into() => row(indexmap! { - "children".into() => table(&[string("2.0")]), - "attributes".into() => row(indexmap! {}) - }) - }) - ]), - "attributes".into() => row(indexmap! { - "version".into() => string("2.0") - }) - }) - }) - ); - - Ok(()) - } - - #[test] - fn parses_element_with_multiple_attributes() -> Result<(), roxmltree::Error> { - let source = "\ - -"; - - assert_eq!( - parse(source)?, - row(indexmap! { - "nu".into() => row(indexmap! { - "children".into() => table(&[]), - "attributes".into() => row(indexmap! { - "version".into() => string("2.0"), - "age".into() => string("25") - }) - }) - }) - ); - - Ok(()) - } - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use super::FromXml; - use crate::examples::test as test_examples; - - test_examples(FromXml {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/from/yaml.rs b/old_nushell/crates/nu-command/src/commands/formats/from/yaml.rs deleted file mode 100644 index b371074a1..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/from/yaml.rs +++ /dev/null @@ -1,258 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, TaggedDictBuilder, UntaggedValue, Value}; - -pub struct FromYaml; - -impl WholeStreamCommand for FromYaml { - fn name(&self) -> &str { - "from yaml" - } - - fn signature(&self) -> Signature { - Signature::build("from yaml") - } - - fn usage(&self) -> &str { - "Parse text as .yaml/.yml and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_yaml(args) - } -} - -pub struct FromYml; - -impl WholeStreamCommand for FromYml { - fn name(&self) -> &str { - "from yml" - } - - fn signature(&self) -> Signature { - Signature::build("from yml") - } - - fn usage(&self) -> &str { - "Parse text as .yaml/.yml and create table." - } - - fn run(&self, args: CommandArgs) -> Result { - from_yaml(args) - } -} - -fn convert_yaml_value_to_nu_value( - v: &serde_yaml::Value, - tag: impl Into, -) -> Result { - let tag = tag.into(); - let span = tag.span; - - let err_not_compatible_number = ShellError::labeled_error( - "Expected a compatible number", - "expected a compatible number", - &tag, - ); - Ok(match v { - serde_yaml::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(tag), - serde_yaml::Value::Number(n) if n.is_i64() => { - UntaggedValue::int(n.as_i64().ok_or(err_not_compatible_number)?).into_value(tag) - } - serde_yaml::Value::Number(n) if n.is_f64() => { - UntaggedValue::decimal_from_float(n.as_f64().ok_or(err_not_compatible_number)?, span) - .into_value(tag) - } - serde_yaml::Value::String(s) => UntaggedValue::string(s).into_value(tag), - serde_yaml::Value::Sequence(a) => { - let result: Result, ShellError> = a - .iter() - .map(|x| convert_yaml_value_to_nu_value(x, &tag)) - .collect(); - UntaggedValue::Table(result?).into_value(tag) - } - serde_yaml::Value::Mapping(t) => { - let mut collected = TaggedDictBuilder::new(&tag); - - for (k, v) in t { - // A ShellError that we re-use multiple times in the Mapping scenario - let err_unexpected_map = ShellError::labeled_error( - format!("Unexpected YAML:\nKey: {:?}\nValue: {:?}", k, v), - "unexpected", - tag.clone(), - ); - match (k, v) { - (serde_yaml::Value::String(k), _) => { - collected.insert_value(k.clone(), convert_yaml_value_to_nu_value(v, &tag)?); - } - // Hard-code fix for cases where "v" is a string without quotations with double curly braces - // e.g. k = value - // value: {{ something }} - // Strangely, serde_yaml returns - // "value" -> Mapping(Mapping { map: {Mapping(Mapping { map: {String("something"): Null} }): Null} }) - (serde_yaml::Value::Mapping(m), serde_yaml::Value::Null) => { - return m - .iter() - .take(1) - .collect_vec() - .first() - .and_then(|e| match e { - (serde_yaml::Value::String(s), serde_yaml::Value::Null) => Some( - UntaggedValue::string("{{ ".to_owned() + s + " }}") - .into_value(tag), - ), - _ => None, - }) - .ok_or(err_unexpected_map); - } - (_, _) => { - return Err(err_unexpected_map); - } - } - } - - collected.into_value() - } - serde_yaml::Value::Null => UntaggedValue::Primitive(Primitive::Nothing).into_value(tag), - x => unimplemented!("Unsupported yaml case: {:?}", x), - }) -} - -pub fn from_yaml_string_to_value(s: String, tag: impl Into) -> Result { - let tag = tag.into(); - - let mut documents = vec![]; - - for document in serde_yaml::Deserializer::from_str(&s) { - let v: serde_yaml::Value = serde_yaml::Value::deserialize(document).map_err(|x| { - ShellError::labeled_error( - format!("Could not load yaml: {}", x), - "could not load yaml from text", - &tag, - ) - })?; - - documents.push(convert_yaml_value_to_nu_value(&v, tag.clone())?); - } - - match documents.len() { - 0 => Ok(UntaggedValue::nothing().into_value(tag)), - 1 => Ok(documents.remove(0)), - _ => Ok(UntaggedValue::Table(documents).into_value(tag)), - } -} - -fn from_yaml(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - - let concat_string = input.collect_string(tag.clone())?; - - match from_yaml_string_to_value(concat_string.item, tag.clone()) { - Ok(x) => match x { - Value { - value: UntaggedValue::Table(list), - .. - } => Ok(list.into_iter().into_output_stream()), - x => Ok(OutputStream::one(x)), - }, - Err(_) => Err(ShellError::labeled_error_with_secondary( - "Could not parse as YAML", - "input cannot be parsed as YAML", - &tag, - "value originates from here", - &concat_string.tag, - )), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::*; - use nu_protocol::row; - use nu_test_support::value::int; - use nu_test_support::value::row; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FromYaml {}) - } - - #[test] - fn test_problematic_yaml() { - struct TestCase { - description: &'static str, - input: &'static str, - expected: Result, - } - let tt: Vec = vec![ - TestCase { - description: "Double Curly Braces With Quotes", - input: r#"value: "{{ something }}""#, - expected: Ok(row!["value".to_owned() => string("{{ something }}")]), - }, - TestCase { - description: "Double Curly Braces Without Quotes", - input: r#"value: {{ something }}"#, - expected: Ok(row!["value".to_owned() => string("{{ something }}")]), - }, - ]; - for tc in tt { - let actual = from_yaml_string_to_value(tc.input.to_owned(), Tag::default()); - if actual.is_err() { - assert!( - tc.expected.is_err(), - "actual is Err for test:\nTest Description {}\nErr: {:?}", - tc.description, - actual - ); - } else { - assert_eq!(actual, tc.expected, "{}", tc.description); - } - } - } - - #[test] - fn test_empty_yaml() { - let input = ""; - - let expected = UntaggedValue::nothing().into_value(Tag::default()); - - let actual = from_yaml_string_to_value(input.to_owned(), Tag::default()); - - assert_eq!(Ok(expected), actual); - } - - #[test] - fn test_single_doc_yaml() { - let input = "k: 107\nj: '106'\n"; - - let expected = - UntaggedValue::row(indexmap! {"k".into() => int(107), "j".into() => string("106") }) - .into_value(Tag::default()); - - let actual = from_yaml_string_to_value(input.to_owned(), Tag::default()); - - assert_eq!(Ok(expected), actual); - } - - #[test] - fn test_multidoc_yaml() { - let input = "---\nk: 107\n---\nj: '106'\n"; - - let expected = UntaggedValue::table(&[ - row(indexmap! {"k".into() => int(107) }), - row(indexmap! {"j".into() => string("106") }), - ]) - .into_value(Tag::default()); - - let actual = from_yaml_string_to_value(input.to_owned(), Tag::default()); - - assert_eq!(Ok(expected), actual); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/mod.rs b/old_nushell/crates/nu-command/src/commands/formats/mod.rs deleted file mode 100644 index 86f06f85f..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod from; -mod to; - -pub use from::*; -pub use to::*; diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/command.rs b/old_nushell/crates/nu-command/src/commands/formats/to/command.rs deleted file mode 100644 index 75573f098..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/command.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -#[derive(Clone)] -pub struct To; - -impl WholeStreamCommand for To { - fn name(&self) -> &str { - "to" - } - - fn signature(&self) -> Signature { - Signature::build("to") - } - - fn usage(&self) -> &str { - "Convert table into an output format (based on subcommand, like csv, html, json, yaml)." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&To, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::To; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(To {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/csv.rs b/old_nushell/crates/nu-command/src/commands/formats/to/csv.rs deleted file mode 100644 index b7069c051..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/csv.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::commands::formats::to::delimited::to_delimited_data; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct ToCsv; - -impl WholeStreamCommand for ToCsv { - fn name(&self) -> &str { - "to csv" - } - - fn signature(&self) -> Signature { - Signature::build("to csv") - .named( - "separator", - SyntaxShape::String, - "a character to separate columns, defaults to ','", - Some('s'), - ) - .switch( - "noheaders", - "do not output the columns names as the first row", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Convert table into .csv text " - } - - fn run(&self, args: CommandArgs) -> Result { - to_csv(args) - } -} - -fn to_csv(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let separator: Option = args.get_flag("separator")?; - let noheaders = args.has_flag("noheaders"); - let input = args.input; - let sep = match separator { - Some(Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - tag, - .. - }) => { - if s == r"\t" { - '\t' - } else { - let vec_s: Vec = s.chars().collect(); - if vec_s.len() != 1 { - return Err(ShellError::labeled_error( - "Expected a single separator char from --separator", - "requires a single character string input", - tag, - )); - }; - vec_s[0] - } - } - _ => ',', - }; - - to_delimited_data(noheaders, sep, "CSV", input, name) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::ToCsv; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToCsv {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/delimited.rs b/old_nushell/crates/nu-command/src/commands/formats/to/delimited.rs deleted file mode 100644 index 2b48d61f1..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/delimited.rs +++ /dev/null @@ -1,220 +0,0 @@ -use crate::prelude::*; -use csv::WriterBuilder; -use indexmap::{indexset, IndexSet}; -use nu_errors::ShellError; -use nu_protocol::{Primitive, UntaggedValue, Value}; -use nu_source::Spanned; -use nu_value_ext::{as_string, ValueExt}; - -fn from_value_to_delimited_string( - tagged_value: &Value, - separator: char, -) -> Result { - let v = &tagged_value.value; - - match v { - UntaggedValue::Row(o) => { - let mut wtr = WriterBuilder::new() - .delimiter(separator as u8) - .from_writer(vec![]); - let mut fields: VecDeque = VecDeque::new(); - let mut values: VecDeque = VecDeque::new(); - - for (k, v) in &o.entries { - fields.push_back(k.clone()); - - values.push_back(to_string_tagged_value(v)?); - } - - wtr.write_record(fields).expect("can not write."); - wtr.write_record(values).expect("can not write."); - - let v = String::from_utf8(wtr.into_inner().map_err(|_| { - ShellError::labeled_error( - "Could not convert record", - "original value", - &tagged_value.tag, - ) - })?) - .map_err(|_| { - ShellError::labeled_error( - "Could not convert record", - "original value", - &tagged_value.tag, - ) - })?; - Ok(v) - } - UntaggedValue::Table(list) => { - let mut wtr = WriterBuilder::new() - .delimiter(separator as u8) - .from_writer(vec![]); - - let merged_descriptors = merge_descriptors(list); - - if merged_descriptors.is_empty() { - wtr.write_record( - list.iter() - .map(|ele| to_string_tagged_value(ele).unwrap_or_else(|_| String::new())) - .collect::>(), - ) - .expect("can not write"); - } else { - wtr.write_record(merged_descriptors.iter().map(|item| &item.item[..])) - .expect("can not write."); - - for l in list { - let mut row = vec![]; - for desc in &merged_descriptors { - row.push(match l.get_data_by_key(desc.borrow_spanned()) { - Some(s) => to_string_tagged_value(&s)?, - None => String::new(), - }); - } - wtr.write_record(&row).expect("can not write"); - } - } - let v = String::from_utf8(wtr.into_inner().map_err(|_| { - ShellError::labeled_error( - "Could not convert record", - "original value", - &tagged_value.tag, - ) - })?) - .map_err(|_| { - ShellError::labeled_error( - "Could not convert record", - "original value", - &tagged_value.tag, - ) - })?; - Ok(v) - } - _ => to_string_tagged_value(tagged_value), - } -} - -// NOTE: could this be useful more widely and implemented on Value ? -pub fn clone_tagged_value(v: &Value) -> Value { - match &v.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - UntaggedValue::Primitive(Primitive::String(s.clone())) - } - UntaggedValue::Primitive(Primitive::Nothing) => { - UntaggedValue::Primitive(Primitive::Nothing) - } - UntaggedValue::Primitive(Primitive::Boolean(b)) => { - UntaggedValue::Primitive(Primitive::Boolean(*b)) - } - UntaggedValue::Primitive(Primitive::Decimal(f)) => { - UntaggedValue::Primitive(Primitive::Decimal(f.clone())) - } - UntaggedValue::Primitive(Primitive::Int(i)) => UntaggedValue::Primitive(Primitive::Int(*i)), - UntaggedValue::Primitive(Primitive::FilePath(x)) => { - UntaggedValue::Primitive(Primitive::FilePath(x.clone())) - } - UntaggedValue::Primitive(Primitive::Filesize(b)) => { - UntaggedValue::Primitive(Primitive::Filesize(*b)) - } - UntaggedValue::Primitive(Primitive::Date(d)) => { - UntaggedValue::Primitive(Primitive::Date(*d)) - } - UntaggedValue::Row(o) => UntaggedValue::Row(o.clone()), - UntaggedValue::Table(l) => UntaggedValue::Table(l.clone()), - UntaggedValue::Block(_) => UntaggedValue::Primitive(Primitive::Nothing), - _ => UntaggedValue::Primitive(Primitive::Nothing), - } - .into_value(v.tag.clone()) -} - -// NOTE: could this be useful more widely and implemented on Value ? -fn to_string_tagged_value(v: &Value) -> Result { - match &v.value { - UntaggedValue::Primitive( - Primitive::String(_) - | Primitive::Filesize(_) - | Primitive::Boolean(_) - | Primitive::Decimal(_) - | Primitive::FilePath(_) - | Primitive::Int(_) - | Primitive::BigInt(_), - ) => as_string(v), - UntaggedValue::Primitive(Primitive::Date(d)) => Ok(d.to_string()), - UntaggedValue::Primitive(Primitive::Nothing) => Ok(String::new()), - UntaggedValue::Table(_) => Ok(String::from("[Table]")), - UntaggedValue::Row(_) => Ok(String::from("[Row]")), - _ => Err(ShellError::labeled_error( - "Unexpected value", - "", - v.tag.clone(), - )), - } -} - -fn merge_descriptors(values: &[Value]) -> Vec> { - let mut ret: Vec> = vec![]; - let mut seen: IndexSet = indexset! {}; - for value in values { - for desc in value.data_descriptors() { - if !seen.contains(&desc) { - seen.insert(desc.clone()); - ret.push(desc.spanned(value.tag.span)); - } - } - } - ret -} - -pub fn to_delimited_data( - noheaders: bool, - sep: char, - format_name: &'static str, - input: InputStream, - name: Tag, -) -> Result { - let name_tag = name; - let name_span = name_tag.span; - - let input: Vec = input.collect(); - - let to_process_input = match input.len() { - x if x > 1 => { - let tag = input[0].tag.clone(); - vec![Value { - value: UntaggedValue::Table(input), - tag, - }] - } - 1 => input, - _ => vec![], - }; - - Ok((to_process_input.into_iter().map(move |value| { - match from_value_to_delimited_string(&clone_tagged_value(&value), sep) { - Ok(mut x) => { - if noheaders { - if let Some(second_line) = x.find('\n') { - let start = second_line + 1; - x.replace_range(0..start, ""); - } - } - UntaggedValue::Primitive(Primitive::String(x)).into_value(&name_tag) - } - Err(_) => { - let expected = format!( - "Expected a table with {}-compatible structure from pipeline", - format_name - ); - let requires = format!("requires {}-compatible input", format_name); - Value::error(ShellError::labeled_error_with_secondary( - expected, - requires, - name_span, - "originates from here".to_string(), - value.tag.span, - )) - } - } - })) - .into_output_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/html.rs b/old_nushell/crates/nu-command/src/commands/formats/to/html.rs deleted file mode 100644 index 991f17e69..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/html.rs +++ /dev/null @@ -1,743 +0,0 @@ -use crate::prelude::*; - -use nu_data::value::format_leaf; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::{AnchorLocation, Tagged}; -use regex::Regex; -use rust_embed::RustEmbed; -use serde::{Deserialize, Serialize}; -use std::borrow::Cow; -use std::collections::HashMap; -use std::error::Error; -use std::fmt::Write; - -#[derive(Serialize, Deserialize, Debug)] -pub struct HtmlThemes { - themes: Vec, -} - -#[allow(non_snake_case)] -#[derive(Serialize, Deserialize, Debug)] -pub struct HtmlTheme { - name: String, - black: String, - red: String, - green: String, - yellow: String, - blue: String, - purple: String, - cyan: String, - white: String, - brightBlack: String, - brightRed: String, - brightGreen: String, - brightYellow: String, - brightBlue: String, - brightPurple: String, - brightCyan: String, - brightWhite: String, - background: String, - foreground: String, -} - -impl Default for HtmlThemes { - fn default() -> Self { - HtmlThemes { - themes: vec![HtmlTheme::default()], - } - } -} - -impl Default for HtmlTheme { - fn default() -> Self { - HtmlTheme { - name: "nu_default".to_string(), - black: "black".to_string(), - red: "red".to_string(), - green: "green".to_string(), - yellow: "#717100".to_string(), - blue: "blue".to_string(), - purple: "#c800c8".to_string(), - cyan: "#037979".to_string(), - white: "white".to_string(), - brightBlack: "black".to_string(), - brightRed: "red".to_string(), - brightGreen: "green".to_string(), - brightYellow: "#717100".to_string(), - brightBlue: "blue".to_string(), - brightPurple: "#c800c8".to_string(), - brightCyan: "#037979".to_string(), - brightWhite: "white".to_string(), - background: "white".to_string(), - foreground: "black".to_string(), - } - } -} - -#[derive(RustEmbed)] -#[folder = "assets/"] -struct Assets; - -pub struct ToHtml; - -impl WholeStreamCommand for ToHtml { - fn name(&self) -> &str { - "to html" - } - - fn signature(&self) -> Signature { - Signature::build("to html") - .switch("html_color", "change ansi colors to html colors", Some('c')) - .switch("no_color", "remove all ansi colors in output", Some('n')) - .switch( - "dark", - "indicate your background color is a darker color", - Some('d'), - ) - .switch( - "partial", - "only output the html for the content itself", - Some('p'), - ) - .named( - "theme", - SyntaxShape::String, - "the name of the theme to use (github, blulocolight, ...)", - Some('t'), - ) - .switch("list", "list the names of all available themes", Some('l')) - } - - fn usage(&self) -> &str { - "Convert table into simple HTML" - } - - fn run(&self, args: CommandArgs) -> Result { - to_html(args) - } -} - -fn get_theme_from_asset_file( - is_dark: bool, - theme: &Option>, - theme_tag: &Tag, -) -> Result, ShellError> { - let theme_name = match theme { - Some(s) => s.as_str(), - None => "default", // There is no theme named "default" so this will be HtmlTheme::default(), which is "nu_default". - }; - - // 228 themes come from - // https://github.com/mbadolato/iTerm2-Color-Schemes/tree/master/windowsterminal - // we should find a hit on any name in there - let asset = get_asset_by_name_as_html_themes("228_themes.zip", "228_themes.json"); - - // If asset doesn't work, make sure to return the default theme - let asset = match asset { - Ok(a) => a, - _ => HtmlThemes::default(), - }; - - // Find the theme by theme name - let th = asset - .themes - .iter() - .find(|&n| n.name.to_lowercase() == theme_name.to_lowercase()); // case insensitive search - - // If no theme is found by the name provided, ensure we return the default theme - let default_theme = HtmlTheme::default(); - let th = match th { - Some(t) => t, - None => &default_theme, - }; - - // this just means no theme was passed in - if th.name.to_lowercase().eq(&"nu_default".to_string()) - // this means there was a theme passed in - && theme.is_some() - { - return Err(ShellError::labeled_error( - "Error finding theme name", - "Error finding theme name", - theme_tag.span, - )); - } - - Ok(convert_html_theme_to_hash_map(is_dark, th)) -} - -#[allow(unused_variables)] -fn get_asset_by_name_as_html_themes( - zip_name: &str, - json_name: &str, -) -> Result> { - match Assets::get(zip_name) { - Some(content) => { - let asset: Vec = match content { - Cow::Borrowed(bytes) => bytes.into(), - Cow::Owned(bytes) => bytes, - }; - let reader = std::io::Cursor::new(asset); - #[cfg(feature = "zip")] - { - use std::io::Read; - let mut archive = zip::ZipArchive::new(reader)?; - let mut zip_file = archive.by_name(json_name)?; - let mut contents = String::new(); - zip_file.read_to_string(&mut contents)?; - Ok(serde_json::from_str(&contents)?) - } - #[cfg(not(feature = "zip"))] - { - let th = HtmlThemes::default(); - Ok(th) - } - } - None => { - let th = HtmlThemes::default(); - Ok(th) - } - } -} - -fn convert_html_theme_to_hash_map( - is_dark: bool, - theme: &HtmlTheme, -) -> HashMap<&'static str, String> { - let mut hm: HashMap<&str, String> = HashMap::new(); - - hm.insert("bold_black", theme.brightBlack[..].to_string()); - hm.insert("bold_red", theme.brightRed[..].to_string()); - hm.insert("bold_green", theme.brightGreen[..].to_string()); - hm.insert("bold_yellow", theme.brightYellow[..].to_string()); - hm.insert("bold_blue", theme.brightBlue[..].to_string()); - hm.insert("bold_magenta", theme.brightPurple[..].to_string()); - hm.insert("bold_cyan", theme.brightCyan[..].to_string()); - hm.insert("bold_white", theme.brightWhite[..].to_string()); - - hm.insert("black", theme.black[..].to_string()); - hm.insert("red", theme.red[..].to_string()); - hm.insert("green", theme.green[..].to_string()); - hm.insert("yellow", theme.yellow[..].to_string()); - hm.insert("blue", theme.blue[..].to_string()); - hm.insert("magenta", theme.purple[..].to_string()); - hm.insert("cyan", theme.cyan[..].to_string()); - hm.insert("white", theme.white[..].to_string()); - - // Try to make theme work with light or dark but - // flipping the foreground and background but leave - // the other colors the same. - if is_dark { - hm.insert("background", theme.black[..].to_string()); - hm.insert("foreground", theme.white[..].to_string()); - } else { - hm.insert("background", theme.white[..].to_string()); - hm.insert("foreground", theme.black[..].to_string()); - } - - hm -} - -fn get_list_of_theme_names() -> Vec { - let asset = get_asset_by_name_as_html_themes("228_themes.zip", "228_themes.json"); - - // If asset doesn't work, make sure to return the default theme - let html_themes = match asset { - Ok(a) => a, - _ => HtmlThemes::default(), - }; - - let theme_names: Vec = html_themes.themes.iter().map(|n| n.name.clone()).collect(); - - theme_names -} - -fn to_html(args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - let html_color = args.has_flag("html_color"); - let no_color = args.has_flag("no_color"); - let dark = args.has_flag("dark"); - let partial = args.has_flag("partial"); - let list = args.has_flag("list"); - let theme: Option> = args.get_flag("theme")?; - - let input: Vec = args.input.collect(); - let headers = nu_protocol::merge_descriptors(&input); - let headers = Some(headers) - .filter(|headers| !headers.is_empty() && (headers.len() > 1 || !headers[0].is_empty())); - let mut output_string = String::new(); - let mut regex_hm: HashMap = HashMap::new(); - - if list { - // Get the list of theme names - let theme_names = get_list_of_theme_names(); - - // Put that list into the output string - for s in &theme_names { - writeln!(&mut output_string, "{}", s).unwrap(); - } - - output_string.push_str("\nScreenshots of themes can be found here:\n"); - output_string.push_str("https://github.com/mbadolato/iTerm2-Color-Schemes\n"); - } else { - let theme_tag = match &theme { - Some(v) => &v.tag, - None => &name_tag, - }; - - let color_hm = get_theme_from_asset_file(dark, &theme, theme_tag); - let color_hm = match color_hm { - Ok(c) => c, - _ => { - return Err(ShellError::labeled_error( - "Error finding theme name", - "Error finding theme name", - theme_tag.span, - )) - } - }; - - // change the color of the page - if !partial { - write!( - &mut output_string, - r"", - color_hm - .get("background") - .expect("Error getting background color"), - color_hm - .get("foreground") - .expect("Error getting foreground color") - ) - .unwrap(); - } else { - write!( - &mut output_string, - "
", - color_hm - .get("background") - .expect("Error getting background color"), - color_hm - .get("foreground") - .expect("Error getting foreground color") - ) - .unwrap(); - } - - let inner_value = match input.len() { - 0 => String::default(), - 1 => match headers { - Some(headers) => html_table(input, headers), - None => { - let value = &input[0]; - html_value(value) - } - }, - _ => match headers { - Some(headers) => html_table(input, headers), - None => html_list(input), - }, - }; - - output_string.push_str(&inner_value); - - if !partial { - output_string.push_str(""); - } else { - output_string.push_str("
") - } - - // Check to see if we want to remove all color or change ansi to html colors - if html_color { - setup_html_color_regexes(&mut regex_hm, &color_hm); - output_string = run_regexes(®ex_hm, &output_string); - } else if no_color { - setup_no_color_regexes(&mut regex_hm); - output_string = run_regexes(®ex_hm, &output_string); - } - } - Ok(OutputStream::one( - UntaggedValue::string(output_string).into_value(name_tag), - )) -} - -fn html_list(list: Vec) -> String { - let mut output_string = String::new(); - output_string.push_str("
    "); - for value in list { - output_string.push_str("
  1. "); - output_string.push_str(&html_value(&value)); - output_string.push_str("
  2. "); - } - output_string.push_str("
"); - output_string -} - -fn html_table(table: Vec, headers: Vec) -> String { - let mut output_string = String::new(); - // Add grid lines to html - // let mut output_string = ""); - - output_string.push_str("
"); - - output_string.push_str(""); - for header in &headers { - output_string.push_str(""); - } - output_string.push_str(""); - - for row in table { - if let UntaggedValue::Row(row) = row.value { - output_string.push_str(""); - for header in &headers { - let data = row.get_data(header); - output_string.push_str(""); - } - output_string.push_str(""); - } - } - output_string.push_str("
"); - output_string.push_str(&htmlescape::encode_minimal(header)); - output_string.push_str("
"); - output_string.push_str(&html_value(data.borrow())); - output_string.push_str("
"); - - output_string -} - -fn html_value(value: &Value) -> String { - let mut output_string = String::new(); - match &value.value { - UntaggedValue::Primitive(Primitive::Binary(b)) => { - // This might be a bit much, but it's fun :) - match &value.tag.anchor { - Some(AnchorLocation::Url(f)) | Some(AnchorLocation::File(f)) => { - let extension = f.split('.').last().map(String::from); - match extension { - Some(s) - if ["png", "jpg", "bmp", "gif", "tiff", "jpeg"] - .contains(&s.to_lowercase().as_str()) => - { - output_string.push_str(""); - } - _ => { - let output = nu_pretty_hex::pretty_hex(&b); - - output_string.push_str("
");
-                            output_string.push_str(&output);
-                            output_string.push_str("
"); - } - } - } - _ => { - let output = nu_pretty_hex::pretty_hex(&b); - - output_string.push_str("
");
-                    output_string.push_str(&output);
-                    output_string.push_str("
"); - } - } - } - UntaggedValue::Primitive(Primitive::String(ref b)) => { - // This might be a bit much, but it's fun :) - match &value.tag.anchor { - Some(AnchorLocation::Url(f)) | Some(AnchorLocation::File(f)) => { - let extension = f.split('.').last().map(String::from); - match extension { - Some(s) if s.to_lowercase() == "svg" => { - output_string.push_str(""); - return output_string; - } - _ => {} - } - } - _ => {} - } - output_string.push_str( - &htmlescape::encode_minimal(&format_leaf(&value.value).plain_string(100_000)) - .replace("\n", "
"), - ); - } - other => output_string.push_str( - &htmlescape::encode_minimal(&format_leaf(other).plain_string(100_000)) - .replace("\n", "
"), - ), - } - output_string -} - -fn setup_html_color_regexes( - hash: &mut HashMap, - color_hm: &HashMap<&str, String>, -) { - // All the bold colors - hash.insert( - 0, - ( - r"(?P\[0m)(?P[[:alnum:][:space:][:punct:]]*)", - // Reset the text color, normal weight font - format!( - r"$word", - color_hm - .get("foreground") - .expect("Error getting reset text color") - ), - ), - ); - hash.insert( - 1, - ( - // Bold Black - r"(?P\[1;30m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("foreground") - .expect("Error getting bold black text color") - ), - ), - ); - hash.insert( - 2, - ( - // Bold Red - r"(?P
\[1;31m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("bold_red") - .expect("Error getting bold red text color"), - ), - ), - ); - hash.insert( - 3, - ( - // Bold Green - r"(?P\[1;32m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("bold_green") - .expect("Error getting bold green text color"), - ), - ), - ); - hash.insert( - 4, - ( - // Bold Yellow - r"(?P\[1;33m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("bold_yellow") - .expect("Error getting bold yellow text color"), - ), - ), - ); - hash.insert( - 5, - ( - // Bold Blue - r"(?P\[1;34m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("bold_blue") - .expect("Error getting bold blue text color"), - ), - ), - ); - hash.insert( - 6, - ( - // Bold Magenta - r"(?P\[1;35m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("bold_magenta") - .expect("Error getting bold magenta text color"), - ), - ), - ); - hash.insert( - 7, - ( - // Bold Cyan - r"(?P\[1;36m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("bold_cyan") - .expect("Error getting bold cyan text color"), - ), - ), - ); - hash.insert( - 8, - ( - // Bold White - // Let's change this to black since the html background - // is white. White on white = no bueno. - r"(?P\[1;37m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("foreground") - .expect("Error getting bold bold white text color"), - ), - ), - ); - // All the normal colors - hash.insert( - 9, - ( - // Black - r"(?P\[30m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("foreground") - .expect("Error getting black text color"), - ), - ), - ); - hash.insert( - 10, - ( - // Red - r"(?P\[31m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm.get("red").expect("Error getting red text color"), - ), - ), - ); - hash.insert( - 11, - ( - // Green - r"(?P\[32m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("green") - .expect("Error getting green text color"), - ), - ), - ); - hash.insert( - 12, - ( - // Yellow - r"(?P\[33m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("yellow") - .expect("Error getting yellow text color"), - ), - ), - ); - hash.insert( - 13, - ( - // Blue - r"(?P\[34m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm.get("blue").expect("Error getting blue text color"), - ), - ), - ); - hash.insert( - 14, - ( - // Magenta - r"(?P\[35m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("magenta") - .expect("Error getting magenta text color"), - ), - ), - ); - hash.insert( - 15, - ( - // Cyan - r"(?P\[36m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm.get("cyan").expect("Error getting cyan text color"), - ), - ), - ); - hash.insert( - 16, - ( - // White - // Let's change this to black since the html background - // is white. White on white = no bueno. - r"(?P\[37m)(?P[[:alnum:][:space:][:punct:]]*)", - format!( - r"$word", - color_hm - .get("foreground") - .expect("Error getting white text color"), - ), - ), - ); -} - -fn setup_no_color_regexes(hash: &mut HashMap) { - // We can just use one regex here because we're just removing ansi sequences - // and not replacing them with html colors. - // attribution: https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python - hash.insert( - 0, - ( - r"(?:\x1B[@-Z\\-_]|[\x80-\x9A\x9C-\x9F]|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~])", - r"$name_group_doesnt_exist".to_string(), - ), - ); -} - -fn run_regexes(hash: &HashMap, contents: &str) -> String { - let mut working_string = contents.to_owned(); - let hash_count: u32 = hash.len() as u32; - for n in 0..hash_count { - let value = hash.get(&n).expect("error getting hash at index"); - //println!("{},{}", value.0, value.1); - let re = Regex::new(value.0).expect("problem with color regex"); - let after = re.replace_all(&working_string, &value.1[..]).to_string(); - working_string = after.clone(); - } - working_string -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::*; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToHtml {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/json.rs b/old_nushell/crates/nu-command/src/commands/formats/to/json.rs deleted file mode 100644 index 43f769ec8..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/json.rs +++ /dev/null @@ -1,256 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::{CoerceInto, ShellError}; -use nu_protocol::{Primitive, Signature, SyntaxShape, UnspannedPathMember, UntaggedValue, Value}; -use serde::Serialize; -use serde_json::json; - -pub struct ToJson; - -impl WholeStreamCommand for ToJson { - fn name(&self) -> &str { - "to json" - } - - fn signature(&self) -> Signature { - Signature::build("to json").named( - "pretty", - SyntaxShape::Int, - "Formats the JSON text with the provided indentation setting", - Some('p'), - ) - } - - fn usage(&self) -> &str { - "Converts table data into JSON text." - } - - fn run(&self, args: CommandArgs) -> Result { - to_json(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: - "Outputs an unformatted JSON string representing the contents of this table", - example: "echo [1 2 3] | to json", - result: Some(vec![Value::from("[1,2,3]")]), - }, - Example { - description: - "Outputs a formatted JSON string representing the contents of this table with an indentation setting of 2 spaces", - example: "echo [1 2 3] | to json --pretty 2", - result: Some(vec![Value::from("[\n 1,\n 2,\n 3\n]")]), - }, - ] - } -} - -pub fn value_to_json_value(v: &Value) -> Result { - Ok(match &v.value { - UntaggedValue::Primitive(Primitive::Boolean(b)) => serde_json::Value::Bool(*b), - UntaggedValue::Primitive(Primitive::Filesize(b)) => serde_json::Value::Number( - serde_json::Number::from(b.to_u64().expect("What about really big numbers")), - ), - UntaggedValue::Primitive(Primitive::Duration(i)) => { - serde_json::Value::String(i.to_string()) - } - UntaggedValue::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()), - UntaggedValue::Primitive(Primitive::EndOfStream) => serde_json::Value::Null, - UntaggedValue::Primitive(Primitive::BeginningOfStream) => serde_json::Value::Null, - UntaggedValue::Primitive(Primitive::Decimal(f)) => { - if let Some(f) = f.to_f64() { - if let Some(num) = serde_json::Number::from_f64( - f.to_f64().expect("TODO: What about really big decimals?"), - ) { - serde_json::Value::Number(num) - } else { - return Err(ShellError::labeled_error( - "Could not convert value to decimal number", - "could not convert to decimal", - &v.tag, - )); - } - } else { - return Err(ShellError::labeled_error( - "Could not convert value to decimal number", - "could not convert to decimal", - &v.tag, - )); - } - } - - UntaggedValue::Primitive(Primitive::Int(i)) => { - serde_json::Value::Number(serde_json::Number::from(*i)) - } - UntaggedValue::Primitive(Primitive::BigInt(i)) => { - serde_json::Value::Number(serde_json::Number::from(CoerceInto::::coerce_into( - i.tagged(&v.tag), - "converting to JSON number", - )?)) - } - UntaggedValue::Primitive(Primitive::Nothing) => serde_json::Value::Null, - UntaggedValue::Primitive(Primitive::GlobPattern(s)) => serde_json::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::ColumnPath(path)) => serde_json::Value::Array( - path.iter() - .map(|x| match &x.unspanned { - UnspannedPathMember::String(string) => { - Ok(serde_json::Value::String(string.clone())) - } - UnspannedPathMember::Int(int) => { - Ok(serde_json::Value::Number(serde_json::Number::from(*int))) - } - }) - .collect::, ShellError>>()?, - ), - UntaggedValue::Primitive(Primitive::FilePath(s)) => { - serde_json::Value::String(s.display().to_string()) - } - - UntaggedValue::Table(l) => serde_json::Value::Array(json_list(l)?), - UntaggedValue::Error(e) => return Err(e.clone()), - UntaggedValue::Block(_) | UntaggedValue::Primitive(Primitive::Range(_)) => { - serde_json::Value::Null - } - #[cfg(feature = "dataframe")] - UntaggedValue::DataFrame(_) | UntaggedValue::FrameStruct(_) => serde_json::Value::Null, - UntaggedValue::Primitive(Primitive::Binary(b)) => serde_json::Value::Array( - b.iter() - .map(|x| { - serde_json::Number::from_f64(*x as f64).ok_or_else(|| { - ShellError::labeled_error( - "Can not convert number from floating point", - "can not convert to number", - &v.tag, - ) - }) - }) - .collect::, ShellError>>()? - .into_iter() - .map(serde_json::Value::Number) - .collect(), - ), - UntaggedValue::Row(o) => { - let mut m = serde_json::Map::new(); - for (k, v) in &o.entries { - m.insert(k.clone(), value_to_json_value(v)?); - } - serde_json::Value::Object(m) - } - }) -} - -fn json_list(input: &[Value]) -> Result, ShellError> { - let mut out = vec![]; - - for value in input { - out.push(value_to_json_value(value)?); - } - - Ok(out) -} - -fn to_json(args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - let pretty: Option = args.get_flag("pretty")?; - - let name_span = name_tag.span; - let input: Vec = args.input.collect(); - - let to_process_input = match input.len() { - x if x > 1 => { - let tag = input[0].tag.clone(); - vec![Value { - value: UntaggedValue::Table(input), - tag, - }] - } - 1 => input, - _ => vec![], - }; - - Ok((to_process_input - .into_iter() - .map(move |value| match value_to_json_value(&value) { - Ok(json_value) => { - let value_span = value.tag.span; - - match serde_json::to_string(&json_value) { - Ok(mut serde_json_string) => { - if let Some(pretty_value) = &pretty { - let mut pretty_format_failed = true; - - if let Ok(pretty_u64) = pretty_value.as_u64() { - if let Ok(serde_json_value) = - serde_json::from_str::(&serde_json_string) - { - let indentation_string = " ".repeat(pretty_u64 as usize); - let serde_formatter = - serde_json::ser::PrettyFormatter::with_indent( - indentation_string.as_bytes(), - ); - let serde_buffer = Vec::new(); - let mut serde_serializer = - serde_json::Serializer::with_formatter( - serde_buffer, - serde_formatter, - ); - let serde_json_object = json!(serde_json_value); - - if let Ok(()) = - serde_json_object.serialize(&mut serde_serializer) - { - if let Ok(ser_json_string) = - String::from_utf8(serde_serializer.into_inner()) - { - pretty_format_failed = false; - serde_json_string = ser_json_string - } - } - } - } - - if pretty_format_failed { - return Value::error(ShellError::labeled_error( - "Pretty formatting failed", - "failed", - pretty_value.tag(), - )); - } - } - - UntaggedValue::Primitive(Primitive::String(serde_json_string)) - .into_value(&value.tag) - } - _ => Value::error(ShellError::labeled_error_with_secondary( - "Expected a table with JSON-compatible structure.tag() from pipeline", - "requires JSON-compatible input", - name_span, - "originates from here".to_string(), - value_span, - )), - } - } - _ => Value::error(ShellError::labeled_error( - "Expected a table with JSON-compatible structure from pipeline", - "requires JSON-compatible input", - &name_tag, - )), - })) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::ToJson; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToJson {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/md.rs b/old_nushell/crates/nu-command/src/commands/formats/to/md.rs deleted file mode 100644 index f29fe145d..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/md.rs +++ /dev/null @@ -1,380 +0,0 @@ -use crate::prelude::*; - -use nu_data::value::format_leaf; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct Command; - -#[derive(Deserialize)] -pub struct Arguments { - pretty: bool, - #[serde(rename = "per-element")] - per_element: bool, -} - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "to md" - } - - fn signature(&self) -> Signature { - Signature::build("to md") - .switch( - "pretty", - "Formats the Markdown table to vertically align items", - Some('p'), - ) - .switch( - "per-element", - "treat each row as markdown syntax element", - Some('e'), - ) - } - - fn usage(&self) -> &str { - "Convert table into simple Markdown" - } - - fn run(&self, args: CommandArgs) -> Result { - to_md(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Outputs an unformatted table markdown string (default)", - example: "ls | to md", - result: Some(vec![Value::from(one(r#" - |name|type|chickens|modified| - |-|-|-|-| - |Andres.txt|File|10|2 years ago| - |Jonathan|Dir|5|2 years ago| - |Darren.txt|File|20|2 years ago| - |Yehuda|Dir|4|2 years ago| - "#))]), - }, - Example { - description: "Optionally, output a formatted markdown string", - example: "ls | to md --pretty", - result: Some(vec![Value::from(one(r#" - | name | type | chickens | modified | - | ---------- | ---- | -------- | ----------- | - | Andres.txt | File | 10 | 2 years ago | - | Jonathan | Dir | 5 | 2 years ago | - | Darren.txt | File | 20 | 2 years ago | - | Yehuda | Dir | 4 | 2 years ago | - "#))]), - }, - Example { - description: "Treat each row as a markdown element", - example: "echo [[H1]; [\"Welcome to Nushell\"]] | append (ls | first 2) | to md --per-element --pretty", - result: Some(vec![Value::from(one(r#" - # Welcome to Nushell - | name | type | chickens | modified | - | ---------- | ---- | -------- | ----------- | - | Andres.txt | File | 10 | 2 years ago | - | Jonathan | Dir | 5 | 2 years ago | - "#))]), - } - ] - } -} - -fn to_md(args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - let arguments = Arguments { - per_element: args.has_flag("per-element"), - pretty: args.has_flag("pretty"), - }; - - let input: Vec = args.input.collect(); - - Ok(OutputStream::one( - UntaggedValue::string(process(&input, arguments)).into_value(if input.is_empty() { - name_tag - } else { - input[0].tag() - }), - )) -} - -fn process( - input: &[Value], - Arguments { - pretty, - per_element, - }: Arguments, -) -> String { - if per_element { - input - .iter() - .map(|v| match &v.value { - UntaggedValue::Table(values) => table(values, pretty), - _ => fragment(v, pretty), - }) - .collect::() - } else { - table(input, pretty) - } -} - -fn fragment(input: &Value, pretty: bool) -> String { - let headers = input.data_descriptors(); - let mut out = String::new(); - - if headers.len() == 1 { - let markup = match (&headers[0]).to_ascii_lowercase().as_ref() { - "h1" => "# ".to_string(), - "h2" => "## ".to_string(), - "h3" => "### ".to_string(), - "blockquote" => "> ".to_string(), - - _ => return table(&[input.clone()], pretty), - }; - - out.push_str(&markup); - out.push_str(&format_leaf(input.get_data(&headers[0]).borrow()).plain_string(100_000)); - } else if input.is_row() { - let string = match input.row_entries().next() { - Some(value) => value.1.as_string().unwrap_or_default(), - None => String::from(""), - }; - - out = format_leaf(&UntaggedValue::from(string)).plain_string(100_000) - } else { - out = format_leaf(&input.value).plain_string(100_000) - } - - out.push('\n'); - out -} - -fn collect_headers(headers: &[String]) -> (Vec, Vec) { - let mut escaped_headers: Vec = Vec::new(); - let mut column_widths: Vec = Vec::new(); - - if !headers.is_empty() && (headers.len() > 1 || !headers[0].is_empty()) { - for header in headers { - let escaped_header_string = htmlescape::encode_minimal(header); - column_widths.push(escaped_header_string.len()); - escaped_headers.push(escaped_header_string); - } - } else { - column_widths = vec![0; headers.len()] - } - - (escaped_headers, column_widths) -} - -fn table(input: &[Value], pretty: bool) -> String { - let headers = nu_protocol::merge_descriptors(input); - - let (escaped_headers, mut column_widths) = collect_headers(&headers); - - let mut escaped_rows: Vec> = Vec::new(); - - for row in input { - let mut escaped_row: Vec = Vec::new(); - - match row.value.clone() { - UntaggedValue::Row(row) => { - for i in 0..headers.len() { - let data = row.get_data(&headers[i]); - let value_string = format_leaf(data.borrow()).plain_string(100_000); - let new_column_width = value_string.len(); - - escaped_row.push(value_string); - - if column_widths[i] < new_column_width { - column_widths[i] = new_column_width; - } - } - } - p => { - let value_string = - htmlescape::encode_minimal(&format_leaf(&p).plain_string(100_000)); - escaped_row.push(value_string); - } - } - - escaped_rows.push(escaped_row); - } - - let output_string = if (column_widths.is_empty() || column_widths.iter().all(|x| *x == 0)) - && escaped_rows.is_empty() - { - String::from("") - } else { - get_output_string(&escaped_headers, &escaped_rows, &column_widths, pretty) - .trim() - .to_string() - }; - - output_string -} - -fn get_output_string( - headers: &[String], - rows: &[Vec], - column_widths: &[usize], - pretty: bool, -) -> String { - let mut output_string = String::new(); - - if !headers.is_empty() { - output_string.push('|'); - - for i in 0..headers.len() { - if pretty { - output_string.push(' '); - output_string.push_str(&get_padded_string( - headers[i].clone(), - column_widths[i], - ' ', - )); - output_string.push(' '); - } else { - output_string.push_str(&headers[i]); - } - - output_string.push('|'); - } - - output_string.push_str("\n|"); - - #[allow(clippy::needless_range_loop)] - for i in 0..headers.len() { - if pretty { - output_string.push(' '); - output_string.push_str(&get_padded_string( - String::from("-"), - column_widths[i], - '-', - )); - output_string.push(' '); - } else { - output_string.push('-'); - } - - output_string.push('|'); - } - - output_string.push('\n'); - } - - for row in rows { - if !headers.is_empty() { - output_string.push('|'); - } - - for i in 0..row.len() { - if pretty { - output_string.push(' '); - output_string.push_str(&get_padded_string(row[i].clone(), column_widths[i], ' ')); - output_string.push(' '); - } else { - output_string.push_str(&row[i]); - } - - if !headers.is_empty() { - output_string.push('|'); - } - } - - output_string.push('\n'); - } - - output_string -} - -fn get_padded_string(text: String, desired_length: usize, padding_character: char) -> String { - let repeat_length = if text.len() > desired_length { - 0 - } else { - desired_length - text.len() - }; - - format!( - "{}{}", - text, - padding_character.to_string().repeat(repeat_length) - ) -} - -fn one(string: &str) -> String { - string - .lines() - .skip(1) - .map(|line| line.trim()) - .collect::>() - .join("\n") - .trim_end() - .to_string() -} - -#[cfg(test)] -mod tests { - use super::{fragment, one, table}; - use nu_protocol::{row, Value}; - - #[test] - fn render_h1() { - let value = row! {"H1".into() => Value::from("Ecuador")}; - - assert_eq!(fragment(&value, false), "# Ecuador\n"); - } - - #[test] - fn render_h2() { - let value = row! {"H2".into() => Value::from("Ecuador")}; - - assert_eq!(fragment(&value, false), "## Ecuador\n"); - } - - #[test] - fn render_h3() { - let value = row! {"H3".into() => Value::from("Ecuador")}; - - assert_eq!(fragment(&value, false), "### Ecuador\n"); - } - - #[test] - fn render_blockquote() { - let value = row! {"BLOCKQUOTE".into() => Value::from("Ecuador")}; - - assert_eq!(fragment(&value, false), "> Ecuador\n"); - } - - #[test] - fn render_table() { - let value = vec![ - row! { "country".into() => Value::from("Ecuador")}, - row! { "country".into() => Value::from("New Zealand")}, - row! { "country".into() => Value::from("USA")}, - ]; - - assert_eq!( - table(&value, false), - one(r#" - |country| - |-| - |Ecuador| - |New Zealand| - |USA| - "#) - ); - - assert_eq!( - table(&value, true), - one(r#" - | country | - | ----------- | - | Ecuador | - | New Zealand | - | USA | - "#) - ); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/mod.rs b/old_nushell/crates/nu-command/src/commands/formats/to/mod.rs deleted file mode 100644 index e6e1ff7fc..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -mod command; -pub(crate) mod csv; -pub(crate) mod delimited; -mod html; -mod json; -mod md; -pub(crate) mod toml; -mod tsv; -pub(crate) mod url; -mod xml; -mod yaml; - -pub use self::csv::ToCsv; -pub use self::toml::ToToml; -pub use self::url::ToUrl; -pub use command::To; -pub use html::ToHtml; -pub use json::ToJson; -pub use md::Command as ToMarkdown; -pub use tsv::ToTsv; -pub use xml::ToXml; -pub use yaml::ToYaml; diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/toml.rs b/old_nushell/crates/nu-command/src/commands/formats/to/toml.rs deleted file mode 100644 index 1610e35c6..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/toml.rs +++ /dev/null @@ -1,242 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::{CoerceInto, ShellError}; -use nu_protocol::{Primitive, Signature, UnspannedPathMember, UntaggedValue, Value}; - -pub struct ToToml; - -impl WholeStreamCommand for ToToml { - fn name(&self) -> &str { - "to toml" - } - - fn signature(&self) -> Signature { - Signature::build("to toml") - } - - fn usage(&self) -> &str { - "Convert table into .toml text" - } - - fn run(&self, args: CommandArgs) -> Result { - to_toml(args) - } -} - -// Helper method to recursively convert nu_protocol::Value -> toml::Value -// This shouldn't be called at the top-level -fn helper(v: &Value) -> Result { - Ok(match &v.value { - UntaggedValue::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b), - UntaggedValue::Primitive(Primitive::Filesize(b)) => { - if let Some(value) = b.to_i64() { - toml::Value::Integer(value) - } else { - return Err(ShellError::labeled_error( - "Value too large to write to toml", - "value too large for toml", - v.tag.span, - )); - } - } - UntaggedValue::Primitive(Primitive::Duration(i)) => toml::Value::String(i.to_string()), - UntaggedValue::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()), - UntaggedValue::Primitive(Primitive::EndOfStream) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::BeginningOfStream) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::Decimal(f)) => { - toml::Value::Float(f.tagged(&v.tag).coerce_into("converting to TOML float")?) - } - UntaggedValue::Primitive(Primitive::Int(i)) => toml::Value::Integer(*i), - UntaggedValue::Primitive(Primitive::BigInt(i)) => { - toml::Value::Integer(i.tagged(&v.tag).coerce_into("converting to TOML integer")?) - } - UntaggedValue::Primitive(Primitive::Nothing) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::GlobPattern(s)) => toml::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::FilePath(s)) => { - toml::Value::String(s.display().to_string()) - } - UntaggedValue::Primitive(Primitive::ColumnPath(path)) => toml::Value::Array( - path.iter() - .map(|x| match &x.unspanned { - UnspannedPathMember::String(string) => Ok(toml::Value::String(string.clone())), - UnspannedPathMember::Int(int) => Ok(toml::Value::Integer(*int)), - }) - .collect::, ShellError>>()?, - ), - UntaggedValue::Table(l) => toml::Value::Array(collect_values(l)?), - UntaggedValue::Error(e) => return Err(e.clone()), - UntaggedValue::Block(_) => toml::Value::String("".to_string()), - #[cfg(feature = "dataframe")] - UntaggedValue::DataFrame(_) | UntaggedValue::FrameStruct(_) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::Range(_)) => toml::Value::String("".to_string()), - UntaggedValue::Primitive(Primitive::Binary(b)) => { - toml::Value::Array(b.iter().map(|x| toml::Value::Integer(*x as i64)).collect()) - } - UntaggedValue::Row(o) => { - let mut m = toml::map::Map::new(); - for (k, v) in &o.entries { - m.insert(k.clone(), helper(v)?); - } - toml::Value::Table(m) - } - }) -} - -/// Converts a nu_protocol::Value into a toml::Value -/// Will return a Shell Error, if the Nu Value is not a valid top-level TOML Value -pub fn value_to_toml_value(v: &Value) -> Result { - match &v.value { - UntaggedValue::Row(o) => { - let mut m = toml::map::Map::new(); - for (k, v) in &o.entries { - m.insert(k.clone(), helper(v)?); - } - Ok(toml::Value::Table(m)) - } - UntaggedValue::Primitive(Primitive::String(s)) => { - // Attempt to de-serialize the String - toml::de::from_str(s).map_err(|_| { - ShellError::labeled_error( - format!("{:?} unable to de-serialize string to TOML", s), - "invalid TOML", - v.tag(), - ) - }) - } - _ => Err(ShellError::labeled_error( - format!("{:?} is not a valid top-level TOML", v.value), - "invalid TOML", - v.tag(), - )), - } -} - -fn collect_values(input: &[Value]) -> Result, ShellError> { - let mut out = vec![]; - - for value in input { - out.push(helper(value)?); - } - - Ok(out) -} - -fn to_toml(args: CommandArgs) -> Result { - let name_tag = args.name_tag(); - let name_span = name_tag.span; - let input: Vec = args.input.collect(); - - let to_process_input = match input.len() { - x if x > 1 => { - let tag = input[0].tag.clone(); - vec![Value { - value: UntaggedValue::Table(input), - tag, - }] - } - 1 => input, - _ => vec![], - }; - - Ok((to_process_input.into_iter().map(move |value| { - let value_span = value.tag.span; - match value_to_toml_value(&value) { - Ok(toml_value) => match toml::to_string(&toml_value) { - Ok(x) => UntaggedValue::Primitive(Primitive::String(x)).into_value(&name_tag), - - _ => Value::error(ShellError::labeled_error_with_secondary( - "Expected a table with TOML-compatible structure.tag() from pipeline", - "requires TOML-compatible input", - name_span, - "originates from here".to_string(), - value_span, - )), - }, - _ => Value::error(ShellError::labeled_error( - "Expected a table with TOML-compatible structure from pipeline", - "requires TOML-compatible input", - &name_tag, - )), - } - })) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::*; - use nu_protocol::Dictionary; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToToml {}) - } - - #[test] - fn test_value_to_toml_value() { - // - // Positive Tests - // - - // Dictionary -> What we do in "crates/nu-cli/src/data/config.rs" to write the config file - let mut m = indexmap::IndexMap::new(); - m.insert("rust".to_owned(), Value::from("editor")); - m.insert("is".to_owned(), Value::nothing()); - m.insert( - "features".to_owned(), - UntaggedValue::Table(vec![ - UntaggedValue::string("hello").into_untagged_value(), - UntaggedValue::string("array").into_untagged_value(), - ]) - .into_untagged_value(), - ); - let tv = value_to_toml_value(&UntaggedValue::Row(Dictionary::new(m)).into_untagged_value()) - .expect("Expected Ok from valid TOML dictionary"); - assert_eq!( - tv.get("features"), - Some(&toml::Value::Array(vec![ - toml::Value::String("hello".to_owned()), - toml::Value::String("array".to_owned()) - ])) - ); - // TOML string - let tv = value_to_toml_value(&Value::from( - r#" - title = "TOML Example" - - [owner] - name = "Tom Preston-Werner" - dob = 1979-05-27T07:32:00-08:00 # First class dates - - [dependencies] - rustyline = "4.1.0" - sysinfo = "0.8.4" - chrono = { version = "0.4.6", features = ["serde"] } - "#, - )) - .expect("Expected Ok from valid TOML string"); - assert_eq!( - tv.get("title").unwrap(), - &toml::Value::String("TOML Example".to_owned()) - ); - // - // Negative Tests - // - value_to_toml_value(&Value::from("not_valid")) - .expect_err("Expected non-valid toml (String) to cause error!"); - value_to_toml_value(&UntaggedValue::Table(vec![Value::from("1")]).into_untagged_value()) - .expect_err("Expected non-valid toml (Table) to cause error!"); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/tsv.rs b/old_nushell/crates/nu-command/src/commands/formats/to/tsv.rs deleted file mode 100644 index f721bea56..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/tsv.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::commands::formats::to::delimited::to_delimited_data; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::Signature; - -pub struct ToTsv; - -impl WholeStreamCommand for ToTsv { - fn name(&self) -> &str { - "to tsv" - } - - fn signature(&self) -> Signature { - Signature::build("to tsv").switch( - "noheaders", - "do not output the column names as the first row", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Convert table into .tsv text" - } - - fn run(&self, args: CommandArgs) -> Result { - to_tsv(args) - } -} - -fn to_tsv(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let noheaders = args.has_flag("noheaders"); - - to_delimited_data(noheaders, '\t', "TSV", args.input, name) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::ToTsv; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToTsv {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/url.rs b/old_nushell/crates/nu-command/src/commands/formats/to/url.rs deleted file mode 100644 index e968f5c97..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/url.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct ToUrl; - -impl WholeStreamCommand for ToUrl { - fn name(&self) -> &str { - "to url" - } - - fn signature(&self) -> Signature { - Signature::build("to url") - } - - fn usage(&self) -> &str { - "Convert table into url-encoded text" - } - - fn run(&self, args: CommandArgs) -> Result { - to_url(args) - } -} - -fn to_url(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let input = args.input; - - Ok(input - .map(move |value| match value { - Value { - value: UntaggedValue::Row(row), - .. - } => { - let mut row_vec = vec![]; - for (k, v) in row.entries { - match v.as_string() { - Ok(s) => { - row_vec.push((k.clone(), s.to_string())); - } - _ => { - return Value::error(ShellError::labeled_error_with_secondary( - "Expected table with string values", - "requires table with strings", - &tag, - "value originates from here", - v.tag, - )); - } - } - } - - match serde_urlencoded::to_string(row_vec) { - Ok(s) => UntaggedValue::string(s).into_value(&tag), - _ => Value::error(ShellError::labeled_error( - "Failed to convert to url-encoded", - "cannot url-encode", - &tag, - )), - } - } - Value { tag: value_tag, .. } => Value::error(ShellError::labeled_error_with_secondary( - "Expected a table from pipeline", - "requires table input", - &tag, - "value originates from here", - value_tag.span, - )), - }) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::ToUrl; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToUrl {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/xml.rs b/old_nushell/crates/nu-command/src/commands/formats/to/xml.rs deleted file mode 100644 index 28fe8d0c2..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/xml.rs +++ /dev/null @@ -1,196 +0,0 @@ -use crate::prelude::*; -use indexmap::IndexMap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; -use std::collections::HashSet; -use std::io::Cursor; -use std::io::Write; - -pub struct ToXml; - -impl WholeStreamCommand for ToXml { - fn name(&self) -> &str { - "to xml" - } - - fn signature(&self) -> Signature { - Signature::build("to xml").named( - "pretty", - SyntaxShape::Int, - "Formats the XML text with the provided indentation setting", - Some('p'), - ) - } - - fn usage(&self) -> &str { - "Convert table into .xml text" - } - - fn run(&self, args: CommandArgs) -> Result { - to_xml(args) - } -} - -pub fn add_attributes<'a>( - element: &mut quick_xml::events::BytesStart<'a>, - attributes: &'a IndexMap, -) { - for (k, v) in attributes { - element.push_attribute((k.as_str(), v.as_str())); - } -} - -pub fn get_attributes(row: &Value) -> Option> { - if let UntaggedValue::Row(r) = &row.value { - if let Some(v) = r.entries.get("attributes") { - if let UntaggedValue::Row(a) = &v.value { - let mut h = IndexMap::new(); - for (k, v) in &a.entries { - h.insert(k.clone(), v.convert_to_string()); - } - return Some(h); - } - } - } - None -} - -pub fn get_children(row: &Value) -> Option<&Vec> { - if let UntaggedValue::Row(r) = &row.value { - if let Some(v) = r.entries.get("children") { - if let UntaggedValue::Table(t) = &v.value { - return Some(t); - } - } - } - None -} - -pub fn is_xml_row(row: &Value) -> bool { - if let UntaggedValue::Row(r) = &row.value { - let keys: HashSet<&String> = r.keys().collect(); - let children: String = "children".to_string(); - let attributes: String = "attributes".to_string(); - return keys.contains(&children) && keys.contains(&attributes) && keys.len() == 2; - } - false -} - -pub fn write_xml_events( - current: &Value, - writer: &mut quick_xml::Writer, -) -> Result<(), ShellError> { - match ¤t.value { - UntaggedValue::Row(o) => { - for (k, v) in &o.entries { - let mut e = BytesStart::owned(k.as_bytes(), k.len()); - if !is_xml_row(v) { - return Err(ShellError::labeled_error( - "Expected a row with 'children' and 'attributes' columns", - "missing 'children' and 'attributes' columns ", - ¤t.tag, - )); - } - let a = get_attributes(v); - if let Some(ref a) = a { - add_attributes(&mut e, a); - } - writer - .write_event(Event::Start(e)) - .expect("Couldn't open XML node"); - let c = get_children(v); - if let Some(c) = c { - for v in c { - write_xml_events(v, writer)?; - } - } - writer - .write_event(Event::End(BytesEnd::borrowed(k.as_bytes()))) - .expect("Couldn't close XML node"); - } - } - UntaggedValue::Table(t) => { - for v in t { - write_xml_events(v, writer)?; - } - } - _ => { - let s = current.convert_to_string(); - writer - .write_event(Event::Text(BytesText::from_plain_str(s.as_str()))) - .expect("Couldn't write XML text"); - } - } - Ok(()) -} - -fn to_xml(args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - let name_span = name_tag.span; - let pretty: Option = args.get_flag("pretty")?; - let input: Vec = args.input.collect(); - - let to_process_input = match input.len() { - x if x > 1 => { - let tag = input[0].tag.clone(); - vec![Value { - value: UntaggedValue::Table(input), - tag, - }] - } - 1 => input, - _ => vec![], - }; - - Ok((to_process_input.into_iter().map(move |value| { - let mut w = pretty.as_ref().map_or_else( - || quick_xml::Writer::new(Cursor::new(Vec::new())), - |p| { - quick_xml::Writer::new_with_indent( - Cursor::new(Vec::new()), - b' ', - p.value.expect_int() as usize, - ) - }, - ); - - let value_span = value.tag.span; - - match write_xml_events(&value, &mut w) { - Ok(_) => { - let b = w.into_inner().into_inner(); - let s = if let Ok(s) = String::from_utf8(b) { - s - } else { - return Value::error(ShellError::untagged_runtime_error( - "Could not convert a string to utf-8", - )); - }; - UntaggedValue::Primitive(Primitive::String(s)).into_value(&name_tag) - } - Err(_) => Value::error(ShellError::labeled_error_with_secondary( - "Expected a table with XML-compatible structure from pipeline", - "requires XML-compatible input", - name_span, - "originates from here".to_string(), - value_span, - )), - } - })) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::ToXml; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToXml {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/formats/to/yaml.rs b/old_nushell/crates/nu-command/src/commands/formats/to/yaml.rs deleted file mode 100644 index 44f65d29f..000000000 --- a/old_nushell/crates/nu-command/src/commands/formats/to/yaml.rs +++ /dev/null @@ -1,172 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::{CoerceInto, ShellError}; -use nu_protocol::{Primitive, Signature, UnspannedPathMember, UntaggedValue, Value}; - -pub struct ToYaml; - -impl WholeStreamCommand for ToYaml { - fn name(&self) -> &str { - "to yaml" - } - - fn signature(&self) -> Signature { - Signature::build("to yaml") - } - - fn usage(&self) -> &str { - "Convert table into .yaml/.yml text" - } - - fn run(&self, args: CommandArgs) -> Result { - to_yaml(args) - } -} - -pub fn value_to_yaml_value(v: &Value) -> Result { - Ok(match &v.value { - UntaggedValue::Primitive(Primitive::Boolean(b)) => serde_yaml::Value::Bool(*b), - UntaggedValue::Primitive(Primitive::Filesize(b)) => { - serde_yaml::Value::Number(serde_yaml::Number::from(b.to_f64().ok_or_else(|| { - ShellError::labeled_error( - "Could not convert to bytes", - "could not convert to bytes", - &v.tag, - ) - })?)) - } - UntaggedValue::Primitive(Primitive::Duration(i)) => { - serde_yaml::Value::String(i.to_string()) - } - UntaggedValue::Primitive(Primitive::Date(d)) => serde_yaml::Value::String(d.to_string()), - UntaggedValue::Primitive(Primitive::EndOfStream) => serde_yaml::Value::Null, - UntaggedValue::Primitive(Primitive::BeginningOfStream) => serde_yaml::Value::Null, - UntaggedValue::Primitive(Primitive::Decimal(f)) => { - serde_yaml::Value::Number(serde_yaml::Number::from(f.to_f64().ok_or_else(|| { - ShellError::labeled_error( - "Could not convert to decimal", - "could not convert to decimal", - &v.tag, - ) - })?)) - } - UntaggedValue::Primitive(Primitive::Int(i)) => { - serde_yaml::Value::Number(serde_yaml::Number::from(*i)) - } - UntaggedValue::Primitive(Primitive::BigInt(i)) => { - serde_yaml::Value::Number(serde_yaml::Number::from(CoerceInto::::coerce_into( - i.tagged(&v.tag), - "converting to YAML number", - )?)) - } - UntaggedValue::Primitive(Primitive::Nothing) => serde_yaml::Value::Null, - UntaggedValue::Primitive(Primitive::GlobPattern(s)) => serde_yaml::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::String(s)) => serde_yaml::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::ColumnPath(path)) => { - let mut out = vec![]; - - for member in path { - match &member.unspanned { - UnspannedPathMember::String(string) => { - out.push(serde_yaml::Value::String(string.clone())) - } - UnspannedPathMember::Int(int) => { - out.push(serde_yaml::Value::Number(serde_yaml::Number::from(*int))) - } - } - } - - serde_yaml::Value::Sequence(out) - } - UntaggedValue::Primitive(Primitive::FilePath(s)) => { - serde_yaml::Value::String(s.display().to_string()) - } - - UntaggedValue::Table(l) => { - let mut out = vec![]; - - for value in l { - out.push(value_to_yaml_value(value)?); - } - - serde_yaml::Value::Sequence(out) - } - UntaggedValue::Error(e) => return Err(e.clone()), - UntaggedValue::Block(_) | UntaggedValue::Primitive(Primitive::Range(_)) => { - serde_yaml::Value::Null - } - #[cfg(feature = "dataframe")] - UntaggedValue::DataFrame(_) | UntaggedValue::FrameStruct(_) => serde_yaml::Value::Null, - UntaggedValue::Primitive(Primitive::Binary(b)) => serde_yaml::Value::Sequence( - b.iter() - .map(|x| serde_yaml::Value::Number(serde_yaml::Number::from(*x))) - .collect(), - ), - UntaggedValue::Row(o) => { - let mut m = serde_yaml::Mapping::new(); - for (k, v) in &o.entries { - m.insert( - serde_yaml::Value::String(k.clone()), - value_to_yaml_value(v)?, - ); - } - serde_yaml::Value::Mapping(m) - } - }) -} - -fn to_yaml(args: CommandArgs) -> Result { - let name_tag = args.name_tag(); - let name_span = name_tag.span; - - let input: Vec = args.input.collect(); - - let to_process_input = match input.len() { - x if x > 1 => { - let tag = input[0].tag.clone(); - vec![Value { - value: UntaggedValue::Table(input), - tag, - }] - } - 1 => input, - _ => vec![], - }; - - Ok((to_process_input.into_iter().map(move |value| { - let value_span = value.tag.span; - - match value_to_yaml_value(&value) { - Ok(yaml_value) => match serde_yaml::to_string(&yaml_value) { - Ok(x) => UntaggedValue::Primitive(Primitive::String(x)).into_value(&name_tag), - - _ => Value::error(ShellError::labeled_error_with_secondary( - "Expected a table with YAML-compatible structure from pipeline", - "requires YAML-compatible input", - name_span, - "originates from here".to_string(), - value_span, - )), - }, - _ => Value::error(ShellError::labeled_error( - "Expected a table with YAML-compatible structure from pipeline", - "requires YAML-compatible input", - &name_tag, - )), - } - })) - .into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::ToYaml; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ToYaml {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/cal.rs b/old_nushell/crates/nu-command/src/commands/generators/cal.rs deleted file mode 100644 index 12195a4d1..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/cal.rs +++ /dev/null @@ -1,338 +0,0 @@ -use crate::prelude::*; -use chrono::{Datelike, Local, NaiveDate}; -use indexmap::IndexMap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct Cal; - -impl WholeStreamCommand for Cal { - fn name(&self) -> &str { - "cal" - } - - fn signature(&self) -> Signature { - Signature::build("cal") - .switch("year", "Display the year column", Some('y')) - .switch("quarter", "Display the quarter column", Some('q')) - .switch("month", "Display the month column", Some('m')) - .named( - "full-year", - SyntaxShape::Int, - "Display a year-long calendar for the specified year", - None, - ) - .named( - "week-start", - SyntaxShape::String, - "Display the calendar with the specified day as the first day of the week", - None, - ) - .switch( - "month-names", - "Display the month names instead of integers", - None, - ) - } - - fn usage(&self) -> &str { - "Display a calendar." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - cal(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "This month's calendar", - example: "cal", - result: None, - }, - Example { - description: "The calendar for all of 2012", - example: "cal --full-year 2012", - result: None, - }, - Example { - description: "This month's calendar with the week starting on monday", - example: "cal --week-start monday", - result: None, - }, - ] - } -} - -pub fn cal(args: CommandArgs) -> Result { - let mut calendar_vec_deque = VecDeque::new(); - let tag = args.call_info.name_tag.clone(); - - let (current_year, current_month, current_day) = get_current_date(); - - let mut selected_year: i32 = current_year; - let mut current_day_option: Option = Some(current_day); - - let full_year_value: Option = args.get_flag("full-year")?; - let month_range = if let Some(full_year_value) = full_year_value { - selected_year = full_year_value as i32; - - if selected_year != current_year { - current_day_option = None - } - - (1, 12) - } else { - (current_month, current_month) - }; - - add_months_of_year_to_table( - &args, - &mut calendar_vec_deque, - &tag, - selected_year, - month_range, - current_month, - current_day_option, - )?; - - Ok(calendar_vec_deque.into_iter().into_action_stream()) -} - -fn get_invalid_year_shell_error(year_tag: &Tag) -> ShellError { - ShellError::labeled_error("The year is invalid", "invalid year", year_tag) -} - -struct MonthHelper { - selected_year: i32, - selected_month: u32, - day_number_of_week_month_starts_on: u32, - number_of_days_in_month: u32, - quarter_number: u32, - month_name: String, -} - -impl MonthHelper { - pub fn new(selected_year: i32, selected_month: u32) -> Result { - let naive_date = NaiveDate::from_ymd_opt(selected_year, selected_month, 1).ok_or(())?; - let number_of_days_in_month = - MonthHelper::calculate_number_of_days_in_month(selected_year, selected_month)?; - - Ok(MonthHelper { - selected_year, - selected_month, - day_number_of_week_month_starts_on: naive_date.weekday().num_days_from_sunday(), - number_of_days_in_month, - quarter_number: ((selected_month - 1) / 3) + 1, - month_name: naive_date.format("%B").to_string().to_ascii_lowercase(), - }) - } - - fn calculate_number_of_days_in_month( - mut selected_year: i32, - mut selected_month: u32, - ) -> Result { - // Chrono does not provide a method to output the amount of days in a month - // This is a workaround taken from the example code from the Chrono docs here: - // https://docs.rs/chrono/0.3.0/chrono/naive/date/struct.NaiveDate.html#example-30 - if selected_month == 12 { - selected_year += 1; - selected_month = 1; - } else { - selected_month += 1; - }; - - let next_month_naive_date = - NaiveDate::from_ymd_opt(selected_year, selected_month, 1).ok_or(())?; - - Ok(next_month_naive_date.pred().day()) - } -} - -fn get_current_date() -> (i32, u32, u32) { - let local_now_date = Local::now().date(); - - let current_year: i32 = local_now_date.year(); - let current_month: u32 = local_now_date.month(); - let current_day: u32 = local_now_date.day(); - - (current_year, current_month, current_day) -} - -fn add_months_of_year_to_table( - args: &CommandArgs, - calendar_vec_deque: &mut VecDeque, - tag: &Tag, - selected_year: i32, - (start_month, end_month): (u32, u32), - current_month: u32, - current_day_option: Option, -) -> Result<(), ShellError> { - for month_number in start_month..=end_month { - let mut new_current_day_option: Option = None; - - if let Some(current_day) = current_day_option { - if month_number == current_month { - new_current_day_option = Some(current_day) - } - } - - let add_month_to_table_result = add_month_to_table( - args, - calendar_vec_deque, - tag, - selected_year, - month_number, - new_current_day_option, - ); - - add_month_to_table_result? - } - - Ok(()) -} - -fn add_month_to_table( - args: &CommandArgs, - calendar_vec_deque: &mut VecDeque, - tag: &Tag, - selected_year: i32, - current_month: u32, - current_day_option: Option, -) -> Result<(), ShellError> { - let month_helper_result = MonthHelper::new(selected_year, current_month); - - let full_year_value: Option> = args.get_flag("full-year")?; - - let month_helper = match month_helper_result { - Ok(month_helper) => month_helper, - Err(()) => match full_year_value { - Some(full_year_value) => { - return Err(get_invalid_year_shell_error(&full_year_value.tag())) - } - None => { - return Err(ShellError::labeled_error( - "Issue parsing command", - "invalid command", - tag, - )) - } - }, - }; - - let mut days_of_the_week = [ - "sunday", - "monday", - "tuesday", - "wednesday", - "thursday", - "friday", - "saturday", - ]; - - let mut week_start_day = days_of_the_week[0].to_string(); - - if let Some(day) = args.get_flag::>("week-start")? { - if days_of_the_week.contains(&day.item.as_str()) { - week_start_day = day.item; - } else { - return Err(ShellError::labeled_error( - "The specified week start day is invalid", - "invalid week start day", - day.tag(), - )); - } - } - - let week_start_day_offset = days_of_the_week.len() - - days_of_the_week - .iter() - .position(|day| *day == week_start_day) - .unwrap_or(0); - - days_of_the_week.rotate_right(week_start_day_offset); - - let mut total_start_offset: u32 = - month_helper.day_number_of_week_month_starts_on + week_start_day_offset as u32; - total_start_offset %= days_of_the_week.len() as u32; - - let mut day_number: u32 = 1; - let day_limit: u32 = total_start_offset + month_helper.number_of_days_in_month; - - let should_show_year_column = args.has_flag("year"); - let should_show_quarter_column = args.has_flag("quarter"); - let should_show_month_column = args.has_flag("month"); - let should_show_month_names = args.has_flag("month-names"); - - while day_number <= day_limit { - let mut indexmap = IndexMap::new(); - - if should_show_year_column { - indexmap.insert( - "year".to_string(), - UntaggedValue::int(month_helper.selected_year).into_value(tag), - ); - } - - if should_show_quarter_column { - indexmap.insert( - "quarter".to_string(), - UntaggedValue::int(month_helper.quarter_number).into_value(tag), - ); - } - - if should_show_month_column || should_show_month_names { - let month_value = if should_show_month_names { - UntaggedValue::string(month_helper.month_name.clone()).into_value(tag) - } else { - UntaggedValue::int(month_helper.selected_month).into_value(tag) - }; - - indexmap.insert("month".to_string(), month_value); - } - - for day in &days_of_the_week { - let should_add_day_number_to_table = - (day_number > total_start_offset) && (day_number <= day_limit); - - let mut value = UntaggedValue::nothing().into_value(tag); - - if should_add_day_number_to_table { - let adjusted_day_number = day_number - total_start_offset; - - value = UntaggedValue::int(adjusted_day_number).into_value(tag); - - if let Some(current_day) = current_day_option { - if current_day == adjusted_day_number { - // TODO: Update the value here with a color when color support is added - // This colors the current day - } - } - } - - indexmap.insert((*day).to_string(), value); - - day_number += 1; - } - - calendar_vec_deque - .push_back(UntaggedValue::Row(Dictionary::from(indexmap)).into_value(tag)); - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::Cal; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Cal {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/command.rs b/old_nushell/crates/nu-command/src/commands/generators/date/command.rs deleted file mode 100644 index 1e736eb10..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/command.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "date" - } - - fn signature(&self) -> Signature { - Signature::build("date") - } - - fn usage(&self) -> &str { - "Apply date function." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&Command, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/format.rs b/old_nushell/crates/nu-command/src/commands/generators/date/format.rs deleted file mode 100644 index 73c486180..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/format.rs +++ /dev/null @@ -1,108 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use std::fmt::{self, write}; - -pub struct Date; - -impl WholeStreamCommand for Date { - fn name(&self) -> &str { - "date format" - } - - fn signature(&self) -> Signature { - Signature::build("date format") - .required("format", SyntaxShape::String, "strftime format") - .switch("table", "print date in a table", Some('t')) - } - - fn usage(&self) -> &str { - "Format a given date using the given format string." - } - - fn run(&self, args: CommandArgs) -> Result { - format(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Format the current date", - example: "date now | date format '%Y.%m.%d_%H %M %S,%z'", - result: None, - }, - Example { - description: "Format the current date and print in a table", - example: "date now | date format -t '%Y-%m-%d_%H:%M:%S %z'", - result: None, - }, - ] - } -} - -pub fn format(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let format: Tagged = args.req(0)?; - let table: Option = args.get_flag("table")?; - - let input = if args.input.is_empty() { - InputStream::one(super::now::date_now(&tag)) - } else { - args.input - }; - - Ok(input - .map(move |value| match value { - Value { - value: UntaggedValue::Primitive(Primitive::Date(dt)), - .. - } => { - let mut output = String::new(); - if let Err(fmt::Error) = - write(&mut output, format_args!("{}", dt.format(&format.item))) - { - Err(ShellError::labeled_error( - "The date format is invalid", - "invalid strftime format", - &format.tag, - )) - } else { - let value = if table.is_some() { - let mut indexmap = IndexMap::new(); - indexmap.insert( - "formatted".to_string(), - UntaggedValue::string(&output).into_value(&tag), - ); - - UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag) - } else { - UntaggedValue::string(&output).into_value(&tag) - }; - - Ok(value) - } - } - _ => Err(ShellError::labeled_error( - "Expected a date from pipeline", - "requires date input", - &tag, - )), - }) - .into_input_stream()) -} - -#[cfg(test)] -mod tests { - use super::Date; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Date {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/humanize.rs b/old_nushell/crates/nu-command/src/commands/generators/date/humanize.rs deleted file mode 100644 index af440f981..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/humanize.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Primitive, Signature, UntaggedValue, Value}; - -pub struct Date; - -impl WholeStreamCommand for Date { - fn name(&self) -> &str { - "date humanize" - } - - fn signature(&self) -> Signature { - Signature::build("date humanize").switch("table", "print date in a table", Some('t')) - } - - fn usage(&self) -> &str { - "Print a 'humanized' format for the date, relative to now." - } - - fn run(&self, args: CommandArgs) -> Result { - humanize(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Humanize the current date", - example: "date now | date humanize", - result: None, - }] - } -} - -pub fn humanize(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let table: Option = args.get_flag("table")?; - let input = args.input; - - Ok(input - .map(move |value| match value { - Value { - value: UntaggedValue::Primitive(dt @ Primitive::Date(_)), - .. - } => { - let output = nu_protocol::format_primitive(&dt, None); - let value = if table.is_some() { - let mut indexmap = IndexMap::new(); - indexmap.insert( - "formatted".to_string(), - UntaggedValue::string(&output).into_value(&tag), - ); - - UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag) - } else { - UntaggedValue::string(&output).into_value(&tag) - }; - - Ok(value) - } - _ => Err(ShellError::labeled_error( - "Expected a date from pipeline", - "requires date input", - &tag, - )), - }) - .into_input_stream()) -} - -#[cfg(test)] -mod tests { - use super::Date; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Date {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/list_timezone.rs b/old_nushell/crates/nu-command/src/commands/generators/date/list_timezone.rs deleted file mode 100644 index af7fc94ad..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/list_timezone.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::prelude::*; -use chrono_tz::TZ_VARIANTS; -use indexmap::IndexMap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Signature, UntaggedValue}; - -pub struct Date; - -impl WholeStreamCommand for Date { - fn name(&self) -> &str { - "date list-timezone" - } - - fn signature(&self) -> Signature { - Signature::build("date list-timezone") - } - - fn usage(&self) -> &str { - "List supported time zones." - } - - fn run(&self, args: CommandArgs) -> Result { - list_timezone(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "List all supported time zones", - example: "date list-timezone", - result: None, - }, - Example { - description: "List all supported European time zones", - example: "date list-timezone | where timezone =~ Europe", - result: None, - }, - ] - } -} - -fn list_timezone(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag; - - let list = TZ_VARIANTS.iter().map(move |tz| { - let mut entries = IndexMap::new(); - - entries.insert( - "timezone".to_string(), - UntaggedValue::string(tz.name()).into_value(&tag), - ); - - Ok(UntaggedValue::Row(Dictionary { entries }).into_value(&tag)) - }); - - Ok(list.into_iter().into_input_stream()) -} - -#[cfg(test)] -mod tests { - use super::Date; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Date {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/mod.rs b/old_nushell/crates/nu-command/src/commands/generators/date/mod.rs deleted file mode 100644 index c98e62ef2..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub mod command; -pub mod format; -pub mod humanize; -pub mod list_timezone; -pub mod now; -pub mod to_table; -pub mod to_timezone; - -mod parser; - -pub use command::Command as Date; -pub use format::Date as DateFormat; -pub use humanize::Date as DateHumanize; -pub use list_timezone::Date as DateListTimeZone; -pub use now::Date as DateNow; -pub use to_table::Date as DateToTable; -pub use to_timezone::Date as DateToTimeZone; diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/now.rs b/old_nushell/crates/nu-command/src/commands/generators/date/now.rs deleted file mode 100644 index fda7b596a..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/now.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::prelude::*; -use chrono::{DateTime, Local}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct Date; - -impl WholeStreamCommand for Date { - fn name(&self) -> &str { - "date now" - } - - fn signature(&self) -> Signature { - Signature::build("date now") - } - - fn usage(&self) -> &str { - "Get the current date." - } - - fn run(&self, args: CommandArgs) -> Result { - now(args) - } -} - -pub fn date_now(tag: &Tag) -> Value { - let now: DateTime = Local::now(); - - UntaggedValue::date(now.with_timezone(now.offset())).into_value(tag) -} - -pub fn now(args: CommandArgs) -> Result { - let value = date_now(&args.call_info.name_tag); - - Ok(OutputStream::one(value)) -} - -#[cfg(test)] -mod tests { - use super::Date; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Date {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/parser.rs b/old_nushell/crates/nu-command/src/commands/generators/date/parser.rs deleted file mode 100644 index d2d1f3a85..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/parser.rs +++ /dev/null @@ -1,107 +0,0 @@ -// Modified from chrono::format::scan - -use chrono::{DateTime, FixedOffset, Local, Offset, TimeZone}; -use chrono_tz::Tz; -use titlecase::titlecase; - -#[derive(Debug, Clone, PartialEq, Eq, Copy)] -pub enum ParseErrorKind { - /// Given field is out of permitted range. - OutOfRange, - - /// The input string has some invalid character sequence for given formatting items. - Invalid, - - /// The input string has been prematurely ended. - TooShort, -} - -pub fn datetime_in_timezone( - dt: &DateTime, - s: &str, -) -> Result, ParseErrorKind> { - match timezone_offset_internal(s, true, true) { - Ok(offset) => match FixedOffset::east_opt(offset) { - Some(offset) => Ok(dt.with_timezone(&offset)), - None => Err(ParseErrorKind::OutOfRange), - }, - Err(ParseErrorKind::Invalid) => { - if s.to_lowercase() == "local" { - Ok(dt.with_timezone(Local::now().offset())) - } else { - let tz: Tz = parse_timezone_internal(s)?; - let offset = tz.offset_from_utc_datetime(&dt.naive_utc()).fix(); - Ok(dt.with_timezone(&offset)) - } - } - Err(e) => Err(e), - } -} - -fn parse_timezone_internal(s: &str) -> Result { - if let Ok(tz) = s.parse() { - Ok(tz) - } else if let Ok(tz) = titlecase(s).parse() { - Ok(tz) - } else if let Ok(tz) = s.to_uppercase().parse() { - Ok(tz) - } else { - Err(ParseErrorKind::Invalid) - } -} - -fn timezone_offset_internal( - mut s: &str, - consume_colon: bool, - allow_missing_minutes: bool, -) -> Result { - fn digits(s: &str) -> Result<(u8, u8), ParseErrorKind> { - let b = s.as_bytes(); - if b.len() < 2 { - Err(ParseErrorKind::TooShort) - } else { - Ok((b[0], b[1])) - } - } - let negative = match s.as_bytes().first() { - Some(&b'+') => false, - Some(&b'-') => true, - Some(_) => return Err(ParseErrorKind::Invalid), - None => return Err(ParseErrorKind::TooShort), - }; - s = &s[1..]; - - // hours (00--99) - let hours = match digits(s)? { - (h1 @ b'0'..=b'9', h2 @ b'0'..=b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')), - _ => return Err(ParseErrorKind::Invalid), - }; - s = &s[2..]; - - // colons (and possibly other separators) - if consume_colon { - s = s.trim_start_matches(|c: char| c == ':' || c.is_whitespace()); - } - - // minutes (00--59) - // if the next two items are digits then we have to add minutes - let minutes = if let Ok(ds) = digits(s) { - match ds { - (m1 @ b'0'..=b'5', m2 @ b'0'..=b'9') => i32::from((m1 - b'0') * 10 + (m2 - b'0')), - (b'6'..=b'9', b'0'..=b'9') => return Err(ParseErrorKind::OutOfRange), - _ => return Err(ParseErrorKind::Invalid), - } - } else if allow_missing_minutes { - 0 - } else { - return Err(ParseErrorKind::TooShort); - }; - match s.len() { - len if len >= 2 => &s[2..], - len if len == 0 => s, - _ => return Err(ParseErrorKind::TooShort), - }; - - let seconds = hours * 3600 + minutes * 60; - Ok(if negative { -seconds } else { seconds }) -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/to_table.rs b/old_nushell/crates/nu-command/src/commands/generators/date/to_table.rs deleted file mode 100644 index 10163451f..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/to_table.rs +++ /dev/null @@ -1,107 +0,0 @@ -use crate::prelude::*; -use chrono::{Datelike, Timelike}; -use indexmap::IndexMap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Primitive, Signature, UntaggedValue, Value}; - -pub struct Date; - -impl WholeStreamCommand for Date { - fn name(&self) -> &str { - "date to-table" - } - - fn signature(&self) -> Signature { - Signature::build("date to-table") - } - - fn usage(&self) -> &str { - "Print the date in a structured table." - } - - fn run(&self, args: CommandArgs) -> Result { - to_table(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Print the current date in a table", - example: "date now | date to-table", - result: None, - }] - } -} - -fn to_table(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let input = if args.input.is_empty() { - InputStream::one(super::now::date_now(&tag)) - } else { - args.input - }; - - Ok(input - .map(move |value| match value { - Value { - value: UntaggedValue::Primitive(Primitive::Date(dt)), - .. - } => { - let mut indexmap = IndexMap::new(); - - indexmap.insert( - "year".to_string(), - UntaggedValue::int(dt.year()).into_value(&tag), - ); - indexmap.insert( - "month".to_string(), - UntaggedValue::int(dt.month()).into_value(&tag), - ); - indexmap.insert( - "day".to_string(), - UntaggedValue::int(dt.day()).into_value(&tag), - ); - indexmap.insert( - "hour".to_string(), - UntaggedValue::int(dt.hour()).into_value(&tag), - ); - indexmap.insert( - "minute".to_string(), - UntaggedValue::int(dt.minute()).into_value(&tag), - ); - indexmap.insert( - "second".to_string(), - UntaggedValue::int(dt.second()).into_value(&tag), - ); - - let tz = dt.offset(); - indexmap.insert( - "timezone".to_string(), - UntaggedValue::string(tz.to_string()).into_value(&tag), - ); - - let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag); - - Ok(value) - } - _ => Err(ShellError::labeled_error( - "Expected a date from pipeline", - "requires date input", - &tag, - )), - }) - .into_input_stream()) -} - -#[cfg(test)] -mod tests { - use super::Date; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Date {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/date/to_timezone.rs b/old_nushell/crates/nu-command/src/commands/generators/date/to_timezone.rs deleted file mode 100644 index 6e1994ba7..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/date/to_timezone.rs +++ /dev/null @@ -1,107 +0,0 @@ -use super::parser::{datetime_in_timezone, ParseErrorKind}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct Date; - -impl WholeStreamCommand for Date { - fn name(&self) -> &str { - "date to-timezone" - } - - fn signature(&self) -> Signature { - Signature::build("date to-timezone").required( - "time zone", - SyntaxShape::String, - "time zone description", - ) - } - - fn usage(&self) -> &str { - "Convert a date to a given time zone." - } - - fn extra_usage(&self) -> &str { - "Use 'date list-timezone' to list all supported time zones." - } - - fn run(&self, args: CommandArgs) -> Result { - to_timezone(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get the current date in UTC+05:00", - example: "date now | date to-timezone +0500", - result: None, - }, - Example { - description: "Get the current local date", - example: "date now | date to-timezone local", - result: None, - }, - Example { - description: "Get the current date in Hawaii", - example: "date now | date to-timezone US/Hawaii", - result: None, - }, - ] - } -} - -fn to_timezone(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let timezone: Tagged = args.req(0)?; - - Ok(args - .input - .map(move |value| match value { - Value { - value: UntaggedValue::Primitive(Primitive::Date(dt)), - .. - } => match datetime_in_timezone(&dt, &timezone.item) { - Ok(dt) => { - let value = UntaggedValue::date(dt).into_value(&tag); - - Ok(value) - } - Err(e) => Err(ShellError::labeled_error( - error_message(e), - "invalid time zone", - &timezone.tag, - )), - }, - _ => Err(ShellError::labeled_error( - "Expected a date from pipeline", - "requires date input", - &tag, - )), - }) - .into_input_stream()) -} - -fn error_message(err: ParseErrorKind) -> &'static str { - match err { - ParseErrorKind::Invalid => "The time zone description is invalid", - ParseErrorKind::OutOfRange => "The time zone offset is out of range", - ParseErrorKind::TooShort => "The format of the time zone is invalid", - } -} - -#[cfg(test)] -mod tests { - use super::Date; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Date {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/for_in.rs b/old_nushell/crates/nu-command/src/commands/generators/for_in.rs deleted file mode 100644 index ef455c610..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/for_in.rs +++ /dev/null @@ -1,167 +0,0 @@ -use crate::prelude::*; -use nu_engine::{evaluate_baseline_expr, run_block}; -use nu_engine::{FromValue, WholeStreamCommand}; - -use nu_errors::ShellError; -use nu_protocol::{ - hir::{CapturedBlock, ExternalRedirection}, - Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value, -}; - -pub struct ForIn; - -impl WholeStreamCommand for ForIn { - fn name(&self) -> &str { - "for" - } - - fn signature(&self) -> Signature { - Signature::build("for") - .required("var", SyntaxShape::String, "the name of the variable") - .required("in", SyntaxShape::String, "the word 'in'") - .required("value", SyntaxShape::Any, "the value we want to iterate") - .required("block", SyntaxShape::Block, "the block to run on each item") - .switch( - "numbered", - "returned a numbered item ($it.index and $it.item)", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Run a block on each row of the table." - } - - fn run(&self, args: CommandArgs) -> Result { - for_in(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Echo the square of each integer", - example: "for x in [1 2 3] { $x * $x }", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(9).into(), - ]), - }, - Example { - description: "Work with elements of a range", - example: "for $x in 1..3 { $x }", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - ]), - }, - Example { - description: "Number each item and echo a message", - example: "for $it in ['bob' 'fred'] --numbered { $\"($it.index) is ($it.item)\" }", - result: Some(vec![Value::from("0 is bob"), Value::from("1 is fred")]), - }, - ] - } -} - -pub fn process_row( - captured_block: &CapturedBlock, - context: &EvaluationContext, - input: Value, - var_name: &str, - external_redirection: ExternalRedirection, -) -> Result { - let input_clone = input.clone(); - // When we process a row, we need to know whether the block wants to have the contents of the row as - // a parameter to the block (so it gets assigned to a variable that can be used inside the block) or - // if it wants the contents as as an input stream - - let input_stream = if !captured_block.block.params.positional.is_empty() { - InputStream::empty() - } else { - vec![Ok(input_clone)].into_iter().into_input_stream() - }; - - context.scope.enter_scope(); - context.scope.add_vars(&captured_block.captured.entries); - - context.scope.add_var(var_name, input); - - let result = run_block( - &captured_block.block, - context, - input_stream, - external_redirection, - ); - - context.scope.exit_scope(); - - result -} - -pub(crate) fn make_indexed_item(index: usize, item: Value) -> Value { - let mut dict = TaggedDictBuilder::new(item.tag()); - dict.insert_untagged("index", UntaggedValue::int(index as i64)); - dict.insert_value("item", item); - - dict.into_value() -} - -fn for_in(args: CommandArgs) -> Result { - let context = args.context.clone(); - let external_redirection = args.call_info.args.external_redirection; - // - let numbered: bool = args.call_info.switch_present("numbered"); - let positional = args - .call_info - .args - .positional - .expect("Internal error: type checker should require args"); - - let var_name = positional[0].var_name()?; - let rhs = evaluate_baseline_expr(&positional[2], &context)?; - - let block: CapturedBlock = - FromValue::from_value(&evaluate_baseline_expr(&positional[3], &context)?)?; - - let input = crate::commands::core_commands::echo::expand_value_to_stream(rhs); - - if numbered { - Ok(input - .enumerate() - .flat_map(move |input| { - let row = make_indexed_item(input.0, input.1); - - match process_row(&block, &context, row, &var_name, external_redirection) { - Ok(s) => s, - Err(e) => OutputStream::one(Value::error(e)), - } - }) - .into_output_stream()) - } else { - Ok(input - .flat_map(move |input| { - let block = block.clone(); - - match process_row(&block, &context, input, &var_name, external_redirection) { - Ok(s) => s, - Err(e) => OutputStream::one(Value::error(e)), - } - }) - .into_output_stream()) - } -} - -#[cfg(test)] -mod tests { - use super::ForIn; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(ForIn {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/hash_/base64_.rs b/old_nushell/crates/nu-command/src/commands/generators/hash_/base64_.rs deleted file mode 100644 index a623bc3a6..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/hash_/base64_.rs +++ /dev/null @@ -1,288 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::{Tag, Tagged}; - -use base64::{decode_config, encode_config}; - -#[derive(Clone)] -pub struct Base64Config { - pub character_set: String, - pub action_type: ActionType, -} - -#[derive(Clone, Copy, PartialEq)] -pub enum ActionType { - Encode, - Decode, -} -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "hash base64" - } - - fn signature(&self) -> Signature { - Signature::build("hash base64") - .named( - "character_set", - SyntaxShape::String, - "specify the character rules for encoding the input.\n\ - \tValid values are 'standard', 'standard-no-padding', 'url-safe', 'url-safe-no-padding',\ - 'binhex', 'bcrypt', 'crypt'", - Some('c'), - ) - .switch( - "encode", - "encode the input as base64. This is the default behavior if not specified.", - Some('e') - ) - .switch( - "decode", - "decode the input from base64", - Some('d')) - .rest( -"rest", - SyntaxShape::ColumnPath, - "optionally base64 encode / decode data by column paths", - ) - } - - fn usage(&self) -> &str { - "base64 encode or decode a value" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Base64 encode a string with default settings", - example: "echo 'username:password' | hash base64", - result: Some(vec![ - UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ=").into_untagged_value() - ]), - }, - Example { - description: "Base64 encode a string with the binhex character set", - example: "echo 'username:password' | hash base64 --character_set binhex --encode", - result: Some(vec![ - UntaggedValue::string("F@0NEPjJD97kE'&bEhFZEP3").into_untagged_value() - ]), - }, - Example { - description: "Base64 decode a value", - example: "echo 'dXNlcm5hbWU6cGFzc3dvcmQ=' | hash base64 --decode", - result: Some(vec![ - UntaggedValue::string("username:password").into_untagged_value() - ]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - - let encode = args.has_flag("encode"); - let decode = args.has_flag("decode"); - let character_set: Option> = args.get_flag("character_set")?; - let column_paths: Vec = args.rest(0)?; - - if encode && decode { - return Err(ShellError::labeled_error( - "only one of --decode and --encode flags can be used", - "conflicting flags", - name_tag, - )); - } - - // Default the action to be encoding if no flags are specified. - let action_type = if decode { - ActionType::Decode - } else { - ActionType::Encode - }; - - // Default the character set to standard if the argument is not specified. - let character_set = match character_set { - Some(inner_tag) => inner_tag.item().to_string(), - None => "standard".to_string(), - }; - - let encoding_config = Base64Config { - character_set, - action_type, - }; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, &encoding_config, v.tag()) - } else { - let mut ret = v; - - for path in &column_paths { - let config = encoding_config.clone(); - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &config, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -fn action( - input: &Value, - base64_config: &Base64Config, - tag: impl Into, -) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let base64_config_enum: base64::Config = if &base64_config.character_set == "standard" { - base64::STANDARD - } else if &base64_config.character_set == "standard-no-padding" { - base64::STANDARD_NO_PAD - } else if &base64_config.character_set == "url-safe" { - base64::URL_SAFE - } else if &base64_config.character_set == "url-safe-no-padding" { - base64::URL_SAFE_NO_PAD - } else if &base64_config.character_set == "binhex" { - base64::BINHEX - } else if &base64_config.character_set == "bcrypt" { - base64::BCRYPT - } else if &base64_config.character_set == "crypt" { - base64::CRYPT - } else { - return Err(ShellError::labeled_error( - "value is not an accepted character set", - format!( - "{} is not a valid character-set.\nPlease use `help hash base64` to see a list of valid character sets.", - &base64_config.character_set - ), - tag.into().span, - )); - }; - - match base64_config.action_type { - ActionType::Encode => Ok(UntaggedValue::string(encode_config( - &s, - base64_config_enum, - )) - .into_value(tag)), - ActionType::Decode => { - let decode_result = decode_config(&s, base64_config_enum); - - match decode_result { - Ok(decoded_value) => Ok(UntaggedValue::string( - std::string::String::from_utf8_lossy(&decoded_value), - ) - .into_value(tag)), - Err(_) => Err(ShellError::labeled_error( - "value could not be base64 decoded", - format!( - "invalid base64 input for character set {}", - &base64_config.character_set - ), - tag.into().span, - )), - } - } - } - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::{action, ActionType, Base64Config}; - use nu_protocol::UntaggedValue; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn base64_encode_standard() { - let word = string("username:password"); - let expected = UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ=").into_untagged_value(); - - let actual = action( - &word, - &Base64Config { - character_set: "standard".to_string(), - action_type: ActionType::Encode, - }, - Tag::unknown(), - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn base64_encode_standard_no_padding() { - let word = string("username:password"); - let expected = UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ").into_untagged_value(); - - let actual = action( - &word, - &Base64Config { - character_set: "standard-no-padding".to_string(), - action_type: ActionType::Encode, - }, - Tag::unknown(), - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn base64_encode_url_safe() { - let word = string("this is for url"); - let expected = UntaggedValue::string("dGhpcyBpcyBmb3IgdXJs").into_untagged_value(); - - let actual = action( - &word, - &Base64Config { - character_set: "url-safe".to_string(), - action_type: ActionType::Encode, - }, - Tag::unknown(), - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn base64_decode_binhex() { - let word = string("A5\"KC9jRB@IIF'8bF!"); - let expected = UntaggedValue::string("a binhex test").into_untagged_value(); - - let actual = action( - &word, - &Base64Config { - character_set: "binhex".to_string(), - action_type: ActionType::Decode, - }, - Tag::unknown(), - ) - .unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/hash_/command.rs b/old_nushell/crates/nu-command/src/commands/generators/hash_/command.rs deleted file mode 100644 index 90ea80962..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/hash_/command.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "hash" - } - - fn signature(&self) -> Signature { - Signature::build("hash").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert by column paths", - ) - } - - fn usage(&self) -> &str { - "Apply hash function." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&Command, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/hash_/generic_digest.rs b/old_nushell/crates/nu-command/src/commands/generators/hash_/generic_digest.rs deleted file mode 100644 index bc0542e5f..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/hash_/generic_digest.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::marker::PhantomData; - -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, SyntaxShape, UntaggedValue, Value}; -use nu_protocol::{ShellTypeName, Signature}; -use nu_source::Tag; - -pub trait HashDigest: digest::Digest { - fn name() -> &'static str; - fn examples() -> Vec; -} - -pub struct SubCommand { - name_string: String, - usage_string: String, - phantom: PhantomData, -} - -impl Default for SubCommand { - fn default() -> Self { - Self { - name_string: format!("hash {}", D::name()), - usage_string: format!("{} encode a value", D::name()), - phantom: PhantomData, - } - } -} - -impl WholeStreamCommand for SubCommand -where - D: HashDigest + Send + Sync, - digest::Output: core::fmt::LowerHex, -{ - fn name(&self) -> &str { - &self.name_string - } - - fn signature(&self) -> Signature { - Signature::build(self.name()).rest( - "rest", - SyntaxShape::ColumnPath, - format!("optionally {} encode data by column paths", D::name()), - ) - } - - fn usage(&self) -> &str { - &self.usage_string - } - - fn examples(&self) -> Vec { - D::examples() - } - - fn run(&self, args: CommandArgs) -> Result { - let column_paths: Vec = args.rest(0)?; - - Ok(args - .input - .map(move |v| { - if column_paths.is_empty() { - action::(&v, v.tag()) - } else { - let mut ret = v; - - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action::(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) - } -} - -pub fn action(input: &Value, tag: Tag) -> Result -where - D: HashDigest, - digest::Output: core::fmt::LowerHex, -{ - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let digest_result = D::digest(s.as_bytes()); - Ok(UntaggedValue::string(&format!("{:x}", digest_result)).into_value(tag)) - } - UntaggedValue::Primitive(Primitive::Binary(bytes)) => { - let digest_result = D::digest(bytes); - Ok(UntaggedValue::string(&format!("{:x}", digest_result)).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - format!("value is not supported for hashing as {}", D::name()), - got, - tag.span, - )) - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/hash_/md5_.rs b/old_nushell/crates/nu-command/src/commands/generators/hash_/md5_.rs deleted file mode 100644 index 0559e7dfc..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/hash_/md5_.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::prelude::*; -use md5::Md5; -use nu_protocol::UntaggedValue; - -use super::generic_digest::{self, HashDigest}; - -pub type SubCommand = generic_digest::SubCommand; - -impl HashDigest for Md5 { - fn name() -> &'static str { - "md5" - } - - fn examples() -> Vec { - vec![ - Example { - description: "md5 encode a string", - example: "echo 'abcdefghijklmnopqrstuvwxyz' | hash md5", - result: Some(vec![UntaggedValue::string( - "c3fcd3d76192e4007dfb496cca67e13b", - ) - .into_untagged_value()]), - }, - Example { - description: "md5 encode a file", - example: "open ./nu_0_24_1_windows.zip | hash md5", - result: Some(vec![UntaggedValue::string( - "dcf30f2836a1a99fc55cf72e28272606", - ) - .into_untagged_value()]), - }, - ] - } -} - -#[cfg(test)] -mod tests { - use md5::Md5; - use nu_protocol::{Primitive, UntaggedValue}; - use nu_source::Tag; - use nu_test_support::value::string; - - use crate::commands::generators::hash_::generic_digest::action; - - #[test] - fn md5_encode_string() { - let word = string("abcdefghijklmnopqrstuvwxyz"); - let expected = - UntaggedValue::string("c3fcd3d76192e4007dfb496cca67e13b").into_untagged_value(); - - let actual = action::(&word, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn md5_encode_bytes() { - let bytes = vec![0xC0, 0xFF, 0xEE]; - let binary = UntaggedValue::Primitive(Primitive::Binary(bytes)).into_untagged_value(); - let expected = - UntaggedValue::string("5f80e231382769b0102b1164cf722d83").into_untagged_value(); - - let actual = action::(&binary, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/hash_/mod.rs b/old_nushell/crates/nu-command/src/commands/generators/hash_/mod.rs deleted file mode 100644 index 0a76ae094..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/hash_/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod base64_; -mod command; -mod generic_digest; -mod md5_; -mod sha256_; - -pub use base64_::SubCommand as HashBase64; -pub use command::Command as Hash; -pub use md5_::SubCommand as HashMd5; -pub use sha256_::SubCommand as HashSha256; diff --git a/old_nushell/crates/nu-command/src/commands/generators/hash_/sha256_.rs b/old_nushell/crates/nu-command/src/commands/generators/hash_/sha256_.rs deleted file mode 100644 index 4028dfdb4..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/hash_/sha256_.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::prelude::*; -use nu_protocol::UntaggedValue; -use sha2::Sha256; - -use super::generic_digest::{self, HashDigest}; - -pub type SubCommand = generic_digest::SubCommand; - -impl HashDigest for Sha256 { - fn name() -> &'static str { - "sha256" - } - - fn examples() -> Vec { - vec![ - Example { - description: "sha256 encode a string", - example: "echo 'abcdefghijklmnopqrstuvwxyz' | hash sha256", - result: Some(vec![UntaggedValue::string( - "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73", - ) - .into_untagged_value()]), - }, - Example { - description: "sha256 encode a file", - example: "open ./nu_0_24_1_windows.zip | hash sha256", - result: Some(vec![UntaggedValue::string( - "c47a10dc272b1221f0380a2ae0f7d7fa830b3e378f2f5309bbf13f61ad211913", - ) - .into_untagged_value()]), - }, - ] - } -} - -#[cfg(test)] -mod tests { - use nu_protocol::{Primitive, UntaggedValue}; - use nu_source::Tag; - use nu_test_support::value::string; - use sha2::Sha256; - - use crate::commands::generators::hash_::generic_digest::action; - - #[test] - fn md5_encode_string() { - let word = string("abcdefghijklmnopqrstuvwxyz"); - let expected = UntaggedValue::string( - "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73", - ) - .into_untagged_value(); - - let actual = action::(&word, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn md5_encode_bytes() { - let bytes = vec![0xC0, 0xFF, 0xEE]; - let binary = UntaggedValue::Primitive(Primitive::Binary(bytes)).into_untagged_value(); - let expected = UntaggedValue::string( - "c47a10dc272b1221f0380a2ae0f7d7fa830b3e378f2f5309bbf13f61ad211913", - ) - .into_untagged_value(); - - let actual = action::(&binary, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/mod.rs b/old_nushell/crates/nu-command/src/commands/generators/mod.rs deleted file mode 100644 index 21e5102bf..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -mod cal; -mod date; -mod for_in; -mod hash_; -mod seq; -mod seq_dates; - -pub use cal::Cal; -pub use date::*; -pub use for_in::ForIn; -pub use hash_::*; -pub use seq::Seq; -pub use seq_dates::SeqDates; diff --git a/old_nushell/crates/nu-command/src/commands/generators/seq.rs b/old_nushell/crates/nu-command/src/commands/generators/seq.rs deleted file mode 100644 index a0eb3fb95..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/seq.rs +++ /dev/null @@ -1,368 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::value::{DecimalExt, I64Ext, StrExt}; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use std::cmp; - -pub struct Seq; - -impl WholeStreamCommand for Seq { - fn name(&self) -> &str { - "seq" - } - - fn signature(&self) -> Signature { - Signature::build("seq") - .rest("rest", SyntaxShape::Number, "sequence values") - .named( - "separator", - SyntaxShape::String, - "separator character (defaults to \\n)", - Some('s'), - ) - .named( - "terminator", - SyntaxShape::String, - "terminator character (defaults to \\n)", - Some('t'), - ) - .switch( - "widths", - "equalize widths of all numbers by padding with zeros", - Some('w'), - ) - } - - fn usage(&self) -> &str { - "Print sequences of numbers." - } - - fn run(&self, args: CommandArgs) -> Result { - seq(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "sequence 1 to 10 with newline separator", - example: "seq 1 10", - result: Some(vec![ - UntaggedValue::int(1).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - UntaggedValue::int(5).into(), - UntaggedValue::int(6).into(), - UntaggedValue::int(7).into(), - UntaggedValue::int(8).into(), - UntaggedValue::int(9).into(), - UntaggedValue::int(10).into(), - ]), - }, - Example { - description: "sequence 1.0 to 2.0 by 0.1s with newline separator", - example: "seq 1.0 0.1 2.0", - result: Some(vec![ - UntaggedValue::decimal_from_float(1.0000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.1000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.2000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.3000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.4000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.5000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.6000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.7000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.8000, Span::default()).into(), - UntaggedValue::decimal_from_float(1.9000, Span::default()).into(), - UntaggedValue::decimal_from_float(2.0000, Span::default()).into(), - ]), - }, - Example { - description: "sequence 1 to 10 with pipe separator", - example: "seq -s '|' 1 10", - result: Some(vec![Value::from("1|2|3|4|5|6|7|8|9|10")]), - }, - Example { - description: "sequence 1 to 10 with pipe separator padded with 0", - example: "seq -s '|' -w 1 10", - result: Some(vec![Value::from("01|02|03|04|05|06|07|08|09|10")]), - }, - Example { - description: "sequence 1 to 10 with pipe separator padded by 2s", - example: "seq -s ' | ' -w 1 2 10", - result: Some(vec![Value::from("01 | 03 | 05 | 07 | 09")]), - }, - ] - } -} - -fn seq(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let rest_nums: Vec> = args.rest(0)?; - let separator: Option> = args.get_flag("separator")?; - let terminator: Option> = args.get_flag("terminator")?; - let widths = args.has_flag("widths"); - - if rest_nums.is_empty() { - return Err(ShellError::labeled_error( - "seq requires some parameters", - "needs parameter", - name, - )); - } - - let sep: String = match separator { - Some(s) => { - if s.item == r"\t" { - '\t'.to_string() - } else if s.item == r"\n" { - '\n'.to_string() - } else if s.item == r"\r" { - '\r'.to_string() - } else { - let vec_s: Vec = s.chars().collect(); - if vec_s.is_empty() { - return Err(ShellError::labeled_error( - "Expected a single separator char from --separator", - "requires a single character string input", - &s.tag, - )); - }; - vec_s.iter().collect() - } - } - _ => '\n'.to_string(), - }; - - let term: String = match terminator { - Some(t) => { - if t.item == r"\t" { - '\t'.to_string() - } else if t.item == r"\n" { - '\n'.to_string() - } else if t.item == r"\r" { - '\r'.to_string() - } else { - let vec_t: Vec = t.chars().collect(); - if vec_t.is_empty() { - return Err(ShellError::labeled_error( - "Expected a single terminator char from --terminator", - "requires a single character string input", - &t.tag, - )); - }; - vec_t.iter().collect() - } - } - _ => '\n'.to_string(), - }; - - let rest_nums: Vec = rest_nums.iter().map(|n| n.item.to_string()).collect(); - - run_seq(sep, Some(term), widths, rest_nums) -} - -#[cfg(test)] -mod tests { - use super::Seq; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Seq {}) - } -} - -fn parse_float(mut s: &str) -> Result { - if s.starts_with('+') { - s = &s[1..]; - } - match s.parse() { - Ok(n) => Ok(n), - Err(e) => Err(format!( - "seq: invalid floating point argument `{}`: {}", - s, e - )), - } -} - -fn escape_sequences(s: &str) -> String { - s.replace("\\n", "\n").replace("\\t", "\t") -} - -pub fn run_seq( - sep: String, - termy: Option, - widths: bool, - free: Vec, -) -> Result { - let mut largest_dec = 0; - let mut padding = 0; - let first = if free.len() > 1 { - let slice = &free[0][..]; - let len = slice.len(); - let dec = slice.find('.').unwrap_or(len); - largest_dec = len - dec; - padding = dec; - match parse_float(slice) { - Ok(n) => n, - Err(s) => { - return Err(ShellError::labeled_error( - s, - "error parsing float", - Tag::unknown(), - )); - } - } - } else { - 1.0 - }; - let step = if free.len() > 2 { - let slice = &free[1][..]; - let len = slice.len(); - let dec = slice.find('.').unwrap_or(len); - largest_dec = cmp::max(largest_dec, len - dec); - padding = cmp::max(padding, dec); - match parse_float(slice) { - Ok(n) => n, - Err(s) => { - return Err(ShellError::labeled_error( - s, - "error parsing float", - Tag::unknown(), - )); - } - } - } else { - 1.0 - }; - let last = { - let slice = &free[free.len() - 1][..]; - padding = cmp::max(padding, slice.find('.').unwrap_or_else(|| slice.len())); - match parse_float(slice) { - Ok(n) => n, - Err(s) => { - return Err(ShellError::labeled_error( - s, - "error parsing float", - Tag::unknown(), - )); - } - } - }; - if largest_dec > 0 { - largest_dec -= 1; - } - let separator = escape_sequences(&sep[..]); - let terminator = match termy { - Some(term) => escape_sequences(&term[..]), - None => separator.clone(), - }; - Ok(print_seq( - first, - step, - last, - largest_dec, - separator, - terminator, - widths, - padding, - )) -} - -fn done_printing(next: f64, step: f64, last: f64) -> bool { - if step >= 0f64 { - next > last - } else { - next < last - } -} - -#[allow(clippy::too_many_arguments)] -fn print_seq( - first: f64, - step: f64, - last: f64, - largest_dec: usize, - separator: String, - terminator: String, - pad: bool, - padding: usize, -) -> OutputStream { - let mut i = 0isize; - let mut value = first + i as f64 * step; - // for string output - let mut ret_str = "".to_owned(); - // for number output - let mut ret_num = vec![]; - // If the separator and terminator are line endings we can convert to numbers - let use_num = - (separator == "\n" || separator == "\r") && (terminator == "\n" || terminator == "\r"); - - while !done_printing(value, step, last) { - if use_num { - ret_num.push(value); - } else { - // formatting for string output with potential padding - let istr = format!("{:.*}", largest_dec, value); - let ilen = istr.len(); - let before_dec = istr.find('.').unwrap_or(ilen); - if pad && before_dec < padding { - for _ in 0..(padding - before_dec) { - ret_str.push('0'); - } - } - ret_str.push_str(&istr); - } - i += 1; - value = first + i as f64 * step; - if !done_printing(value, step, last) { - ret_str.push_str(&separator); - } - } - - if !use_num && ((first >= last && step < 0f64) || (first <= last && step > 0f64)) { - ret_str.push_str(&terminator); - } - - if use_num { - // we'd like to keep the datatype the same for the output, so check - // and see if any of the output is really decimals, and if it is - // we'll make the entire output decimals - let contains_decimals = vec_contains_decimals(&ret_num); - let rows: Vec = ret_num - .iter() - .map(|v| { - if contains_decimals { - v.to_value_create_tag() - } else { - let vi64 = *v as i64; - vi64.to_value_create_tag() - } - }) - .collect(); - (rows.into_iter()).into_output_stream() - } else { - let rows: Vec = ret_str - .lines() - .map(|v| v.to_str_value_create_tag()) - .collect(); - (rows.into_iter()).into_output_stream() - } -} - -fn vec_contains_decimals(array: &[f64]) -> bool { - let mut found_decimal = false; - for x in array { - if x.fract() != 0.0 { - found_decimal = true; - break; - } - } - - found_decimal -} diff --git a/old_nushell/crates/nu-command/src/commands/generators/seq_dates.rs b/old_nushell/crates/nu-command/src/commands/generators/seq_dates.rs deleted file mode 100644 index 184aae7c9..000000000 --- a/old_nushell/crates/nu-command/src/commands/generators/seq_dates.rs +++ /dev/null @@ -1,353 +0,0 @@ -use crate::prelude::*; -use chrono::naive::NaiveDate; -use chrono::{Duration, Local}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{value::I64Ext, value::StrExt, value::StringExt}; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct SeqDates; - -impl WholeStreamCommand for SeqDates { - fn name(&self) -> &str { - "seq date" - } - - fn signature(&self) -> Signature { - Signature::build("seq date") - .named( - "separator", - SyntaxShape::String, - "separator character (defaults to \\n)", - Some('s'), - ) - .named( - "output-format", - SyntaxShape::String, - "prints dates in this format (defaults to %Y-%m-%d)", - Some('o'), - ) - .named( - "input-format", - SyntaxShape::String, - "give argument dates in this format (defaults to %Y-%m-%d)", - Some('i'), - ) - .named( - "begin-date", - SyntaxShape::String, - "beginning date range", - Some('b'), - ) - .named("end-date", SyntaxShape::String, "ending date", Some('e')) - .named( - "increment", - SyntaxShape::Int, - "increment dates by this number", - Some('n'), - ) - .named( - "days", - SyntaxShape::Int, - "number of days to print", - Some('d'), - ) - .switch("reverse", "print dates in reverse", Some('r')) - } - - fn usage(&self) -> &str { - "print sequences of dates" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - seq_dates(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "print the next 10 days in YYYY-MM-DD format with newline separator", - example: "seq date --days 10", - result: None, - }, - Example { - description: "print the previous 10 days in YYYY-MM-DD format with newline separator", - example: "seq date --days 10 -r", - result: None, - }, - Example { - description: "print the previous 10 days starting today in MM/DD/YYYY format with newline separator", - example: "seq date --days 10 -o '%m/%d/%Y' -r", - result: None, - }, - Example { - description: "print the first 10 days in January, 2020", - example: "seq date -b '2020-01-01' -e '2020-01-10'", - result: Some(vec![ - UntaggedValue::string("2020-01-01").into(), - UntaggedValue::string("2020-01-02").into(), - UntaggedValue::string("2020-01-03").into(), - UntaggedValue::string("2020-01-04").into(), - UntaggedValue::string("2020-01-05").into(), - UntaggedValue::string("2020-01-06").into(), - UntaggedValue::string("2020-01-07").into(), - UntaggedValue::string("2020-01-08").into(), - UntaggedValue::string("2020-01-09").into(), - UntaggedValue::string("2020-01-10").into(), - ]), - }, - Example { - description: "print every fifth day between January 1st 2020 and January 31st 2020", - example: "seq date -b '2020-01-01' -e '2020-01-31' -n 5", - result: Some(vec![ - UntaggedValue::string("2020-01-01").into(), - UntaggedValue::string("2020-01-06").into(), - UntaggedValue::string("2020-01-11").into(), - UntaggedValue::string("2020-01-16").into(), - UntaggedValue::string("2020-01-21").into(), - UntaggedValue::string("2020-01-26").into(), - UntaggedValue::string("2020-01-31").into(), - ]), - }, - Example { - description: "starting on May 5th, 2020, print the next 10 days in your locale's date format, colon separated", - example: "seq date -o %x -s ':' -d 10 -b '2020-05-01'", - result: None, - }, - ] - } -} - -fn seq_dates(args: CommandArgs) -> Result { - let _name = args.call_info.name_tag.clone(); - - let separator: Option> = args.get_flag("separator")?; - let output_format: Option> = args.get_flag("output-format")?; - let input_format: Option> = args.get_flag("input-format")?; - let begin_date: Option> = args.get_flag("begin-date")?; - let end_date: Option> = args.get_flag("end-date")?; - let increment: Option> = args.get_flag("increment")?; - let days: Option> = args.get_flag("days")?; - let reverse = args.has_flag("reverse"); - - let sep: String = match separator { - Some(s) => { - if s.item == r"\t" { - '\t'.to_string() - } else if s.item == r"\n" { - '\n'.to_string() - } else if s.item == r"\r" { - '\r'.to_string() - } else { - let vec_s: Vec = s.chars().collect(); - if vec_s.is_empty() { - return Err(ShellError::labeled_error( - "Expected a single separator char from --separator", - "requires a single character string input", - &s.tag, - )); - }; - vec_s.iter().collect() - } - } - _ => '\n'.to_string(), - }; - - let outformat = match output_format { - Some(s) => Some(s.item.to_string_value(s.tag)), - _ => None, - }; - - let informat = match input_format { - Some(s) => Some(s.item.to_string_value(s.tag)), - _ => None, - }; - - let begin = match begin_date { - Some(s) => Some(s.item), - _ => None, - }; - - let end = match end_date { - Some(s) => Some(s.item), - _ => None, - }; - - let inc = match increment { - Some(i) => { - let clone = i.clone(); - i.to_value(clone.tag) - } - _ => (1_i64).to_value_create_tag(), - }; - - let day_count: Option = match days { - Some(i) => Some(i.item.to_value(i.tag)), - _ => None, - }; - - let mut rev = false; - if reverse { - rev = reverse; - } - - run_seq_dates(sep, outformat, informat, begin, end, inc, day_count, rev) -} - -pub fn parse_date_string(s: &str, format: &str) -> Result { - let d = match NaiveDate::parse_from_str(s, format) { - Ok(d) => d, - Err(_) => return Err("Failed to parse date."), - }; - Ok(d) -} - -#[allow(clippy::too_many_arguments)] -pub fn run_seq_dates( - separator: String, - output_format: Option, - input_format: Option, - beginning_date: Option, - ending_date: Option, - increment: Value, - day_count: Option, - reverse: bool, -) -> Result { - let today = Local::today().naive_local(); - let mut step_size: i64 = increment - .as_i64() - .expect("unable to change increment to i64"); - - if step_size == 0 { - return Err(ShellError::labeled_error( - "increment cannot be 0", - "increment cannot be 0", - increment.tag, - )); - } - - let in_format = match input_format { - Some(i) => i.as_string().map_err(|e| { - ShellError::labeled_error( - e.to_string(), - "error with input_format as_string", - i.tag.span, - ) - })?, - None => "%Y-%m-%d".to_string(), - }; - - let out_format = match output_format { - Some(o) => o.as_string().map_err(|e| { - ShellError::labeled_error( - e.to_string(), - "error with output_format as_string", - o.tag.span, - ) - })?, - None => "%Y-%m-%d".to_string(), - }; - - let start_date = match beginning_date { - Some(d) => match parse_date_string(&d, &in_format) { - Ok(nd) => nd, - Err(e) => { - return Err(ShellError::labeled_error( - e, - "Failed to parse date", - Tag::unknown(), - )) - } - }, - _ => today, - }; - - let mut end_date = match ending_date { - Some(d) => match parse_date_string(&d, &in_format) { - Ok(nd) => nd, - Err(e) => { - return Err(ShellError::labeled_error( - e, - "Failed to parse date", - Tag::unknown(), - )) - } - }, - _ => today, - }; - - let mut days_to_output = match day_count { - Some(d) => d.as_i64()?, - None => 0i64, - }; - - // Make the signs opposite if we're created dates in reverse direction - if reverse { - step_size *= -1; - days_to_output *= -1; - } - - if days_to_output != 0 { - end_date = match start_date.checked_add_signed(Duration::days(days_to_output)) { - Some(date) => date, - None => { - return Err(ShellError::labeled_error( - "integer value too large", - "integer value too large", - Tag::unknown(), - )); - } - } - } - - // conceptually counting down with a positive step or counting up with a negative step - // makes no sense, attempt to do what one means by inverting the signs in those cases. - if (start_date > end_date) && (step_size > 0) || (start_date < end_date) && step_size < 0 { - step_size = -step_size; - } - - let is_out_of_range = - |next| (step_size > 0 && next > end_date) || (step_size < 0 && next < end_date); - - let mut next = start_date; - if is_out_of_range(next) { - return Err(ShellError::labeled_error( - "date is out of range", - "date is out of range", - Tag::unknown(), - )); - } - - let mut ret_str = String::from(""); - loop { - ret_str.push_str(&next.format(&out_format).to_string()); - // TODO: check this value is good - next += Duration::days(step_size); - - if is_out_of_range(next) { - break; - } - - ret_str.push_str(&separator); - } - - let rows: Vec = ret_str - .lines() - .map(|v| v.to_str_value_create_tag()) - .collect(); - Ok((rows.into_iter().map(ReturnSuccess::value)).into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::SeqDates; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SeqDates {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/abs.rs b/old_nushell/crates/nu-command/src/commands/math/abs.rs deleted file mode 100644 index e257bca1f..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/abs.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math abs" - } - - fn signature(&self) -> Signature { - Signature::build("math abs") - } - - fn usage(&self) -> &str { - "Returns absolute values of a list of numbers" - } - - fn run(&self, args: CommandArgs) -> Result { - let mapped = args.input.map(move |val| match val.value { - UntaggedValue::Primitive(Primitive::Int(val)) => UntaggedValue::int(val.abs()).into(), - UntaggedValue::Primitive(Primitive::BigInt(val)) => { - UntaggedValue::big_int(val.magnitude().clone()).into() - } - UntaggedValue::Primitive(Primitive::Decimal(val)) => { - UntaggedValue::decimal(val.abs()).into() - } - UntaggedValue::Primitive(Primitive::Duration(val)) => { - UntaggedValue::duration(val).into() - } - other => abs_default(other), - }); - Ok(mapped.into_output_stream()) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get absolute of each value in a list of numbers", - example: "echo [-50 -100.0 25] | math abs", - result: Some(vec![ - UntaggedValue::int(50).into(), - UntaggedValue::decimal_from_float(100.0, Span::default()).into(), - UntaggedValue::int(25).into(), - ]), - }] - } -} - -fn abs_default(_: UntaggedValue) -> Value { - UntaggedValue::Error(ShellError::unexpected( - "Only numerical values are supported", - )) - .into() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/avg.rs b/old_nushell/crates/nu-command/src/commands/math/avg.rs deleted file mode 100644 index 5a93219ae..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/avg.rs +++ /dev/null @@ -1,179 +0,0 @@ -use crate::prelude::*; - -use crate::commands::math::reducers::{reducer_for, Reduce}; -use crate::commands::math::utils::run_with_function; -use nu_engine::WholeStreamCommand; - -use nu_errors::ShellError; -use nu_protocol::{hir::Operator, Primitive, Signature, UntaggedValue, Value}; - -use bigdecimal::FromPrimitive; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math avg" - } - - fn signature(&self) -> Signature { - Signature::build("math avg") - } - - fn usage(&self) -> &str { - "Finds the average of a list of numbers or tables" - } - - fn run(&self, args: CommandArgs) -> Result { - run_with_function(args, average) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get the average of a list of numbers", - example: "echo [-50 100.0 25] | math avg", - result: Some(vec![UntaggedValue::decimal_from_float( - 25.0, - Span::unknown(), - ) - .into()]), - }] - } -} - -fn to_byte(value: &Value) -> Option { - match &value.value { - UntaggedValue::Primitive(Primitive::Int(num)) => { - Some(UntaggedValue::Primitive(Primitive::Filesize(*num as u64)).into_untagged_value()) - } - _ => None, - } -} - -pub fn average(values: &[Value], name: &Tag) -> Result { - let sum = reducer_for(Reduce::Summation); - - let number = BigDecimal::from_usize(values.len()).ok_or_else(|| { - ShellError::labeled_error("nothing to average", "nothing to average", &name.span) - })?; - - let total_rows = UntaggedValue::decimal(number); - - let are_bytes = values - .get(0) - .ok_or_else(|| { - ShellError::unexpected("Cannot perform aggregate math operation on empty data") - })? - .is_filesize(); - - let total = if are_bytes { - to_byte(&sum( - UntaggedValue::int(0).into_untagged_value(), - values - .to_vec() - .iter() - .map(|v| match v { - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(num)), - .. - } => UntaggedValue::int(*num as i64).into_untagged_value(), - other => other.clone(), - }) - .collect::>(), - )?) - .ok_or_else(|| { - ShellError::labeled_error( - "could not convert to big decimal", - "could not convert to big decimal", - &name.span, - ) - }) - } else { - sum(UntaggedValue::int(0).into_untagged_value(), values.to_vec()) - }?; - - match total { - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(num)), - .. - } => { - let left = UntaggedValue::from(Primitive::Int(num as i64)); - let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows); - - match result { - Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) => match result.to_u64() { - Some(number) => Ok(UntaggedValue::filesize(number).into_value(name)), - None => Err(ShellError::labeled_error( - "could not calculate average of non-integer or unrelated types", - "source", - name, - )), - }, - Ok(_) => Err(ShellError::labeled_error( - "could not calculate average of non-integer or unrelated types", - "source", - name, - )), - Err((left_type, right_type)) => Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )), - } - } - Value { - value: UntaggedValue::Primitive(Primitive::Duration(duration)), - .. - } => { - let left = UntaggedValue::from(Primitive::Duration(duration)); - let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows); - - match result { - Ok(UntaggedValue::Primitive(Primitive::Duration(result))) => { - Ok(UntaggedValue::duration(result).into_value(name)) - } - Ok(_) => Err(ShellError::labeled_error( - "could not calculate average of non-integer or unrelated types", - "source", - name, - )), - Err((left_type, right_type)) => Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )), - } - } - Value { - value: UntaggedValue::Primitive(other), - .. - } => { - let left = UntaggedValue::from(other); - let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows); - - match result { - Ok(value) => Ok(value.into_value(name)), - Err((left_type, right_type)) => Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )), - } - } - _ => Err(ShellError::labeled_error( - "could not calculate average of non-integer or unrelated types", - "source", - name, - )), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/ceil.rs b/old_nushell/crates/nu-command/src/commands/math/ceil.rs deleted file mode 100644 index fe54c4434..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/ceil.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::commands::math::utils::run_with_numerical_functions_on_stream; -use crate::prelude::*; -use bigdecimal::One; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math ceil" - } - - fn signature(&self) -> Signature { - Signature::build("math ceil") - } - - fn usage(&self) -> &str { - "Applies the ceil function to a list of numbers" - } - - fn run(&self, args: CommandArgs) -> Result { - let input = args.input; - - run_with_numerical_functions_on_stream( - input, - ceil_int, - ceil_big_int, - ceil_big_decimal, - ceil_default, - ) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Apply the ceil function to a list of numbers", - example: "echo [1.5 2.3 -3.1] | math ceil", - result: Some(vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(3).into(), - UntaggedValue::int(-3).into(), - ]), - }] - } -} - -fn ceil_int(val: i64) -> Value { - UntaggedValue::int(val).into() -} - -fn ceil_big_int(val: BigInt) -> Value { - UntaggedValue::big_int(val).into() -} - -fn ceil_big_decimal(val: BigDecimal) -> Value { - let mut maybe_ceiled = val.round(0); - if maybe_ceiled < val { - maybe_ceiled += BigDecimal::one(); - } - let ceiling = maybe_ceiled.to_i64(); - - match ceiling { - Some(x) => UntaggedValue::int(x).into(), - None => UntaggedValue::Error(ShellError::untagged_runtime_error( - "Value too big to ceiling to an 64-bit integer", - )) - .into(), - } -} - -fn ceil_default(_: UntaggedValue) -> Value { - UntaggedValue::Error(ShellError::unexpected( - "Only numerical values are supported", - )) - .into() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/command.rs b/old_nushell/crates/nu-command/src/commands/math/command.rs deleted file mode 100644 index 84604745f..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/command.rs +++ /dev/null @@ -1,199 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "math" - } - - fn signature(&self) -> Signature { - Signature::build("math") - } - - fn usage(&self) -> &str { - "Use mathematical functions as aggregate functions on a list of numbers or tables." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&Command, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::commands::math::{ - avg::average, max::maximum, median::median, min::minimum, mode::mode, stddev::stddev, - sum::summation, utils::calculate, utils::MathFunction, variance::variance, - }; - use nu_protocol::{row, Value}; - use nu_test_support::value::{decimal, decimal_from_float, int, table}; - use std::str::FromStr; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } - - #[test] - fn test_math_functions() { - struct TestCase { - description: &'static str, - values: Vec, - expected_err: Option, - // Order is: average, minimum, maximum, median, summation - expected_res: Vec>, - } - let tt: Vec = vec![ - TestCase { - description: "Empty data should throw an error", - values: Vec::new(), - expected_err: Some(ShellError::unexpected("Expected data")), - expected_res: Vec::new(), - }, - TestCase { - description: "Single value", - values: vec![int(10)], - expected_err: None, - expected_res: vec![ - Ok(decimal_from_float(10.0)), - Ok(int(10)), - Ok(int(10)), - Ok(int(10)), - Ok(table(&[int(10)])), - Ok(decimal_from_float(0.0)), - Ok(int(10)), - Ok(decimal_from_float(0.0)), - ], - }, - TestCase { - description: "Multiple Values", - values: vec![int(10), int(20), int(30)], - expected_err: None, - expected_res: vec![ - Ok(decimal_from_float(20.0)), - Ok(int(10)), - Ok(int(30)), - Ok(int(20)), - Ok(table(&[int(10), int(20), int(30)])), - Ok(decimal(BigDecimal::from_str("8.164965809277260327324280249019637973219824935522233761442308557503201258191050088466198110348800783").expect("Could not convert to decimal from string"))), - Ok(int(60)), - Ok(decimal(BigDecimal::from_str("66.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667").expect("Could not convert to decimal from string"))), - ], - }, - TestCase { - description: "Mixed Values", - values: vec![int(10), decimal_from_float(26.5), decimal_from_float(26.5)], - expected_err: None, - expected_res: vec![ - Ok(decimal_from_float(21.0)), - Ok(int(10)), - Ok(decimal_from_float(26.5)), - Ok(decimal_from_float(26.5)), - Ok(table(&[decimal_from_float(26.5)])), - Ok(decimal(BigDecimal::from_str("7.77817459305202276840928798315333943213319531457321440247173855894902863154158871367713143880202865").expect("Could not convert to decimal from string"))), - Ok(decimal_from_float(63.0)), - Ok(decimal_from_float(60.5)), - ], - }, - TestCase { - description: "Negative Values", - values: vec![int(-14), int(-11), int(10)], - expected_err: None, - expected_res: vec![ - Ok(decimal_from_float(-5.0)), - Ok(int(-14)), - Ok(int(10)), - Ok(int(-11)), - Ok(table(&[int(-14), int(-11), int(10)])), - Ok(decimal(BigDecimal::from_str("10.67707825203131121081152396559571062628228776946058011397810604284900898365140801704064843595778374").expect("Could not convert to decimal from string"))), - Ok(int(-15)), - Ok(decimal_from_float(114.0)), - ], - }, - TestCase { - description: "Mixed Negative Values", - values: vec![decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)], - expected_err: None, - expected_res: vec![ - Ok(decimal_from_float(-5.0)), - Ok(decimal_from_float(-13.5)), - Ok(int(10)), - Ok(decimal_from_float(-11.5)), - Ok(table(&[decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)])), - Ok(decimal(BigDecimal::from_str("10.63798226482196513098036125801342585449179971588207816421068645273754903468375890632981926875247027").expect("Could not convert to decimal from string"))), - Ok(decimal_from_float(-15.0)), - Ok(decimal(BigDecimal::from_str("113.1666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667").expect("Could not convert to decimal from string"))), - ], - }, - TestCase { - description: "Tables Or Rows", - values: vec![ - row!["col1".to_owned() => int(1), "col2".to_owned() => int(5)], - row!["col1".to_owned() => int(2), "col2".to_owned() => int(6)], - row!["col1".to_owned() => int(3), "col2".to_owned() => int(7)], - row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)], - ], - expected_err: None, - expected_res: vec![ - Ok(row!["col1".to_owned() => decimal_from_float(2.5), "col2".to_owned() => decimal_from_float(6.5)]), - Ok(row!["col1".to_owned() => int(1), "col2".to_owned() => int(5)]), - Ok(row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)]), - Ok(row!["col1".to_owned() => decimal_from_float(2.5), "col2".to_owned() => decimal_from_float(6.5)]), - Ok(row![ - "col1".to_owned() => table(&[int(1), int(2), int(3), int(4)]), - "col2".to_owned() => table(&[int(5), int(6), int(7), int(8)]) - ]), - Ok(row![ - "col1".to_owned() => decimal(BigDecimal::from_str("1.118033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137").expect("Could not convert to decimal from string")), - "col2".to_owned() => decimal(BigDecimal::from_str("1.118033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137").expect("Could not convert to decimal from string")) - ]), - Ok(row!["col1".to_owned() => int(10), "col2".to_owned() => int(26)]), - Ok(row!["col1".to_owned() => decimal_from_float(1.25), "col2".to_owned() => decimal_from_float(1.25)]), - ], - }, - // TODO-Uncomment once Issue: https://github.com/nushell/nushell/issues/1883 is resolved - // TestCase { - // description: "Invalid Mixed Values", - // values: vec![int(10), decimal(26.5), decimal(26.5), string("math")], - // expected_err: Some(ShellError::unimplemented("something")), - // expected_res: vec![], - // }, - ]; - let test_tag = Tag::unknown(); - for tc in &tt { - let tc: &TestCase = tc; // Just for type annotations - let math_functions: Vec = vec![ - average, minimum, maximum, median, mode, stddev, summation, variance, - ]; - let results = math_functions - .into_iter() - .map(|mf| calculate(&tc.values, &test_tag, mf)) - .collect_vec(); - - if tc.expected_err.is_some() { - assert!( - results.iter().all(|r| r.is_err()), - "Expected all functions to error for test-case: {}", - tc.description, - ); - } else { - for (i, res) in results.into_iter().enumerate() { - assert_eq!( - res, tc.expected_res[i], - "math function {} failed on test-case {}", - i, tc.description - ); - } - } - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/eval.rs b/old_nushell/crates/nu-command/src/commands/math/eval.rs deleted file mode 100644 index 679358fa1..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/eval.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math eval" - } - - fn usage(&self) -> &str { - "Evaluate a math expression into a number" - } - - fn signature(&self) -> Signature { - Signature::build("math eval").desc(self.usage()).optional( - "math expression", - SyntaxShape::String, - "the math expression to evaluate", - ) - } - - fn run(&self, args: CommandArgs) -> Result { - eval(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Evalulate math in the pipeline", - example: "echo '10 / 4' | math eval", - result: Some(vec![UntaggedValue::decimal_from_float( - 2.5, - Span::unknown(), - ) - .into()]), - }] - } -} - -pub fn eval(args: CommandArgs) -> Result { - let expression: Option> = args.opt(0)?; - let name = args.call_info.name_tag.clone(); - let input = args.input; - - if let Some(string) = expression { - match parse(&string, &string.tag) { - Ok(value) => Ok(OutputStream::one(value)), - Err(err) => Err(ShellError::labeled_error( - "Math evaluation error", - err, - &string.tag.span, - )), - } - } else { - let mapped: Result, _> = input - .map(move |x| { - if let Some(Tagged { - tag, - item: expression, - }) = &expression - { - UntaggedValue::string(expression).into_value(tag) - } else { - x - } - }) - .map(move |input| { - if let Ok(string) = input.as_string() { - match parse(&string, &input.tag) { - Ok(value) => Ok(value), - Err(err) => Err(ShellError::labeled_error( - "Math evaluation error", - err, - &input.tag.span, - )), - } - } else { - Err(ShellError::labeled_error( - "Expected a string from pipeline", - "requires string input", - name.clone(), - )) - } - }) - .collect(); - match mapped { - Ok(values) => Ok(OutputStream::from(values)), - Err(e) => Err(e), - } - } -} - -pub fn parse>(math_expression: &str, tag: T) -> Result { - let mut ctx = meval::Context::new(); - ctx.var("tau", std::f64::consts::TAU); - match meval::eval_str_with_context(math_expression, &ctx) { - Ok(num) if num.is_infinite() || num.is_nan() => Err("cannot represent result".to_string()), - Ok(num) => Ok(UntaggedValue::from(Primitive::from(num)).into_value(tag)), - Err(error) => Err(error.to_string().to_lowercase()), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/floor.rs b/old_nushell/crates/nu-command/src/commands/math/floor.rs deleted file mode 100644 index 3ec9ebf21..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/floor.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::commands::math::utils::run_with_numerical_functions_on_stream; -use crate::prelude::*; -use bigdecimal::One; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math floor" - } - - fn signature(&self) -> Signature { - Signature::build("math floor") - } - - fn usage(&self) -> &str { - "Applies the floor function to a list of numbers" - } - - fn run(&self, args: CommandArgs) -> Result { - let input = args.input; - - run_with_numerical_functions_on_stream( - input, - floor_int, - floor_big_int, - floor_big_decimal, - floor_default, - ) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Apply the floor function to a list of numbers", - example: "echo [1.5 2.3 -3.1] | math floor", - result: Some(vec![ - UntaggedValue::big_int(1).into(), - UntaggedValue::big_int(2).into(), - UntaggedValue::big_int(-4).into(), - ]), - }] - } -} - -fn floor_int(val: i64) -> Value { - UntaggedValue::int(val).into() -} - -fn floor_big_int(val: BigInt) -> Value { - UntaggedValue::big_int(val).into() -} - -fn floor_big_decimal(val: BigDecimal) -> Value { - let mut maybe_floored = val.round(0); - if maybe_floored > val { - maybe_floored -= BigDecimal::one(); - } - let (floored, _) = maybe_floored.into_bigint_and_exponent(); - UntaggedValue::big_int(floored).into() -} - -fn floor_default(_: UntaggedValue) -> Value { - UntaggedValue::Error(ShellError::unexpected( - "Only numerical values are supported", - )) - .into() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/max.rs b/old_nushell/crates/nu-command/src/commands/math/max.rs deleted file mode 100644 index 0facfafcc..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/max.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::commands::math::reducers::{reducer_for, Reduce}; -use crate::commands::math::utils::run_with_function; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math max" - } - - fn signature(&self) -> Signature { - Signature::build("math max") - } - - fn usage(&self) -> &str { - "Finds the maximum within a list of numbers or tables" - } - - fn run(&self, args: CommandArgs) -> Result { - run_with_function(args, maximum) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Find the maximum of list of numbers", - example: "echo [-50 100 25] | math max", - result: Some(vec![UntaggedValue::int(100).into()]), - }] - } -} - -pub fn maximum(values: &[Value], _name: &Tag) -> Result { - let max_func = reducer_for(Reduce::Maximum); - max_func(Value::nothing(), values.to_vec()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/median.rs b/old_nushell/crates/nu-command/src/commands/math/median.rs deleted file mode 100644 index 9cc735a7d..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/median.rs +++ /dev/null @@ -1,185 +0,0 @@ -use crate::commands::math::reducers::{reducer_for, Reduce}; -use crate::commands::math::utils::run_with_function; -use crate::prelude::*; -use bigdecimal::FromPrimitive; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{hir::Operator, Primitive, Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math median" - } - - fn signature(&self) -> Signature { - Signature::build("math median") - } - - fn usage(&self) -> &str { - "Gets the median of a list of numbers" - } - - fn run(&self, args: CommandArgs) -> Result { - run_with_function(args, median) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get the median of a list of numbers", - example: "echo [3 8 9 12 12 15] | math median", - result: Some(vec![UntaggedValue::decimal_from_float( - 10.5, - Span::unknown(), - ) - .into()]), - }] - } -} - -enum Pick { - MedianAverage, - Median, -} - -pub fn median(values: &[Value], name: &Tag) -> Result { - let take = if values.len() % 2 == 0 { - Pick::MedianAverage - } else { - Pick::Median - }; - - let mut sorted = vec![]; - - for item in values { - sorted.push(item.clone()); - } - - crate::commands::filters::sort_by::sort(&mut sorted, &[], name, false)?; - - match take { - Pick::Median => { - let idx = (values.len() as f64 / 2.0).floor() as usize; - let out = sorted.get(idx).ok_or_else(|| { - ShellError::labeled_error( - "could not extract value", - "could not extract value", - &name.span, - ) - })?; - Ok(out.clone()) - } - Pick::MedianAverage => { - let idx_end = (values.len() / 2) as usize; - let idx_start = idx_end - 1; - - let left = sorted - .get(idx_start) - .ok_or_else(|| { - ShellError::labeled_error( - "could not extract value", - "could not extract value", - &name.span, - ) - })? - .clone(); - - let right = sorted - .get(idx_end) - .ok_or_else(|| { - ShellError::labeled_error( - "could not extract value", - "could not extract value", - &name.span, - ) - })? - .clone(); - - compute_average(&[left, right], name) - } - } -} - -fn compute_average(values: &[Value], name: impl Into) -> Result { - let name = name.into(); - - let sum = reducer_for(Reduce::Summation); - let number = BigDecimal::from_usize(2).ok_or_else(|| { - ShellError::labeled_error( - "could not convert to big decimal", - "could not convert to big decimal", - &name, - ) - })?; - - let total_rows = UntaggedValue::decimal(number); - let total = sum(Value::nothing(), values.to_vec())?; - - match total { - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(num)), - .. - } => { - let left = UntaggedValue::from(Primitive::Int(num as i64)); - let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows); - - match result { - Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) => { - let (bi, _) = result.as_bigint_and_exponent(); - let number = bi.to_u64(); - match number { - Some(number) => Ok(UntaggedValue::filesize(number).into_value(name)), - None => Err(ShellError::labeled_error( - "Can't convert to filesize", - "can't convert to filesize", - name, - )), - } - } - Ok(_) => Err(ShellError::labeled_error( - "could not calculate median of non-numeric or unrelated types", - "source", - name, - )), - Err((left_type, right_type)) => Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )), - } - } - Value { - value: UntaggedValue::Primitive(other), - .. - } => { - let left = UntaggedValue::from(other); - let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows); - - match result { - Ok(value) => Ok(value.into_value(name)), - Err((left_type, right_type)) => Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )), - } - } - _ => Err(ShellError::labeled_error( - "could not calculate median of non-numeric or unrelated types", - "source", - name, - )), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/min.rs b/old_nushell/crates/nu-command/src/commands/math/min.rs deleted file mode 100644 index 2ed64a0c4..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/min.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::commands::math::reducers::{reducer_for, Reduce}; -use crate::commands::math::utils::run_with_function; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math min" - } - - fn signature(&self) -> Signature { - Signature::build("math min") - } - - fn usage(&self) -> &str { - "Finds the minimum within a list of numbers or tables" - } - - fn run(&self, args: CommandArgs) -> Result { - run_with_function(args, minimum) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get the minimum of a list of numbers", - example: "echo [-50 100 25] | math min", - result: Some(vec![UntaggedValue::int(-50).into()]), - }] - } -} - -pub fn minimum(values: &[Value], _name: &Tag) -> Result { - let min_func = reducer_for(Reduce::Minimum); - min_func(Value::nothing(), values.to_vec()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/mod.rs b/old_nushell/crates/nu-command/src/commands/math/mod.rs deleted file mode 100644 index 66ca5f1e1..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -pub mod abs; -pub mod avg; -pub mod ceil; -pub mod command; -pub mod eval; -pub mod floor; -pub mod max; -pub mod median; -pub mod min; -pub mod mode; -pub mod product; -pub mod round; -pub mod sqrt; -pub mod stddev; -pub mod sum; -pub mod variance; - -mod reducers; -mod utils; - -pub use abs::SubCommand as MathAbs; -pub use avg::SubCommand as MathAverage; -pub use ceil::SubCommand as MathCeil; -pub use command::Command as Math; -pub use eval::SubCommand as MathEval; -pub use floor::SubCommand as MathFloor; -pub use max::SubCommand as MathMaximum; -pub use median::SubCommand as MathMedian; -pub use min::SubCommand as MathMinimum; -pub use mode::SubCommand as MathMode; -pub use product::SubCommand as MathProduct; -pub use round::SubCommand as MathRound; -pub use sqrt::SubCommand as MathSqrt; -pub use stddev::SubCommand as MathStddev; -pub use sum::SubCommand as MathSummation; -pub use variance::SubCommand as MathVariance; diff --git a/old_nushell/crates/nu-command/src/commands/math/mode.rs b/old_nushell/crates/nu-command/src/commands/math/mode.rs deleted file mode 100644 index 61c7ea50c..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/mode.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::commands::math::utils::run_with_function; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue, Value}; -use std::cmp::Ordering; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math mode" - } - - fn signature(&self) -> Signature { - Signature::build("math mode") - } - - fn usage(&self) -> &str { - "Gets the most frequent element(s) from a list of numbers or tables" - } - - fn run(&self, args: CommandArgs) -> Result { - run_with_function(args, mode) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get the mode(s) of a list of numbers", - example: "echo [3 3 9 12 12 15] | math mode", - result: Some(vec![ - UntaggedValue::int(3).into_untagged_value(), - UntaggedValue::int(12).into_untagged_value(), - ]), - }] - } -} - -pub fn mode(values: &[Value], name: &Tag) -> Result { - let mut frequency_map = std::collections::HashMap::new(); - for v in values { - let counter = frequency_map.entry(v.value.clone()).or_insert(0); - *counter += 1; - } - - let mut max_freq = -1; - let mut modes = Vec::::new(); - for (value, frequency) in &frequency_map { - match max_freq.cmp(frequency) { - Ordering::Less => { - max_freq = *frequency; - modes.clear(); - modes.push(value.clone().into_value(name)); - } - Ordering::Equal => { - modes.push(value.clone().into_value(name)); - } - Ordering::Greater => (), - } - } - - crate::commands::filters::sort_by::sort(&mut modes, &[], name, false)?; - Ok(UntaggedValue::Table(modes).into_value(name)) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/product.rs b/old_nushell/crates/nu-command/src/commands/math/product.rs deleted file mode 100644 index 880eb2920..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/product.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::commands::math::reducers::{reducer_for, Reduce}; -use crate::commands::math::utils::run_with_function; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math product" - } - - fn signature(&self) -> Signature { - Signature::build("math product") - } - - fn usage(&self) -> &str { - "Finds the product of a list of numbers or tables" - } - - fn run(&self, args: CommandArgs) -> Result { - run_with_function(args, product) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get the product of a list of numbers", - example: "echo [2 3 3 4] | math product", - result: Some(vec![UntaggedValue::int(72).into()]), - }] - } -} - -fn to_byte(value: &Value) -> Option { - match &value.value { - UntaggedValue::Primitive(Primitive::Int(num)) => { - Some(UntaggedValue::Primitive(Primitive::Filesize(*num as u64)).into_untagged_value()) - } - _ => None, - } -} - -/// Calculate product of given values -pub fn product(values: &[Value], name: &Tag) -> Result { - let prod = reducer_for(Reduce::Product); - - let first = values.get(0).ok_or_else(|| { - ShellError::unexpected("Cannot perform aggregate math operation on empty data") - })?; - - match first { - v if v.is_filesize() => to_byte(&prod( - UntaggedValue::int(1).into_untagged_value(), - values - .iter() - .map(|v| match v { - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(num)), - .. - } => UntaggedValue::int(*num as i64).into_untagged_value(), - other => other.clone(), - }) - .collect::>(), - )?) - .ok_or_else(|| { - ShellError::labeled_error( - "could not convert to decimal", - "could not convert to decimal", - &name.span, - ) - }), - - v if v.is_none() => prod( - UntaggedValue::int(1).into_untagged_value(), - values - .iter() - .map(|v| match v { - Value { - value: UntaggedValue::Primitive(Primitive::Nothing), - .. - } => UntaggedValue::int(1).into_untagged_value(), - other => other.clone(), - }) - .collect::>(), - ), - _ => prod(UntaggedValue::int(1).into_untagged_value(), values.to_vec()), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/reducers.rs b/old_nushell/crates/nu-command/src/commands/math/reducers.rs deleted file mode 100644 index fdf183172..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/reducers.rs +++ /dev/null @@ -1,183 +0,0 @@ -use nu_data::value::{compare_values, compute_values}; -use nu_errors::ShellError; -use nu_protocol::hir::Operator; -use nu_protocol::{UntaggedValue, Value}; -use nu_source::{SpannedItem, Tag}; - -// Re-usable error messages -const ERR_EMPTY_DATA: &str = "Cannot perform aggregate math operation on empty data"; - -fn formula( - acc_begin: Value, - calculator: Box) -> Result + Send + Sync + 'static>, -) -> Box) -> Result + Send + Sync + 'static> { - Box::new(move |acc, datax| -> Result { - let result = match compute_values(Operator::Multiply, &acc, &acc_begin) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned_unknown(), - right_type.spanned_unknown(), - )) - } - }; - - match calculator(datax) { - Ok(total) => Ok(match compute_values(Operator::Plus, &result, &total) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned_unknown(), - right_type.spanned_unknown(), - )) - } - }), - Err(reason) => Err(reason), - } - }) -} - -pub fn reducer_for( - command: Reduce, -) -> Box) -> Result + Send + Sync + 'static> { - match command { - Reduce::Default => Box::new(formula( - UntaggedValue::int(0).into_untagged_value(), - Box::new(sum), - )), - Reduce::Summation => Box::new(|_, values| sum(values)), - Reduce::Minimum => Box::new(|_, values| min(values)), - Reduce::Maximum => Box::new(|_, values| max(values)), - Reduce::Product => Box::new(|_, values| product(values)), - } -} - -#[allow(dead_code)] -pub enum Reduce { - Summation, - Minimum, - Maximum, - Product, - Default, -} - -pub fn sum(data: Vec) -> Result { - let first_value = data - .get(0) - .ok_or_else(|| ShellError::unexpected(ERR_EMPTY_DATA))?; - - // Generate the initial accumulator value, of the correct type for - // the incoming data, this will be used in conjunction with the - // sum aggregator. Currently this is only handling, filesize, - // and other types are defaulting to an integer. - let mut acc = if first_value.is_filesize() { - UntaggedValue::filesize(0u64).into_untagged_value() - } else { - UntaggedValue::int(0).into_untagged_value() - }; - - for value in data { - match value.value { - UntaggedValue::Primitive(_) => { - acc = match compute_values(Operator::Plus, &acc, &value) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned_unknown(), - right_type.spanned_unknown(), - )) - } - }; - } - _ => { - return Err(ShellError::labeled_error( - "Attempted to compute the sum of a value that cannot be summed.", - "value appears here", - value.tag.span, - )) - } - } - } - Ok(acc) -} - -pub fn max(data: Vec) -> Result { - let mut biggest = data - .first() - .ok_or_else(|| ShellError::unexpected(ERR_EMPTY_DATA))? - .value - .clone(); - - for value in &data { - if let Ok(greater_than) = compare_values(Operator::GreaterThan, &value.value, &biggest) { - if greater_than { - biggest = value.value.clone(); - } - } else { - return Err(ShellError::unexpected(format!( - "Could not compare\nleft: {:?}\nright: {:?}", - biggest, value.value - ))); - } - } - Ok(Value { - value: biggest, - tag: Tag::unknown(), - }) -} - -pub fn min(data: Vec) -> Result { - let mut smallest = data - .first() - .ok_or_else(|| ShellError::unexpected(ERR_EMPTY_DATA))? - .value - .clone(); - - for value in &data { - if let Ok(greater_than) = compare_values(Operator::LessThan, &value.value, &smallest) { - if greater_than { - smallest = value.value.clone(); - } - } else { - return Err(ShellError::unexpected(format!( - "Could not compare\nleft: {:?}\nright: {:?}", - smallest, value.value - ))); - } - } - Ok(Value { - value: smallest, - tag: Tag::unknown(), - }) -} - -pub fn product(data: Vec) -> Result { - if data.is_empty() { - return Err(ShellError::unexpected(ERR_EMPTY_DATA)); - } - - let mut prod = UntaggedValue::int(1).into_untagged_value(); - for value in data { - match value.value { - UntaggedValue::Primitive(_) => { - prod = match compute_values(Operator::Multiply, &prod, &value) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned_unknown(), - right_type.spanned_unknown(), - )) - } - }; - } - _ => { - return Err(ShellError::labeled_error( - "Attempted to compute the product of a value that cannot be multiplied.", - "value appears here", - value.tag.span, - )) - } - } - } - Ok(prod) -} diff --git a/old_nushell/crates/nu-command/src/commands/math/round.rs b/old_nushell/crates/nu-command/src/commands/math/round.rs deleted file mode 100644 index 79eb92234..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/round.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math round" - } - - fn signature(&self) -> Signature { - Signature::build("math round").named( - "precision", - SyntaxShape::Number, - "digits of precision", - Some('p'), - ) - } - - fn usage(&self) -> &str { - "Applies the round function to a list of numbers" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Apply the round function to a list of numbers", - example: "echo [1.5 2.3 -3.1] | math round", - result: Some(vec![ - UntaggedValue::int(2).into(), - UntaggedValue::int(2).into(), - UntaggedValue::int(-3).into(), - ]), - }, - Example { - description: "Apply the round function with precision specified", - example: "echo [1.555 2.333 -3.111] | math round -p 2", - result: Some(vec![ - UntaggedValue::decimal_from_float(1.56, Span::default()).into(), - UntaggedValue::decimal_from_float(2.33, Span::default()).into(), - UntaggedValue::decimal_from_float(-3.11, Span::default()).into(), - ]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let precision: Option> = args.get_flag("precision")?; - let input = args.input; - let precision = if let Some(precision) = precision { - precision.item - } else { - 0 - }; - let mapped = input.map(move |val| match val.value { - UntaggedValue::Primitive(Primitive::BigInt(val)) => round_big_int(val), - UntaggedValue::Primitive(Primitive::Decimal(val)) => { - round_big_decimal(val, precision.into()) - } - UntaggedValue::Primitive(Primitive::Int(val)) => UntaggedValue::int(val).into(), - other => round_default(other), - }); - Ok(mapped.into_output_stream()) -} - -fn round_big_int(val: BigInt) -> Value { - UntaggedValue::big_int(val).into() -} - -fn round_big_decimal(val: BigDecimal, precision: i64) -> Value { - if precision > 0 { - UntaggedValue::decimal(val.with_scale(precision + 1).round(precision)).into() - } else { - let rounded = val.with_scale(precision + 1).round(precision).to_i64(); - - match rounded { - Some(x) => UntaggedValue::int(x).into(), - None => UntaggedValue::Error(ShellError::untagged_runtime_error( - "Number too larger to round to 64-bit int", - )) - .into(), - } - } -} - -fn round_default(_: UntaggedValue) -> Value { - UntaggedValue::Error(ShellError::unexpected( - "Only numerical values are supported", - )) - .into() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/sqrt.rs b/old_nushell/crates/nu-command/src/commands/math/sqrt.rs deleted file mode 100644 index ef0815d43..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/sqrt.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math sqrt" - } - - fn signature(&self) -> Signature { - Signature::build("math sqrt") - } - - fn usage(&self) -> &str { - "Applies the square root function to a list of numbers" - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(operate(args)) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Apply the square root function to a list of numbers", - example: "echo [9 16] | math sqrt", - result: Some(vec![ - UntaggedValue::int(3).into(), - UntaggedValue::int(4).into(), - ]), - }] - } -} - -fn operate(args: CommandArgs) -> OutputStream { - let mapped = args.input.map(move |val| match val.value { - UntaggedValue::Primitive(Primitive::Int(val)) => sqrt_big_decimal(BigDecimal::from(val)), - UntaggedValue::Primitive(Primitive::Decimal(val)) => sqrt_big_decimal(val), - other => sqrt_default(other), - }); - mapped.into_output_stream() -} - -fn sqrt_big_decimal(val: BigDecimal) -> Value { - let squared = val.sqrt(); - match squared { - None => UntaggedValue::Error(ShellError::untagged_runtime_error( - "Can't square root a negative number", - )) - .into(), - Some(val) if !val.is_integer() => UntaggedValue::decimal(val.normalized()).into(), - Some(val) => match val.to_i64() { - Some(x) => UntaggedValue::int(x).into(), - None => UntaggedValue::Error(ShellError::untagged_runtime_error( - "Value too large to convert to 64-bit integer", - )) - .into(), - }, - } -} - -fn sqrt_default(_: UntaggedValue) -> Value { - UntaggedValue::Error(ShellError::unexpected( - "Only numerical values are supported", - )) - .into() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/stddev.rs b/old_nushell/crates/nu-command/src/commands/math/stddev.rs deleted file mode 100644 index 02f0ce824..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/stddev.rs +++ /dev/null @@ -1,139 +0,0 @@ -use super::variance::compute_variance as variance; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Primitive, Signature, UntaggedValue, Value}; -use std::str::FromStr; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math stddev" - } - - fn signature(&self) -> Signature { - Signature::build("math stddev").switch( - "sample", - "calculate sample standard deviation", - Some('s'), - ) - } - - fn usage(&self) -> &str { - "Finds the stddev of a list of numbers or tables" - } - - fn run(&self, mut args: CommandArgs) -> Result { - let sample: bool = args.has_flag("sample"); - let values: Vec = args.input.drain_vec(); - let name = args.call_info.name_tag; - - let n = if sample { - values.len() - 1 - } else { - values.len() - }; - - let res = if values.iter().all(|v| v.is_primitive()) { - compute_stddev(&values, n, &name) - } else { - // If we are not dealing with Primitives, then perhaps we are dealing with a table - // Create a key for each column name - let mut column_values = IndexMap::new(); - for value in values { - if let UntaggedValue::Row(row_dict) = &value.value { - for (key, value) in &row_dict.entries { - column_values - .entry(key.clone()) - .and_modify(|v: &mut Vec| v.push(value.clone())) - .or_insert(vec![value.clone()]); - } - } - } - // The mathematical function operates over the columns of the table - let mut column_totals = IndexMap::new(); - for (col_name, col_vals) in column_values { - if let Ok(out) = compute_stddev(&col_vals, n, &name) { - column_totals.insert(col_name, out); - } - } - - if column_totals.keys().len() == 0 { - return Err(ShellError::labeled_error( - "Attempted to compute values that can't be operated on", - "value appears here", - name.span, - )); - } - - Ok(UntaggedValue::Row(Dictionary { - entries: column_totals, - }) - .into_untagged_value()) - }?; - - if res.value.is_table() { - Ok(OutputStream::from( - res.table_entries().cloned().collect::>(), - )) - } else { - Ok(OutputStream::one(res)) - } - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get the stddev of a list of numbers", - example: "echo [1 2 3 4 5] | math stddev", - result: Some(vec![UntaggedValue::decimal(BigDecimal::from_str("1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573").expect("Could not convert to decimal from string")).into()]), - }, - Example { - description: "Get the sample stddev of a list of numbers", - example: "echo [1 2 3 4 5] | math stddev -s", - result: Some(vec![UntaggedValue::decimal(BigDecimal::from_str("1.581138830084189665999446772216359266859777569662608413428752426396297219319619110672124054189650148").expect("Could not convert to decimal from string")).into()]), - }, - ] - } -} - -#[cfg(test)] -pub fn stddev(values: &[Value], name: &Tag) -> Result { - compute_stddev(values, values.len(), name) -} - -pub fn compute_stddev(values: &[Value], n: usize, name: &Tag) -> Result { - let variance = variance(values, n, name)?.as_primitive()?; - let sqrt_var = match variance { - Primitive::Decimal(var) => var.sqrt(), - _ => { - return Err(ShellError::labeled_error( - "Could not take square root of variance", - "error occurred here", - name.span, - )) - } - }; - match sqrt_var { - Some(stddev) => Ok(UntaggedValue::from(Primitive::Decimal(stddev)).into_value(name)), - None => Err(ShellError::labeled_error( - "Could not calculate stddev", - "error occurred here", - name.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/sum.rs b/old_nushell/crates/nu-command/src/commands/math/sum.rs deleted file mode 100644 index 30ba8c22a..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/sum.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::commands::math::reducers::{reducer_for, Reduce}; -use crate::commands::math::utils::run_with_function; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; - -use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math sum" - } - - fn signature(&self) -> Signature { - Signature::build("math sum") - } - - fn usage(&self) -> &str { - "Finds the sum of a list of numbers or tables" - } - - fn run(&self, args: CommandArgs) -> Result { - run_with_function(args, summation) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Sum a list of numbers", - example: "echo [1 2 3] | math sum", - result: Some(vec![UntaggedValue::int(6).into()]), - }, - Example { - description: "Get the disk usage for the current directory", - example: "ls --all --du | get size | math sum", - result: None, - }, - ] - } -} - -fn to_byte(value: &Value) -> Option { - match &value.value { - UntaggedValue::Primitive(Primitive::Int(num)) => { - Some(UntaggedValue::Primitive(Primitive::Filesize(*num as u64)).into_untagged_value()) - } - _ => None, - } -} - -pub fn summation(values: &[Value], name: &Tag) -> Result { - let sum = reducer_for(Reduce::Summation); - - let first = values.get(0).ok_or_else(|| { - ShellError::labeled_error( - "Cannot perform aggregate math operation on empty data", - "expected input", - name.span, - ) - })?; - - match first { - v if v.is_filesize() => to_byte(&sum( - UntaggedValue::int(0).into_untagged_value(), - values - .to_vec() - .iter() - .map(|v| match v { - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(num)), - .. - } => UntaggedValue::int(*num as i64).into_untagged_value(), - other => other.clone(), - }) - .collect::>(), - )?) - .ok_or_else(|| { - ShellError::labeled_error( - "could not convert to big decimal", - "could not convert to big decimal", - &name.span, - ) - }), - v if v.is_duration() => sum(UntaggedValue::int(0).into_untagged_value(), values.to_vec()), - // v is nothing primitive - v if v.is_none() => sum( - UntaggedValue::int(0).into_untagged_value(), - values - .to_vec() - .iter() - .map(|v| match v { - Value { - value: UntaggedValue::Primitive(Primitive::Nothing), - .. - } => UntaggedValue::int(0).into_untagged_value(), - other => other.clone(), - }) - .collect::>(), - ), - _ => sum(UntaggedValue::int(0).into_untagged_value(), values.to_vec()), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/utils.rs b/old_nushell/crates/nu-command/src/commands/math/utils.rs deleted file mode 100644 index 19ee44b84..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/utils.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Primitive, UntaggedValue, Value}; - -use indexmap::map::IndexMap; - -pub type MathFunction = fn(values: &[Value], tag: &Tag) -> Result; - -pub fn run_with_function( - args: impl Into, - mf: MathFunction, -) -> Result { - let RunnableContext { - mut input, - call_info, - .. - } = args.into(); - let name = call_info.name_tag; - - let values: Vec = input.drain_vec(); - - let res = calculate(&values, &name, mf); - match res { - Ok(v) => { - if v.value.is_table() { - Ok(OutputStream::from( - v.table_entries().cloned().collect::>(), - )) - } else { - Ok(OutputStream::one(v)) - } - } - Err(e) => Err(e), - } -} - -pub type BigIntFunction = fn(val: BigInt) -> Value; - -pub type IntFunction = fn(val: i64) -> Value; - -pub type DecimalFunction = fn(val: BigDecimal) -> Value; - -pub type DefaultFunction = fn(val: UntaggedValue) -> Value; - -pub fn run_with_numerical_functions_on_stream( - input: InputStream, - int_function: IntFunction, - big_int_function: BigIntFunction, - decimal_function: DecimalFunction, - default_function: DefaultFunction, -) -> Result { - let mapped = input.map(move |val| match val.value { - UntaggedValue::Primitive(Primitive::Int(val)) => int_function(val), - UntaggedValue::Primitive(Primitive::BigInt(val)) => big_int_function(val), - UntaggedValue::Primitive(Primitive::Decimal(val)) => decimal_function(val), - other => default_function(other), - }); - Ok(mapped.into_output_stream()) -} - -pub fn calculate(values: &[Value], name: &Tag, mf: MathFunction) -> Result { - if values.iter().all(|v| v.is_primitive()) { - mf(values, name) - } else { - // If we are not dealing with Primitives, then perhaps we are dealing with a table - // Create a key for each column name - let mut column_values = IndexMap::new(); - for value in values { - if let UntaggedValue::Row(row_dict) = &value.value { - for (key, value) in &row_dict.entries { - column_values - .entry(key.clone()) - .and_modify(|v: &mut Vec| v.push(value.clone())) - .or_insert(vec![value.clone()]); - } - } - } - // The mathematical function operates over the columns of the table - let mut column_totals = IndexMap::new(); - for (col_name, col_vals) in column_values { - if let Ok(out) = mf(&col_vals, name) { - column_totals.insert(col_name, out); - } - } - - if column_totals.keys().len() == 0 { - return Err(ShellError::labeled_error( - "Attempted to compute values that can't be operated on", - "value appears here", - name.span, - )); - } - - Ok(UntaggedValue::Row(Dictionary { - entries: column_totals, - }) - .into_untagged_value()) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/math/variance.rs b/old_nushell/crates/nu-command/src/commands/math/variance.rs deleted file mode 100644 index a73b4e60f..000000000 --- a/old_nushell/crates/nu-command/src/commands/math/variance.rs +++ /dev/null @@ -1,236 +0,0 @@ -use crate::prelude::*; -use bigdecimal::FromPrimitive; -use nu_data::value::compute_values; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{hir::Operator, Dictionary, Primitive, Signature, UntaggedValue, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "math variance" - } - - fn signature(&self) -> Signature { - Signature::build("math variance").switch("sample", "calculate sample variance", Some('s')) - } - - fn usage(&self) -> &str { - "Finds the variance of a list of numbers or tables" - } - - fn run(&self, mut args: CommandArgs) -> Result { - let sample: bool = args.has_flag("sample"); - let values: Vec = args.input.drain_vec(); - let name = args.call_info.name_tag; - - let n = if sample { - values.len() - 1 - } else { - values.len() - }; - - let res = if values.iter().all(|v| v.is_primitive()) { - compute_variance(&values, n, &name) - } else { - // If we are not dealing with Primitives, then perhaps we are dealing with a table - // Create a key for each column name - let mut column_values = IndexMap::new(); - for value in values { - if let UntaggedValue::Row(row_dict) = &value.value { - for (key, value) in &row_dict.entries { - column_values - .entry(key.clone()) - .and_modify(|v: &mut Vec| v.push(value.clone())) - .or_insert(vec![value.clone()]); - } - } - } - // The mathematical function operates over the columns of the table - let mut column_totals = IndexMap::new(); - for (col_name, col_vals) in column_values { - if let Ok(out) = compute_variance(&col_vals, n, &name) { - column_totals.insert(col_name, out); - } - } - - if column_totals.keys().len() == 0 { - return Err(ShellError::labeled_error( - "Attempted to compute values that can't be operated on", - "value appears here", - name.span, - )); - } - - Ok(UntaggedValue::Row(Dictionary { - entries: column_totals, - }) - .into_untagged_value()) - }?; - - if res.value.is_table() { - Ok(OutputStream::from( - res.table_entries().cloned().collect::>(), - )) - } else { - Ok(OutputStream::one(res)) - } - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get the variance of a list of numbers", - example: "echo [1 2 3 4 5] | math variance", - result: Some(vec![UntaggedValue::decimal_from_float( - 2.0, - Span::unknown(), - ) - .into()]), - }, - Example { - description: "Get the sample variance of a list of numbers", - example: "echo [1 2 3 4 5] | math variance -s", - result: Some(vec![UntaggedValue::decimal_from_float( - 2.5, - Span::unknown(), - ) - .into()]), - }, - ] - } -} - -fn sum_of_squares(values: &[Value], name: &Tag) -> Result { - let n = BigDecimal::from_usize(values.len()).ok_or_else(|| { - ShellError::labeled_error( - "could not convert to big decimal", - "could not convert to big decimal", - &name.span, - ) - })?; - let mut sum_x = UntaggedValue::int(0).into_untagged_value(); - let mut sum_x2 = UntaggedValue::int(0).into_untagged_value(); - for value in values { - let v = match value { - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(num)), - .. - } => { - UntaggedValue::from(Primitive::Int(*num as i64)) - }, - Value { - value: UntaggedValue::Primitive(num), - .. - } => { - UntaggedValue::from(num.clone()) - }, - _ => { - return Err(ShellError::labeled_error( - "Attempted to compute the sum of squared values of a value that cannot be summed or squared.", - "value appears here", - value.tag.span, - )) - } - }; - let v_squared = compute_values(Operator::Multiply, &v, &v); - match v_squared { - // X^2 - Ok(x2) => { - sum_x2 = match compute_values(Operator::Plus, &sum_x2, &x2) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )) - } - }; - } - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned(value.tag.span), - right_type.spanned(value.tag.span), - )) - } - }; - sum_x = match compute_values(Operator::Plus, &sum_x, &v) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )) - } - }; - } - - let sum_x_squared = match compute_values(Operator::Multiply, &sum_x, &sum_x) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )) - } - }; - let sum_x_squared_div_n = match compute_values(Operator::Divide, &sum_x_squared, &n.into()) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )) - } - }; - let ss = match compute_values(Operator::Minus, &sum_x2, &sum_x_squared_div_n) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned(name.span), - right_type.spanned(name.span), - )) - } - }; - - Ok(ss) -} - -#[cfg(test)] -pub fn variance(values: &[Value], name: &Tag) -> Result { - compute_variance(values, values.len(), name) -} - -pub fn compute_variance(values: &[Value], n: usize, name: &Tag) -> Result { - let ss = sum_of_squares(values, name)?; - let n = BigDecimal::from_usize(n).ok_or_else(|| { - ShellError::labeled_error( - "could not convert to big decimal", - "could not convert to big decimal", - &name.span, - ) - })?; - let variance = compute_values(Operator::Divide, &ss, &n.into()); - match variance { - Ok(value) => Ok(value.into_value(name)), - Err((_, _)) => Err(ShellError::labeled_error( - "could not calculate variance of non-integer or unrelated types", - "source", - name, - )), - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/mod.rs b/old_nushell/crates/nu-command/src/commands/mod.rs deleted file mode 100644 index b6f6cae59..000000000 --- a/old_nushell/crates/nu-command/src/commands/mod.rs +++ /dev/null @@ -1,141 +0,0 @@ -mod charting; -mod config; -mod conversions; -mod core_commands; -#[cfg(feature = "dataframe")] -mod dataframe; -mod env; -mod filesystem; -mod filters; -mod formats; -mod generators; -mod math; -mod network; -mod path; -mod pathvar; -mod platform; -mod random; -mod shells; -mod strings; -mod system; -mod viewers; - -pub use charting::*; -pub use config::*; -pub use conversions::*; -pub use core_commands::*; -#[cfg(feature = "dataframe")] -pub use dataframe::{ - DataFrame, DataFrameAggregate, DataFrameAllFalse, DataFrameAllTrue, DataFrameAppend, - DataFrameArgMax, DataFrameArgMin, DataFrameArgSort, DataFrameArgTrue, DataFrameArgUnique, - DataFrameColumn, DataFrameConcatenate, DataFrameContains, DataFrameCumulative, DataFrameDTypes, - DataFrameDescribe, DataFrameDrop, DataFrameDropDuplicates, DataFrameDropNulls, - DataFrameDummies, DataFrameFilter, DataFrameFirst, DataFrameGet, DataFrameGetDay, - DataFrameGetHour, DataFrameGetMinute, DataFrameGetMonth, DataFrameGetNanoSecond, - DataFrameGetOrdinal, DataFrameGetSecond, DataFrameGetWeek, DataFrameGetWeekDay, - DataFrameGetYear, DataFrameGroupBy, DataFrameIsDuplicated, DataFrameIsIn, DataFrameIsNotNull, - DataFrameIsNull, DataFrameIsUnique, DataFrameJoin, DataFrameLast, DataFrameList, DataFrameMelt, - DataFrameNNull, DataFrameNUnique, DataFrameNot, DataFrameOpen, DataFramePivot, DataFrameRename, - DataFrameReplace, DataFrameReplaceAll, DataFrameRolling, DataFrameSample, DataFrameSelect, - DataFrameSeriesRename, DataFrameSet, DataFrameSetWithIdx, DataFrameShape, DataFrameShift, - DataFrameShow, DataFrameSlice, DataFrameSort, DataFrameStrFTime, DataFrameStringLengths, - DataFrameStringSlice, DataFrameTake, DataFrameToCsv, DataFrameToDF, DataFrameToLowercase, - DataFrameToParquet, DataFrameToUppercase, DataFrameUnique, DataFrameValueCounts, - DataFrameWhere, DataFrameWithColumn, -}; -pub use env::*; -pub use filesystem::*; -pub use filters::*; -pub use formats::*; -pub use generators::*; -pub use math::*; -pub use network::*; -pub use path::*; -pub use pathvar::*; -pub use platform::*; -pub use random::*; -pub use shells::*; -pub use strings::*; -pub use system::*; -pub use viewers::*; - -#[cfg(test)] -mod tests { - use super::*; - use crate::examples::{test_anchors, test_examples}; - use nu_engine::{whole_stream_command, Command}; - use nu_errors::ShellError; - - fn full_tests() -> Vec { - vec![ - whole_stream_command(ErrorMake), - whole_stream_command(Drop), - whole_stream_command(DropNth), - whole_stream_command(DropColumn), - whole_stream_command(Append), - whole_stream_command(GroupBy), - whole_stream_command(Insert), - whole_stream_command(MoveColumn), - whole_stream_command(Update), - whole_stream_command(Empty), - whole_stream_command(Nth), - // whole_stream_command(Select), - // whole_stream_command(Get), - // Str Command Suite - whole_stream_command(Str), - whole_stream_command(StrToDecimal), - whole_stream_command(StrToInteger), - whole_stream_command(StrDowncase), - whole_stream_command(StrUpcase), - whole_stream_command(StrCapitalize), - whole_stream_command(StrFindReplace), - whole_stream_command(StrSubstring), - whole_stream_command(StrToDatetime), - whole_stream_command(StrContains), - whole_stream_command(StrIndexOf), - whole_stream_command(StrTrim), - whole_stream_command(StrStartsWith), - whole_stream_command(StrEndsWith), - //whole_stream_command(StrCollect), - whole_stream_command(StrLength), - whole_stream_command(StrLPad), - whole_stream_command(StrReverse), - whole_stream_command(StrRPad), - whole_stream_command(StrCamelCase), - whole_stream_command(StrPascalCase), - whole_stream_command(StrKebabCase), - whole_stream_command(StrSnakeCase), - whole_stream_command(StrScreamingSnakeCase), - whole_stream_command(ToMarkdown), - ] - } - - fn only_examples() -> Vec { - let mut commands = full_tests(); - commands.extend([ - whole_stream_command(UpdateCells), - whole_stream_command(Zip), - whole_stream_command(Flatten), - ]); - commands - } - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - for cmd in only_examples() { - println!("cmd: {}", cmd.name()); - test_examples(cmd)?; - } - - Ok(()) - } - - #[test] - fn tracks_metadata() -> Result<(), ShellError> { - for cmd in full_tests() { - test_anchors(cmd)?; - } - - Ok(()) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/network/fetch.rs b/old_nushell/crates/nu-command/src/commands/network/fetch.rs deleted file mode 100644 index 82b5df989..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/fetch.rs +++ /dev/null @@ -1,377 +0,0 @@ -use crate::prelude::*; -use base64::encode; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{CommandAction, ReturnSuccess, ReturnValue, Value}; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::{AnchorLocation, Span, Tag}; -use std::path::PathBuf; -use std::str::FromStr; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "fetch" - } - - fn signature(&self) -> Signature { - Signature::build("fetch") - .desc("Load from a URL into a cell, convert to table if possible (avoid by appending '--raw').") - .required( - "URL", - SyntaxShape::String, - "the URL to fetch the contents from", - ) - .named( - "user", - SyntaxShape::Any, - "the username when authenticating", - Some('u'), - ) - .named( - "password", - SyntaxShape::Any, - "the password when authenticating", - Some('p'), - ) - .switch("raw", "fetch contents as text rather than a table", Some('r')) - .switch("insecure", "allow insecure server connections when using SSL", Some('k')) - .filter() - } - - fn usage(&self) -> &str { - "Fetch the contents from a URL (HTTP GET operation)." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - run_fetch(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Fetch content from url.com", - example: "fetch url.com", - result: None, - }, - Example { - description: "Fetch content from url.com, with username and password", - example: "fetch -u myuser -p mypass url.com", - result: None, - }, - ] - } -} - -fn run_fetch(args: CommandArgs) -> Result { - let mut fetch_helper = Fetch::new(); - - fetch_helper.setup(args)?; - - let runtime = tokio::runtime::Runtime::new()?; - Ok(vec![runtime.block_on(fetch( - &fetch_helper.path.clone().ok_or_else(|| { - ShellError::labeled_error( - "internal error: path not set", - "path not set", - &fetch_helper.tag, - ) - })?, - fetch_helper.has_raw, - fetch_helper.has_insecure, - fetch_helper.user.clone(), - fetch_helper.password, - ))] - .into_iter() - .into_action_stream()) - - //fetch.setup(callinfo)?; -} - -#[derive(Default)] -pub struct Fetch { - pub path: Option, - pub tag: Tag, - pub has_raw: bool, - pub has_insecure: bool, - pub user: Option, - pub password: Option, -} - -impl Fetch { - pub fn new() -> Fetch { - Fetch { - path: None, - tag: Tag::unknown(), - has_raw: false, - has_insecure: false, - user: None, - password: None, - } - } - - pub fn setup(&mut self, args: CommandArgs) -> Result<(), ShellError> { - self.path = Some({ - args.req(0).map_err(|_| { - ShellError::labeled_error( - "No file or directory specified", - "for command", - &args.name_tag(), - ) - })? - }); - self.tag = args.name_tag(); - - self.has_raw = args.has_flag("raw"); - - self.has_insecure = args.has_flag("insecure"); - - self.user = args.get_flag("user")?; - - self.password = args.get_flag("password")?; - - Ok(()) - } -} - -pub async fn fetch( - path: &Value, - has_raw: bool, - has_insecure: bool, - user: Option, - password: Option, -) -> ReturnValue { - let path_str = path.as_string()?; - let path_span = path.tag.span; - - let result = helper(&path_str, path_span, has_raw, has_insecure, user, password).await; - - if let Err(e) = result { - return Err(e); - } - let (file_extension, value) = result?; - - let file_extension = if has_raw { - None - } else { - // If the extension could not be determined via mimetype, try to use the path - // extension. Some file types do not declare their mimetypes (such as bson files). - file_extension.or_else(|| path_str.split('.').last().map(String::from)) - }; - - if let Some(extension) = file_extension { - Ok(ReturnSuccess::Action(CommandAction::AutoConvert( - value, extension, - ))) - } else { - ReturnSuccess::value(value) - } -} - -// Helper function that actually goes to retrieve the resource from the url given -// The Option return a possible file extension which can be used in AutoConvert commands -async fn helper( - location: &str, - span: Span, - has_raw: bool, - has_insecure: bool, - user: Option, - password: Option, -) -> std::result::Result<(Option, Value), ShellError> { - let url = match url::Url::parse(location) { - Ok(u) => u, - Err(e) => { - return Err(ShellError::labeled_error( - format!("Incomplete or incorrect url:\n{:?}", e), - "expected a full url", - span, - )); - } - }; - - let login = match (user, password) { - (Some(user), Some(password)) => Some(encode(&format!("{}:{}", user, password))), - (Some(user), _) => Some(encode(&format!("{}:", user))), - _ => None, - }; - - let client = http_client(has_insecure); - let mut request = client.get(url); - - if let Some(login) = login { - request = request.header("Authorization", format!("Basic {}", login)); - } - - let generate_error = |t: &str, e: reqwest::Error, span: &Span| { - ShellError::labeled_error( - format!("Could not load {} from remote url: {:?}", t, e), - "could not load", - span, - ) - }; - let tag = Tag { - span, - anchor: Some(AnchorLocation::Url(location.to_string())), - }; - - match request.send().await { - Ok(r) => match r.headers().get("content-type") { - Some(content_type) => { - let content_type = content_type.to_str().map_err(|e| { - ShellError::labeled_error(e.to_string(), "MIME type were invalid", &tag) - })?; - let content_type = mime::Mime::from_str(content_type).map_err(|_| { - ShellError::labeled_error( - format!("MIME type unknown: {}", content_type), - "given unknown MIME type", - span, - ) - })?; - match (content_type.type_(), content_type.subtype()) { - (mime::APPLICATION, mime::XML) => Ok(( - Some("xml".to_string()), - UntaggedValue::string( - r.text() - .await - .map_err(|e| generate_error("text", e, &span))?, - ) - .into_value(tag), - )), - (mime::APPLICATION, mime::JSON) => Ok(( - Some("json".to_string()), - UntaggedValue::string( - r.text() - .await - .map_err(|e| generate_error("text", e, &span))?, - ) - .into_value(tag), - )), - (mime::APPLICATION, mime::OCTET_STREAM) => { - let buf: Vec = r - .bytes() - .await - .map_err(|e| generate_error("binary", e, &span))? - .to_vec(); - Ok((None, UntaggedValue::binary(buf).into_value(tag))) - } - (mime::IMAGE, mime::SVG) => Ok(( - Some("svg".to_string()), - UntaggedValue::string( - r.text() - .await - .map_err(|e| generate_error("svg", e, &span))?, - ) - .into_value(tag), - )), - (mime::IMAGE, image_ty) => { - let buf: Vec = r - .bytes() - .await - .map_err(|e| generate_error("image", e, &span))? - .to_vec(); - Ok(( - Some(image_ty.to_string()), - UntaggedValue::binary(buf).into_value(tag), - )) - } - (mime::TEXT, mime::HTML) => Ok(( - Some("html".to_string()), - UntaggedValue::string( - r.text() - .await - .map_err(|e| generate_error("text", e, &span))?, - ) - .into_value(tag), - )), - (mime::TEXT, mime::CSV) => Ok(( - Some("csv".to_string()), - UntaggedValue::string( - r.text() - .await - .map_err(|e| generate_error("text", e, &span))?, - ) - .into_value(tag), - )), - (mime::TEXT, mime::PLAIN) => { - let path_extension = url::Url::parse(location) - .map_err(|_| { - ShellError::labeled_error( - format!("Cannot parse URL: {}", location), - "cannot parse", - span, - ) - })? - .path_segments() - .and_then(|segments| segments.last()) - .and_then(|name| if name.is_empty() { None } else { Some(name) }) - .and_then(|name| { - PathBuf::from(name) - .extension() - .map(|name| name.to_string_lossy().to_string()) - }); - - Ok(( - path_extension, - UntaggedValue::string( - r.text() - .await - .map_err(|e| generate_error("text", e, &span))?, - ) - .into_value(tag), - )) - } - (_ty, _sub_ty) if has_raw => { - let raw_bytes = r.bytes().await; - let raw_bytes = match raw_bytes { - Ok(r) => r, - Err(e) => { - return Err(ShellError::labeled_error( - "error with raw_bytes", - e.to_string(), - &span, - )); - } - }; - - // For unsupported MIME types, we do not know if the data is UTF-8, - // so we get the raw body bytes and try to convert to UTF-8 if possible. - match std::str::from_utf8(&raw_bytes) { - Ok(response_str) => { - Ok((None, UntaggedValue::string(response_str).into_value(tag))) - } - Err(_) => Ok(( - None, - UntaggedValue::binary(raw_bytes.to_vec()).into_value(tag), - )), - } - } - (ty, sub_ty) => Err(ShellError::unimplemented(format!( - "Not yet supported MIME type: {} {}", - ty, sub_ty - ))), - } - } - // TODO: Should this return "nothing" or Err? - None => Ok(( - None, - UntaggedValue::string("No content type found".to_owned()).into_value(tag), - )), - }, - Err(e) => Err(ShellError::labeled_error( - "url could not be opened", - e.to_string(), - span, - )), - } -} - -// Only panics if the user agent is invalid but we define it statically so either -// it always or never fails -fn http_client(allow_insecure: bool) -> reqwest::Client { - reqwest::Client::builder() - .user_agent("nushell") - .danger_accept_invalid_certs(allow_insecure) - .build() - .expect("Failed to build reqwest client") -} diff --git a/old_nushell/crates/nu-command/src/commands/network/mod.rs b/old_nushell/crates/nu-command/src/commands/network/mod.rs deleted file mode 100644 index d6e32be4b..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -#[cfg(feature = "fetch")] -mod fetch; -#[cfg(feature = "fetch")] -pub use fetch::Command as Fetch; - -#[cfg(feature = "post")] -mod post; -#[cfg(feature = "post")] -pub use post::Command as Post; - -mod url_; -pub use url_::*; diff --git a/old_nushell/crates/nu-command/src/commands/network/post.rs b/old_nushell/crates/nu-command/src/commands/network/post.rs deleted file mode 100644 index be472d4ba..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/post.rs +++ /dev/null @@ -1,646 +0,0 @@ -use crate::prelude::*; -use base64::encode; -use mime::Mime; -use nu_engine::WholeStreamCommand; -use nu_errors::{CoerceInto, ShellError}; -use nu_protocol::{ - CommandAction, Primitive, ReturnSuccess, ReturnValue, UnspannedPathMember, UntaggedValue, Value, -}; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::{AnchorLocation, Tag, TaggedItem}; -use num_traits::cast::ToPrimitive; -use std::path::PathBuf; -use std::str::FromStr; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "post" - } - - fn signature(&self) -> Signature { - Signature::build("post") - .desc("Post content to a URL and retrieve data as a table if possible.") - .required("path", SyntaxShape::Any, "the URL to post to") - .required("body", SyntaxShape::Any, "the contents of the post body") - .named( - "user", - SyntaxShape::Any, - "the username when authenticating", - Some('u'), - ) - .named( - "password", - SyntaxShape::Any, - "the password when authenticating", - Some('p'), - ) - .named( - "content-type", - SyntaxShape::Any, - "the MIME type of content to post", - Some('t'), - ) - .named( - "content-length", - SyntaxShape::Any, - "the length of the content being posted", - Some('l'), - ) - .switch( - "raw", - "return values as a string instead of a table", - Some('r'), - ) - .switch( - "insecure", - "allow insecure server connections when using SSL", - Some('k'), - ) - .filter() - } - - fn usage(&self) -> &str { - "Post a body to a URL (HTTP POST operation)." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - run_post(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Post content to url.com", - example: "post url.com 'body'", - result: None, - }, - Example { - description: "Post content to url.com, with username and password", - example: "post -u myuser -p mypass url.com 'body'", - result: None, - }, - ] - } -} - -fn run_post(args: CommandArgs) -> Result { - let mut helper = Post::new(); - - helper.setup(args)?; - - let runtime = tokio::runtime::Runtime::new()?; - Ok(vec![runtime.block_on(post_helper( - &helper.path.clone().ok_or_else(|| { - ShellError::labeled_error("expected a 'path'", "expected a 'path'", &helper.tag) - })?, - helper.has_raw, - helper.has_insecure, - &helper.body.clone().ok_or_else(|| { - ShellError::labeled_error("expected a 'body'", "expected a 'body'", &helper.tag) - })?, - helper.user.clone(), - helper.password.clone(), - &helper.headers, - ))] - .into_iter() - .into_action_stream()) - - //fetch.setup(callinfo)?; -} - -#[derive(Clone)] -pub enum HeaderKind { - ContentType(String), - ContentLength(String), -} - -#[derive(Default)] -pub struct Post { - pub path: Option, - pub has_raw: bool, - pub has_insecure: bool, - pub body: Option, - pub user: Option, - pub password: Option, - pub headers: Vec, - pub tag: Tag, -} - -impl Post { - pub fn new() -> Post { - Post { - path: None, - has_raw: false, - has_insecure: false, - body: None, - user: None, - password: None, - headers: vec![], - tag: Tag::default(), - } - } - - pub fn setup(&mut self, args: CommandArgs) -> Result<(), ShellError> { - self.path = Some({ - args.req(0).map_err(|_| { - ShellError::labeled_error( - "No file or directory specified", - "for command", - &args.name_tag(), - ) - })? - }); - - self.body = { - let file = args.req(1).map_err(|_| { - ShellError::labeled_error("No body specified", "for command", &args.name_tag()) - })?; - Some(file) - }; - - self.tag = args.name_tag(); - - self.has_raw = args.has_flag("raw"); - - self.has_insecure = args.has_flag("insecure"); - - self.user = args.get_flag("user")?; - - self.password = args.get_flag("password")?; - - self.headers = get_headers(&args)?; - - Ok(()) - } -} - -pub async fn post_helper( - path: &Value, - has_raw: bool, - has_insecure: bool, - body: &Value, - user: Option, - password: Option, - headers: &[HeaderKind], -) -> ReturnValue { - let path_tag = path.tag.clone(); - let path_str = path.as_string()?; - - let (file_extension, contents, contents_tag) = post( - &path_str, - has_insecure, - body, - user, - password, - headers, - path_tag.clone(), - ) - .await?; - - let file_extension = if has_raw { - None - } else { - // If the extension could not be determined via mimetype, try to use the path - // extension. Some file types do not declare their mimetypes (such as bson files). - file_extension.or_else(|| path_str.split('.').last().map(String::from)) - }; - - let tagged_contents = contents.into_value(&contents_tag); - - if let Some(extension) = file_extension { - Ok(ReturnSuccess::Action(CommandAction::AutoConvert( - tagged_contents, - extension, - ))) - } else { - ReturnSuccess::value(tagged_contents) - } -} - -pub async fn post( - location: &str, - allow_insecure: bool, - body: &Value, - user: Option, - password: Option, - headers: &[HeaderKind], - tag: Tag, -) -> Result<(Option, UntaggedValue, Tag), ShellError> { - if location.starts_with("http:") || location.starts_with("https:") { - let login = match (user, password) { - (Some(user), Some(password)) => Some(encode(&format!("{}:{}", user, password))), - (Some(user), _) => Some(encode(&format!("{}:", user))), - _ => None, - }; - let response = match body { - Value { - value: UntaggedValue::Primitive(Primitive::String(body_str)), - .. - } => { - let mut s = http_client(allow_insecure) - .post(location) - .body(body_str.to_string()); - if let Some(login) = login { - s = s.header("Authorization", format!("Basic {}", login)); - } - - for h in headers { - s = match h { - HeaderKind::ContentType(ct) => s.header("Content-Type", ct), - HeaderKind::ContentLength(cl) => s.header("Content-Length", cl), - }; - } - - s.send().await - } - Value { - value: UntaggedValue::Primitive(Primitive::Binary(b)), - .. - } => { - let mut s = http_client(allow_insecure) - .post(location) - .body(Vec::from(&b[..])); - if let Some(login) = login { - s = s.header("Authorization", format!("Basic {}", login)); - } - s.send().await - } - Value { value, tag } => { - match value_to_json_value(&value.clone().into_untagged_value()) { - Ok(json_value) => match serde_json::to_string(&json_value) { - Ok(result_string) => { - let mut s = http_client(allow_insecure) - .post(location) - .body(result_string); - - if let Some(login) = login { - s = s.header("Authorization", format!("Basic {}", login)); - } - s.send().await - } - _ => { - return Err(ShellError::labeled_error( - "Could not automatically convert table", - "needs manual conversion", - tag, - )); - } - }, - _ => { - return Err(ShellError::labeled_error( - "Could not automatically convert table", - "needs manual conversion", - tag, - )); - } - } - } - }; - match response { - Ok(r) => match r.headers().get("content-type") { - Some(content_type) => { - let content_type = content_type.to_str().map_err(|e| { - ShellError::labeled_error(e.to_string(), "MIME type were invalid", &tag) - })?; - let content_type = Mime::from_str(content_type).map_err(|_| { - ShellError::labeled_error( - format!("Unknown MIME type: {}", content_type), - "unknown MIME type", - &tag, - ) - })?; - match (content_type.type_(), content_type.subtype()) { - (mime::APPLICATION, mime::XML) => Ok(( - Some("xml".to_string()), - UntaggedValue::string(r.text().await.map_err(|_| { - ShellError::labeled_error( - "Could not load text from remote url", - "could not load", - &tag, - ) - })?), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )), - (mime::APPLICATION, mime::JSON) => Ok(( - Some("json".to_string()), - UntaggedValue::string(r.text().await.map_err(|_| { - ShellError::labeled_error( - "Could not load text from remote url", - "could not load", - &tag, - ) - })?), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )), - (mime::APPLICATION, mime::OCTET_STREAM) => { - let buf: Vec = r - .bytes() - .await - .map_err(|_| { - ShellError::labeled_error( - "Could not load binary file", - "could not load", - &tag, - ) - })? - .to_vec(); - Ok(( - None, - UntaggedValue::binary(buf), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )) - } - (mime::IMAGE, image_ty) => { - let buf: Vec = r - .bytes() - .await - .map_err(|_| { - ShellError::labeled_error( - "Could not load image file", - "could not load", - &tag, - ) - })? - .to_vec(); - Ok(( - Some(image_ty.to_string()), - UntaggedValue::binary(buf), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )) - } - (mime::TEXT, mime::HTML) => Ok(( - Some("html".to_string()), - UntaggedValue::string(r.text().await.map_err(|_| { - ShellError::labeled_error( - "Could not load text from remote url", - "could not load", - &tag, - ) - })?), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )), - (mime::TEXT, mime::PLAIN) => { - let path_extension = url::Url::parse(location) - .map_err(|_| { - ShellError::labeled_error( - format!("could not parse URL: {}", location), - "could not parse URL", - &tag, - ) - })? - .path_segments() - .and_then(|segments| segments.last()) - .and_then(|name| if name.is_empty() { None } else { Some(name) }) - .and_then(|name| { - PathBuf::from(name) - .extension() - .map(|name| name.to_string_lossy().to_string()) - }); - - Ok(( - path_extension, - UntaggedValue::string(r.text().await.map_err(|_| { - ShellError::labeled_error( - "Could not load text from remote url", - "could not load", - &tag, - ) - })?), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )) - } - (ty, sub_ty) => Ok(( - None, - UntaggedValue::string(format!( - "Not yet supported MIME type: {} {}", - ty, sub_ty - )), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )), - } - } - None => Ok(( - None, - UntaggedValue::string("No content type found".to_owned()), - Tag { - anchor: Some(AnchorLocation::Url(location.to_string())), - span: tag.span, - }, - )), - }, - Err(_) => Err(ShellError::labeled_error( - "URL could not be opened", - "url not found", - tag, - )), - } - } else { - Err(ShellError::labeled_error( - "Expected a url", - "needs a url", - tag, - )) - } -} - -// FIXME FIXME FIXME -// Ultimately, we don't want to duplicate to-json here, but we need to because there isn't an easy way to call into it, yet -pub fn value_to_json_value(v: &Value) -> Result { - Ok(match &v.value { - UntaggedValue::Primitive(Primitive::Boolean(b)) => serde_json::Value::Bool(*b), - UntaggedValue::Primitive(Primitive::Filesize(b)) => serde_json::Value::Number( - serde_json::Number::from(b.to_u64().expect("What about really big numbers")), - ), - UntaggedValue::Primitive(Primitive::Duration(i)) => serde_json::Value::Number( - serde_json::Number::from_f64( - i.to_f64().expect("TODO: What about really big decimals?"), - ) - .ok_or_else(|| { - ShellError::labeled_error( - "Can not convert big decimal to f64", - "cannot convert big decimal to f64", - &v.tag, - ) - })?, - ), - UntaggedValue::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()), - UntaggedValue::Primitive(Primitive::EndOfStream) => serde_json::Value::Null, - UntaggedValue::Primitive(Primitive::BeginningOfStream) => serde_json::Value::Null, - UntaggedValue::Primitive(Primitive::Decimal(f)) => serde_json::Value::Number( - serde_json::Number::from_f64( - f.to_f64().expect("TODO: What about really big decimals?"), - ) - .ok_or_else(|| { - ShellError::labeled_error( - "Can not convert big decimal to f64", - "cannot convert big decimal to f64", - &v.tag, - ) - })?, - ), - UntaggedValue::Primitive(Primitive::Int(i)) => { - serde_json::Value::Number(serde_json::Number::from(*i)) - } - UntaggedValue::Primitive(Primitive::BigInt(i)) => { - serde_json::Value::Number(serde_json::Number::from(CoerceInto::::coerce_into( - i.tagged(&v.tag), - "converting to JSON number", - )?)) - } - UntaggedValue::Primitive(Primitive::Nothing) => serde_json::Value::Null, - UntaggedValue::Primitive(Primitive::GlobPattern(s)) => serde_json::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::ColumnPath(path)) => serde_json::Value::Array( - path.iter() - .map(|x| match &x.unspanned { - UnspannedPathMember::String(string) => { - Ok(serde_json::Value::String(string.clone())) - } - UnspannedPathMember::Int(int) => { - Ok(serde_json::Value::Number(serde_json::Number::from(*int))) - } - }) - .collect::, ShellError>>()?, - ), - UntaggedValue::Primitive(Primitive::FilePath(s)) => { - serde_json::Value::String(s.display().to_string()) - } - - UntaggedValue::Table(l) => serde_json::Value::Array(json_list(l)?), - #[cfg(feature = "dataframe")] - UntaggedValue::DataFrame(_) | UntaggedValue::FrameStruct(_) => { - return Err(ShellError::labeled_error( - "Cannot convert data struct", - "Cannot convert data struct", - &v.tag, - )) - } - UntaggedValue::Error(e) => return Err(e.clone()), - UntaggedValue::Block(_) | UntaggedValue::Primitive(Primitive::Range(_)) => { - serde_json::Value::Null - } - UntaggedValue::Primitive(Primitive::Binary(b)) => { - let mut output = vec![]; - - for item in b { - output.push(serde_json::Value::Number( - serde_json::Number::from_f64(*item as f64).ok_or_else(|| { - ShellError::labeled_error( - "Cannot create number from from f64", - "cannot created number from f64", - &v.tag, - ) - })?, - )); - } - serde_json::Value::Array(output) - } - UntaggedValue::Row(o) => { - let mut m = serde_json::Map::new(); - for (k, v) in &o.entries { - m.insert(k.clone(), value_to_json_value(v)?); - } - serde_json::Value::Object(m) - } - }) -} - -fn json_list(input: &[Value]) -> Result, ShellError> { - let mut out = vec![]; - - for value in input { - out.push(value_to_json_value(value)?); - } - - Ok(out) -} - -fn get_headers(args: &CommandArgs) -> Result, ShellError> { - let mut headers = vec![]; - - match extract_header_value(args, "content-type") { - Ok(h) => { - if let Some(ct) = h { - headers.push(HeaderKind::ContentType(ct)) - } - } - Err(e) => { - return Err(e); - } - }; - - match extract_header_value(args, "content-length") { - Ok(h) => { - if let Some(cl) = h { - headers.push(HeaderKind::ContentLength(cl)) - } - } - Err(e) => { - return Err(e); - } - }; - - Ok(headers) -} - -fn extract_header_value(args: &CommandArgs, key: &str) -> Result, ShellError> { - if args.has_flag(key) { - let tagged = args.get_flag(key)?; - let val = match tagged { - Some(Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - .. - }) => s, - Some(Value { tag, .. }) => { - return Err(ShellError::labeled_error( - format!("{} not in expected format. Expected string.", key), - "post error", - tag, - )); - } - _ => { - return Err(ShellError::labeled_error( - format!("{} not in expected format. Expected string.", key), - "post error", - Tag::unknown(), - )); - } - }; - return Ok(Some(val)); - } - - Ok(None) -} - -// Only panics if the user agent is invalid but we define it statically so either -// it always or never fails -fn http_client(allow_insecure: bool) -> reqwest::Client { - reqwest::Client::builder() - .user_agent("nushell") - .danger_accept_invalid_certs(allow_insecure) - .build() - .expect("Failed to build reqwest client") -} diff --git a/old_nushell/crates/nu-command/src/commands/network/url_/command.rs b/old_nushell/crates/nu-command/src/commands/network/url_/command.rs deleted file mode 100644 index e541912cf..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/url_/command.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Url; - -impl WholeStreamCommand for Url { - fn name(&self) -> &str { - "url" - } - - fn signature(&self) -> Signature { - Signature::build("url") - } - - fn usage(&self) -> &str { - "Apply url function." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&Url, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Url; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Url {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/network/url_/host.rs b/old_nushell/crates/nu-command/src/commands/network/url_/host.rs deleted file mode 100644 index 0571f20ae..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/url_/host.rs +++ /dev/null @@ -1,59 +0,0 @@ -use url::Url; - -use super::operate; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value}; - -pub struct UrlHost; - -impl WholeStreamCommand for UrlHost { - fn name(&self) -> &str { - "url host" - } - - fn signature(&self) -> Signature { - Signature::build("url host").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally operate by column path", - ) - } - - fn usage(&self) -> &str { - "gets the host of a url" - } - - fn run(&self, args: CommandArgs) -> Result { - let rest: Vec = args.rest(0)?; - let input = args.input; - - Ok(operate(input, rest, &host)) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Get host of a url", - example: "echo 'http://www.example.com/foo/bar' | url host", - result: Some(vec![Value::from("www.example.com")]), - }] - } -} - -fn host(url: &Url) -> &str { - url.host_str().unwrap_or("") -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::UrlHost; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(UrlHost {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/network/url_/mod.rs b/old_nushell/crates/nu-command/src/commands/network/url_/mod.rs deleted file mode 100644 index 082552dd1..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/url_/mod.rs +++ /dev/null @@ -1,62 +0,0 @@ -mod command; -mod host; -mod path; -mod query; -mod scheme; - -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive, ShellTypeName, UntaggedValue, Value}; -use url::Url; - -pub use command::Url as UrlCommand; -pub use host::UrlHost; -pub use path::UrlPath; -pub use query::UrlQuery; -pub use scheme::UrlScheme; - -fn handle_value(action: &F, v: &Value) -> Result -where - F: Fn(&Url) -> &str + Send + 'static, -{ - let a = |url| UntaggedValue::string(action(url)); - let v = match &v.value { - UntaggedValue::Primitive(Primitive::String(s)) => match Url::parse(s) { - Ok(url) => a(&url).into_value(v.tag()), - Err(_) => UntaggedValue::string("").into_value(v.tag()), - }, - other => { - let got = format!("got {}", other.type_name()); - return Err(ShellError::labeled_error( - "value is not a string", - got, - v.tag().span, - )); - } - }; - Ok(v) -} - -fn operate(input: crate::InputStream, paths: Vec, action: &'static F) -> OutputStream -where - F: Fn(&Url) -> &str + Send + Sync + 'static, -{ - input - .map(move |v| { - if paths.is_empty() { - handle_value(&action, &v) - } else { - let mut ret = v; - - for path in &paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| handle_value(&action, old)), - )?; - } - - Ok(ret) - } - }) - .into_input_stream() -} diff --git a/old_nushell/crates/nu-command/src/commands/network/url_/path.rs b/old_nushell/crates/nu-command/src/commands/network/url_/path.rs deleted file mode 100644 index 75525ad53..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/url_/path.rs +++ /dev/null @@ -1,62 +0,0 @@ -use url::Url; - -use super::operate; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value}; - -pub struct UrlPath; - -impl WholeStreamCommand for UrlPath { - fn name(&self) -> &str { - "url path" - } - - fn signature(&self) -> Signature { - Signature::build("url path").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally operate by column path", - ) - } - - fn usage(&self) -> &str { - "gets the path of a url" - } - - fn run(&self, args: CommandArgs) -> Result { - let rest: Vec = args.rest(0)?; - let input = args.input; - - Ok(operate(input, rest, &Url::path)) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get path of a url", - example: "echo 'http://www.example.com/foo/bar' | url path", - result: Some(vec![Value::from("/foo/bar")]), - }, - Example { - description: "A trailing slash will be reflected in the path", - example: "echo 'http://www.example.com' | url path", - result: Some(vec![Value::from("/")]), - }, - ] - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::UrlPath; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(UrlPath {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/network/url_/query.rs b/old_nushell/crates/nu-command/src/commands/network/url_/query.rs deleted file mode 100644 index ce6a5cf47..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/url_/query.rs +++ /dev/null @@ -1,65 +0,0 @@ -use url::Url; - -use super::operate; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value}; - -pub struct UrlQuery; - -impl WholeStreamCommand for UrlQuery { - fn name(&self) -> &str { - "url query" - } - - fn signature(&self) -> Signature { - Signature::build("url query").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally operate by column path", - ) - } - - fn usage(&self) -> &str { - "gets the query of a url" - } - - fn run(&self, args: CommandArgs) -> Result { - let rest: Vec = args.rest(0)?; - let input = args.input; - Ok(operate(input, rest, &query)) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get query of a url", - example: "echo 'http://www.example.com/?foo=bar&baz=quux' | url query", - result: Some(vec![Value::from("foo=bar&baz=quux")]), - }, - Example { - description: "No query gives the empty string", - example: "echo 'http://www.example.com/' | url query", - result: Some(vec![Value::from("")]), - }, - ] - } -} - -fn query(url: &Url) -> &str { - url.query().unwrap_or("") -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::UrlQuery; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(UrlQuery {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/network/url_/scheme.rs b/old_nushell/crates/nu-command/src/commands/network/url_/scheme.rs deleted file mode 100644 index 643883bc5..000000000 --- a/old_nushell/crates/nu-command/src/commands/network/url_/scheme.rs +++ /dev/null @@ -1,60 +0,0 @@ -use url::Url; - -use super::operate; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, Value}; - -pub struct UrlScheme; - -impl WholeStreamCommand for UrlScheme { - fn name(&self) -> &str { - "url scheme" - } - - fn signature(&self) -> Signature { - Signature::build("url scheme").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally operate by path", - ) - } - - fn usage(&self) -> &str { - "gets the scheme (eg http, file) of a url" - } - - fn run(&self, args: CommandArgs) -> Result { - let rest: Vec = args.rest(0)?; - Ok(operate(args.input, rest, &Url::scheme)) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get scheme of a url", - example: "echo 'http://www.example.com' | url scheme", - result: Some(vec![Value::from("http")]), - }, - Example { - description: "You get an empty string if there is no scheme", - example: "echo 'test' | url scheme", - result: Some(vec![Value::from("")]), - }, - ] - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::UrlScheme; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(UrlScheme {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/basename.rs b/old_nushell/crates/nu-command/src/commands/path/basename.rs deleted file mode 100644 index 21a1901b8..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/basename.rs +++ /dev/null @@ -1,127 +0,0 @@ -use super::{column_paths_from_args, operate, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use std::path::Path; - -pub struct PathBasename; - -struct PathBasenameArguments { - columns: Vec, - replace: Option>, -} - -impl PathSubcommandArguments for PathBasenameArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathBasename { - fn name(&self) -> &str { - "path basename" - } - - fn signature(&self) -> Signature { - Signature::build("path basename") - .named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - .named( - "replace", - SyntaxShape::String, - "Return original path with basename replaced by this string", - Some('r'), - ) - } - - fn usage(&self) -> &str { - "Get the final component of a path" - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathBasenameArguments { - columns: column_paths_from_args(&args)?, - replace: args.get_flag("replace")?, - }); - - Ok(operate(args.input, &action, tag.span, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get basename of a path", - example: "'C:\\Users\\joe\\test.txt' | path basename", - result: Some(vec![Value::from("test.txt")]), - }, - Example { - description: "Get basename of a path in a column", - example: "ls .. | path basename -c [ name ]", - result: None, - }, - Example { - description: "Replace basename of a path", - example: "'C:\\Users\\joe\\test.txt' | path basename -r 'spam.png'", - result: Some(vec![Value::from(UntaggedValue::filepath( - "C:\\Users\\joe\\spam.png", - ))]), - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get basename of a path", - example: "'/home/joe/test.txt' | path basename", - result: Some(vec![Value::from("test.txt")]), - }, - Example { - description: "Get basename of a path in a column", - example: "ls .. | path basename -c [ name ]", - result: None, - }, - Example { - description: "Replace basename of a path", - example: "'/home/joe/test.txt' | path basename -r 'spam.png'", - result: Some(vec![Value::from(UntaggedValue::filepath( - "/home/joe/spam.png", - ))]), - }, - ] - } -} - -fn action(path: &Path, tag: Tag, args: &PathBasenameArguments) -> Value { - let untagged = match args.replace { - Some(ref basename) => UntaggedValue::filepath(path.with_file_name(&basename.item)), - None => UntaggedValue::string(match path.file_name() { - Some(filename) => filename.to_string_lossy(), - None => "".into(), - }), - }; - - untagged.into_value(tag) -} - -#[cfg(test)] -mod tests { - use super::PathBasename; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathBasename {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/command.rs b/old_nushell/crates/nu-command/src/commands/path/command.rs deleted file mode 100644 index 22a0d30eb..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/command.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Path; - -impl WholeStreamCommand for Path { - fn name(&self) -> &str { - "path" - } - - fn signature(&self) -> Signature { - Signature::build("path") - } - - fn usage(&self) -> &str { - "Explore and manipulate paths." - } - - fn extra_usage(&self) -> &str { - r#"There are three ways to represent a path: - -* As a path literal, e.g., '/home/viking/spam.txt' -* As a structured path: a table with 'parent', 'stem', and 'extension' (and -* 'prefix' on Windows) columns. This format is produced by the 'path parse' - subcommand. -* As an inner list of path parts, e.g., '[[ / home viking spam.txt ]]'. - Splitting into parts is done by the `path split` command. - -All subcommands accept all three variants as an input. Furthermore, the 'path -join' subcommand can be used to join the structured path or path parts back into -the path literal."# - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one( - UntaggedValue::string(get_full_help(&Path, args.scope())).into_value(Tag::unknown()), - )) - } -} - -#[cfg(test)] -mod tests { - use super::Path; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Path {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/dirname.rs b/old_nushell/crates/nu-command/src/commands/path/dirname.rs deleted file mode 100644 index 7e000629d..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/dirname.rs +++ /dev/null @@ -1,166 +0,0 @@ -use super::{column_paths_from_args, operate, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use std::path::Path; - -pub struct PathDirname; - -struct PathDirnameArguments { - columns: Vec, - replace: Option>, - num_levels: Option>, -} - -impl PathSubcommandArguments for PathDirnameArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathDirname { - fn name(&self) -> &str { - "path dirname" - } - - fn signature(&self) -> Signature { - Signature::build("path dirname") - .named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - .named( - "replace", - SyntaxShape::String, - "Return original path with dirname replaced by this string", - Some('r'), - ) - .named( - "num-levels", - SyntaxShape::Int, - "Number of directories to walk up", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "Get the parent directory of a path" - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathDirnameArguments { - columns: column_paths_from_args(&args)?, - replace: args.get_flag("replace")?, - num_levels: args.get_flag("num-levels")?, - }); - - Ok(operate(args.input, &action, tag.span, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get dirname of a path", - example: "'C:\\Users\\joe\\code\\test.txt' | path dirname", - result: Some(vec![Value::from(UntaggedValue::filepath( - "C:\\Users\\joe\\code", - ))]), - }, - Example { - description: "Get dirname of a path in a column", - example: "ls ('.' | path expand) | path dirname -c [ name ]", - result: None, - }, - Example { - description: "Walk up two levels", - example: "'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2", - result: Some(vec![Value::from(UntaggedValue::filepath("C:\\Users\\joe"))]), - }, - Example { - description: "Replace the part that would be returned with a custom path", - example: - "'C:\\Users\\joe\\code\\test.txt' | path dirname -n 2 -r C:\\Users\\viking", - result: Some(vec![Value::from(UntaggedValue::filepath( - "C:\\Users\\viking\\code\\test.txt", - ))]), - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get dirname of a path", - example: "'/home/joe/code/test.txt' | path dirname", - result: Some(vec![Value::from(UntaggedValue::filepath("/home/joe/code"))]), - }, - Example { - description: "Get dirname of a path in a column", - example: "ls ('.' | path expand) | path dirname -c [ name ]", - result: None, - }, - Example { - description: "Walk up two levels", - example: "'/home/joe/code/test.txt' | path dirname -n 2", - result: Some(vec![Value::from(UntaggedValue::filepath("/home/joe"))]), - }, - Example { - description: "Replace the part that would be returned with a custom path", - example: "'/home/joe/code/test.txt' | path dirname -n 2 -r /home/viking", - result: Some(vec![Value::from(UntaggedValue::filepath( - "/home/viking/code/test.txt", - ))]), - }, - ] - } -} - -fn action(path: &Path, tag: Tag, args: &PathDirnameArguments) -> Value { - let num_levels = args.num_levels.as_ref().map_or(1, |tagged| tagged.item); - - let mut dirname = path; - let mut reached_top = false; // end early if somebody passes -n 99999999 - for _ in 0..num_levels { - dirname = dirname.parent().unwrap_or_else(|| { - reached_top = true; - dirname - }); - if reached_top { - break; - } - } - - let untagged = match args.replace { - Some(ref newdir) => { - let remainder = path.strip_prefix(dirname).unwrap_or(dirname); - if !remainder.as_os_str().is_empty() { - UntaggedValue::filepath(Path::new(&newdir.item).join(remainder)) - } else { - UntaggedValue::filepath(Path::new(&newdir.item)) - } - } - None => UntaggedValue::filepath(dirname), - }; - - untagged.into_value(tag) -} - -#[cfg(test)] -mod tests { - use super::PathDirname; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathDirname {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/exists.rs b/old_nushell/crates/nu-command/src/commands/path/exists.rs deleted file mode 100644 index e88b3b643..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/exists.rs +++ /dev/null @@ -1,95 +0,0 @@ -use super::{column_paths_from_args, operate, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use std::path::Path; - -pub struct PathExists; - -struct PathExistsArguments { - columns: Vec, -} - -impl PathSubcommandArguments for PathExistsArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathExists { - fn name(&self) -> &str { - "path exists" - } - - fn signature(&self) -> Signature { - Signature::build("path exists").named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - } - - fn usage(&self) -> &str { - "Check whether a path exists" - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathExistsArguments { - columns: column_paths_from_args(&args)?, - }); - - Ok(operate(args.input, &action, tag.span, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Check if a file exists", - example: "'C:\\Users\\joe\\todo.txt' | path exists", - result: Some(vec![Value::from(UntaggedValue::boolean(false))]), - }, - Example { - description: "Check if a file exists in a column", - example: "ls | path exists -c [ name ]", - result: None, - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Check if a file exists", - example: "'/home/joe/todo.txt' | path exists", - result: Some(vec![Value::from(UntaggedValue::boolean(false))]), - }, - Example { - description: "Check if a file exists in a column", - example: "ls | path exists -c [ name ]", - result: None, - }, - ] - } -} - -fn action(path: &Path, tag: Tag, _args: &PathExistsArguments) -> Value { - UntaggedValue::boolean(path.exists()).into_value(tag) -} - -#[cfg(test)] -mod tests { - use super::PathExists; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathExists {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/expand.rs b/old_nushell/crates/nu-command/src/commands/path/expand.rs deleted file mode 100644 index e30504e9c..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/expand.rs +++ /dev/null @@ -1,134 +0,0 @@ -use super::{column_paths_from_args, operate, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_path::{canonicalize, expand_path}; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Span; -use std::path::Path; - -pub struct PathExpand; - -struct PathExpandArguments { - strict: bool, - columns: Vec, -} - -impl PathSubcommandArguments for PathExpandArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathExpand { - fn name(&self) -> &str { - "path expand" - } - - fn signature(&self) -> Signature { - Signature::build("path expand") - .switch( - "strict", - "Throw an error if the path could not be expanded", - Some('s'), - ) - .named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - } - - fn usage(&self) -> &str { - "Try to expand a path to its absolute form" - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathExpandArguments { - strict: args.has_flag("strict"), - columns: column_paths_from_args(&args)?, - }); - - Ok(operate(args.input, &action, tag.span, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Expand an absolute path", - example: r"'C:\Users\joe\foo\..\bar' | path expand", - result: Some(vec![ - UntaggedValue::filepath(r"C:\Users\joe\bar").into_value(Span::new(0, 25)) - ]), - }, - Example { - description: "Expand a path in a column", - example: "ls | path expand -c [ name ]", - result: None, - }, - Example { - description: "Expand a relative path", - example: r"'foo\..\bar' | path expand", - result: Some(vec![ - UntaggedValue::filepath("bar").into_value(Span::new(0, 12)) - ]), - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Expand an absolute path", - example: "'/home/joe/foo/../bar' | path expand", - result: Some(vec![ - UntaggedValue::filepath("/home/joe/bar").into_value(Span::new(0, 22)) - ]), - }, - Example { - description: "Expand a path in a column", - example: "ls | path expand -c [ name ]", - result: None, - }, - Example { - description: "Expand a relative path", - example: "'foo/../bar' | path expand", - result: Some(vec![ - UntaggedValue::filepath("bar").into_value(Span::new(0, 12)) - ]), - }, - ] - } -} - -fn action(path: &Path, tag: Tag, args: &PathExpandArguments) -> Value { - if let Ok(p) = canonicalize(path) { - UntaggedValue::filepath(p).into_value(tag) - } else if args.strict { - Value::error(ShellError::labeled_error( - "Could not expand path", - "could not be expanded (path might not exist, non-final \ - component is not a directory, or other cause)", - tag.span, - )) - } else { - UntaggedValue::filepath(expand_path(path)).into_value(tag) - } -} - -#[cfg(test)] -mod tests { - use super::PathExpand; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathExpand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/join.rs b/old_nushell/crates/nu-command/src/commands/path/join.rs deleted file mode 100644 index a81eaf300..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/join.rs +++ /dev/null @@ -1,193 +0,0 @@ -use super::{ - column_paths_from_args, handle_value, join_path, operate_column_paths, PathSubcommandArguments, -}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use std::path::{Path, PathBuf}; - -pub struct PathJoin; - -struct PathJoinArguments { - columns: Vec, - append: Option>, -} - -impl PathSubcommandArguments for PathJoinArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathJoin { - fn name(&self) -> &str { - "path join" - } - - fn signature(&self) -> Signature { - Signature::build("path join") - .named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - .optional( - "append", - SyntaxShape::FilePath, - "Path to append to the input", - ) - } - - fn usage(&self) -> &str { - "Join a structured path or a list of path parts." - } - - fn extra_usage(&self) -> &str { - r#"Optionally, append an additional path to the result. It is designed to accept -the output of 'path parse' and 'path split' subcommands."# - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let cmd_args = Arc::new(PathJoinArguments { - columns: column_paths_from_args(&args)?, - append: args.opt(0)?, - }); - - Ok(operate_join(args.input, &action, tag, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Append a filename to a path", - example: r"'C:\Users\viking' | path join spam.txt", - result: Some(vec![Value::from(UntaggedValue::filepath( - r"C:\Users\viking\spam.txt", - ))]), - }, - Example { - description: "Append a filename to a path inside a column", - example: r"ls | path join spam.txt -c [ name ]", - result: None, - }, - Example { - description: "Join a list of parts into a path", - example: r"[ 'C:' '\' 'Users' 'viking' 'spam.txt' ] | path join", - result: Some(vec![Value::from(UntaggedValue::filepath( - r"C:\Users\viking\spam.txt", - ))]), - }, - Example { - description: "Join a structured path into a path", - example: r"[ [parent stem extension]; ['C:\Users\viking' 'spam' 'txt']] | path join", - result: Some(vec![Value::from(UntaggedValue::filepath( - r"C:\Users\viking\spam.txt", - ))]), - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Append a filename to a path", - example: r"'/home/viking' | path join spam.txt", - result: Some(vec![Value::from(UntaggedValue::filepath( - r"/home/viking/spam.txt", - ))]), - }, - Example { - description: "Append a filename to a path inside a column", - example: r"ls | path join spam.txt -c [ name ]", - result: None, - }, - Example { - description: "Join a list of parts into a path", - example: r"[ '/' 'home' 'viking' 'spam.txt' ] | path join", - result: Some(vec![Value::from(UntaggedValue::filepath( - r"/home/viking/spam.txt", - ))]), - }, - Example { - description: "Join a structured path into a path", - example: r"[[ parent stem extension ]; [ '/home/viking' 'spam' 'txt' ]] | path join", - result: Some(vec![Value::from(UntaggedValue::filepath( - r"/home/viking/spam.txt", - ))]), - }, - ] - } -} - -fn operate_join( - input: crate::InputStream, - action: &'static F, - tag: Tag, - args: Arc, -) -> OutputStream -where - T: PathSubcommandArguments + Send + Sync + 'static, - F: Fn(&Path, Tag, &T) -> Value + Send + Sync + 'static, -{ - let span = tag.span; - - if args.get_column_paths().is_empty() { - let mut parts = input.peekable(); - let has_rows = matches!( - parts.peek(), - Some(&Value { - value: UntaggedValue::Row(_), - .. - }) - ); - - if has_rows { - // operate one-by-one like the other path subcommands - parts - .into_iter() - .map( - move |v| match handle_value(&action, &v, span, Arc::clone(&args)) { - Ok(v) => v, - Err(e) => Value::error(e), - }, - ) - .into_output_stream() - } else { - // join the whole input stream - match join_path(&parts.collect_vec(), &span) { - Ok(path_buf) => OutputStream::one(action(&path_buf, tag, &args)), - Err(e) => OutputStream::one(Value::error(e)), - } - } - } else { - operate_column_paths(input, action, span, args) - } -} - -fn action(path: &Path, tag: Tag, args: &PathJoinArguments) -> Value { - if let Some(ref append) = args.append { - UntaggedValue::filepath(path.join(&append.item)).into_value(tag) - } else { - UntaggedValue::filepath(path).into_value(tag) - } -} - -#[cfg(test)] -mod tests { - use super::PathJoin; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathJoin {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/mod.rs b/old_nushell/crates/nu-command/src/commands/path/mod.rs deleted file mode 100644 index ffd2fba52..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/mod.rs +++ /dev/null @@ -1,251 +0,0 @@ -mod basename; -mod command; -mod dirname; -mod exists; -mod expand; -mod join; -mod parse; -mod relative_to; -mod split; -mod r#type; - -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{ - ColumnPath, Dictionary, MaybeOwned, Primitive, ShellTypeName, UntaggedValue, Value, -}; -use nu_source::Span; -use std::path::{Path, PathBuf}; -use std::sync::Arc; - -pub use basename::PathBasename; -pub use command::Path as PathCommand; -pub use dirname::PathDirname; -pub use exists::PathExists; -pub use expand::PathExpand; -pub use join::PathJoin; -pub use parse::PathParse; -pub use r#type::PathType; -pub use relative_to::PathRelativeTo; -pub use split::PathSplit; - -#[cfg(windows)] -const ALLOWED_COLUMNS: [&str; 4] = ["prefix", "parent", "stem", "extension"]; -#[cfg(not(windows))] -const ALLOWED_COLUMNS: [&str; 3] = ["parent", "stem", "extension"]; - -trait PathSubcommandArguments { - fn get_column_paths(&self) -> &Vec; -} - -fn encode_path( - entries: &Dictionary, - orig_span: Span, - new_span: Span, -) -> Result { - if entries.length() == 0 { - return Err(ShellError::labeled_error_with_secondary( - "Empty table cannot be encoded as a path", - "got empty table", - new_span, - "originates from here", - orig_span, - )); - } - - for col in entries.keys() { - if !ALLOWED_COLUMNS.contains(&col.as_str()) { - let msg = format!( - "Column '{}' is not valid for a structured path. Allowed columns are: {}", - col, - ALLOWED_COLUMNS.join(", ") - ); - return Err(ShellError::labeled_error_with_secondary( - "Expected structured path table", - msg, - new_span, - "originates from here", - orig_span, - )); - } - } - - // At this point, the row is known to have >0 columns, all of them allowed - let mut result = PathBuf::new(); - - #[cfg(windows)] - if let MaybeOwned::Borrowed(val) = entries.get_data("prefix") { - let s = val.as_string()?; - if !s.is_empty() { - result.push(&s); - } - }; - - if let MaybeOwned::Borrowed(val) = entries.get_data("parent") { - let p = val.as_string()?; - if !p.is_empty() { - result.push(p); - } - }; - - let mut basename = String::new(); - - if let MaybeOwned::Borrowed(val) = entries.get_data("stem") { - let s = val.as_string()?; - if !s.is_empty() { - basename.push_str(&s); - } - }; - - if let MaybeOwned::Borrowed(val) = entries.get_data("extension") { - let s = val.as_string()?; - if !s.is_empty() { - basename.push('.'); - basename.push_str(&s); - } - }; - - if !basename.is_empty() { - result.push(basename); - } - - Ok(result) -} - -fn join_path(parts: &[Value], new_span: &Span) -> Result { - parts - .iter() - .map(|part| match &part.value { - UntaggedValue::Primitive(Primitive::String(s)) => Ok(Path::new(s)), - UntaggedValue::Primitive(Primitive::FilePath(pb)) => Ok(pb.as_path()), - _ => { - let got = format!("got {}", part.type_name()); - Err(ShellError::labeled_error_with_secondary( - "Cannot join values that are not paths or strings.", - got, - new_span, - "originates from here", - part.tag.span, - )) - } - }) - .collect() -} - -fn handle_value(action: &F, v: &Value, span: Span, args: Arc) -> Result -where - T: PathSubcommandArguments, - F: Fn(&Path, Tag, &T) -> Value, -{ - match &v.value { - UntaggedValue::Primitive(Primitive::FilePath(buf)) => Ok(action(buf, v.tag(), &args)), - UntaggedValue::Primitive(Primitive::String(s)) => Ok(action(s.as_ref(), v.tag(), &args)), - UntaggedValue::Row(entries) => { - // implicit path join makes all subcommands understand the structured path - let path_buf = encode_path(entries, v.tag().span, span)?; - Ok(action(&path_buf, v.tag(), &args)) - } - UntaggedValue::Table(parts) => { - // implicit path join makes all subcommands understand path split into parts - let path_buf = join_path(parts, &span)?; - Ok(action(&path_buf, v.tag(), &args)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error_with_secondary( - "Value is a not string, path, row, or table", - got, - span, - "originates from here", - v.tag().span, - )) - } - } -} - -fn operate_column_paths( - input: crate::InputStream, - action: &'static F, - span: Span, - args: Arc, -) -> OutputStream -where - T: PathSubcommandArguments + Send + Sync + 'static, - F: Fn(&Path, Tag, &T) -> Value + Send + Sync + 'static, -{ - input - .map(move |v| { - let mut ret = v; - - for path in args.get_column_paths() { - let cloned_args = Arc::clone(&args); - ret = match ret.swap_data_by_column_path( - path, - Box::new(move |old| handle_value(&action, old, span, cloned_args)), - ) { - Ok(v) => v, - Err(e) => Value::error(e), - }; - } - - ret - }) - .into_output_stream() -} - -fn operate( - input: crate::InputStream, - action: &'static F, - span: Span, - args: Arc, -) -> OutputStream -where - T: PathSubcommandArguments + Send + Sync + 'static, - F: Fn(&Path, Tag, &T) -> Value + Send + Sync + 'static, -{ - if args.get_column_paths().is_empty() { - input - .map( - move |v| match handle_value(&action, &v, span, Arc::clone(&args)) { - Ok(v) => v, - Err(e) => Value::error(e), - }, - ) - .into_output_stream() - } else { - operate_column_paths(input, action, span, args) - } -} - -fn column_paths_from_args(args: &CommandArgs) -> Result, ShellError> { - let column_paths: Option> = args.get_flag("columns")?; - let has_columns = column_paths.is_some(); - let column_paths = match column_paths { - Some(cols) => { - let mut c = Vec::new(); - for col in cols { - let colpath = ColumnPath::build(&col.convert_to_string().spanned_unknown()); - if !colpath.is_empty() { - c.push(colpath) - } - } - c - } - None => Vec::new(), - }; - - if has_columns && column_paths.is_empty() { - let colval: Option = args.get_flag("columns")?; - let colspan = match colval { - Some(v) => v.tag.span, - None => Span::unknown(), - }; - return Err(ShellError::labeled_error( - "Requires a list of columns", - "must be a list of columns", - colspan, - )); - } - - Ok(column_paths) -} diff --git a/old_nushell/crates/nu-command/src/commands/path/parse.rs b/old_nushell/crates/nu-command/src/commands/path/parse.rs deleted file mode 100644 index 81fd30ea4..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/parse.rs +++ /dev/null @@ -1,181 +0,0 @@ -use super::{column_paths_from_args, operate, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tagged; -#[cfg(windows)] -use std::path::Component; -use std::path::Path; - -pub struct PathParse; - -struct PathParseArguments { - columns: Vec, - extension: Option>, -} - -impl PathSubcommandArguments for PathParseArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathParse { - fn name(&self) -> &str { - "path parse" - } - - fn signature(&self) -> Signature { - Signature::build("path parse") - .named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - .named( - "extension", - SyntaxShape::String, - "Manually supply the extension (without the dot)", - Some('e'), - ) - } - - fn usage(&self) -> &str { - "Convert a path into structured data." - } - - fn extra_usage(&self) -> &str { - r#"Each path is split into a table with 'parent', 'stem' and 'extension' fields. -On Windows, an extra 'prefix' column is added."# - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathParseArguments { - columns: column_paths_from_args(&args)?, - extension: args.get_flag("extension")?, - }); - - Ok(operate(args.input, &action, tag.span, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Parse a single path", - example: r"'C:\Users\viking\spam.txt' | path parse", - result: None, - }, - Example { - description: "Replace a complex extension", - example: r"'C:\Users\viking\spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }", - result: None, - }, - Example { - description: "Ignore the extension", - example: r"'C:\Users\viking.d' | path parse -e ''", - result: None, - }, - Example { - description: "Parse all paths under the 'name' column", - example: r"ls | path parse -c [ name ]", - result: None, - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Parse a path", - example: r"'/home/viking/spam.txt' | path parse", - result: None, - }, - Example { - description: "Replace a complex extension", - example: r"'/home/viking/spam.tar.gz' | path parse -e tar.gz | update extension { 'txt' }", - result: None, - }, - Example { - description: "Ignore the extension", - example: r"'/etc/conf.d' | path parse -e ''", - result: None, - }, - Example { - description: "Parse all paths under the 'name' column", - example: r"ls | path parse -c [ name ]", - result: None, - }, - ] - } -} - -fn action(path: &Path, tag: Tag, args: &PathParseArguments) -> Value { - let mut dict = TaggedDictBuilder::new(&tag); - - #[cfg(windows)] - { - // The prefix is only valid on Windows. On non-Windows, it's always empty. - let prefix = match path.components().next() { - Some(Component::Prefix(prefix_component)) => { - prefix_component.as_os_str().to_string_lossy() - } - _ => "".into(), - }; - dict.insert_untagged("prefix", UntaggedValue::string(prefix)); - } - - let parent = path.parent().unwrap_or_else(|| "".as_ref()); - dict.insert_untagged("parent", UntaggedValue::filepath(parent)); - - let basename = path - .file_name() - .unwrap_or_else(|| "".as_ref()) - .to_string_lossy(); - - match &args.extension { - Some(Tagged { item: ext, .. }) => { - let ext_with_dot = [".", ext].concat(); - if basename.ends_with(&ext_with_dot) && !ext.is_empty() { - let stem = basename.trim_end_matches(&ext_with_dot); - dict.insert_untagged("stem", UntaggedValue::string(stem)); - dict.insert_untagged("extension", UntaggedValue::string(ext)); - } else { - dict.insert_untagged("stem", UntaggedValue::string(basename)); - dict.insert_untagged("extension", UntaggedValue::string("")); - } - } - None => { - let stem = path - .file_stem() - .unwrap_or_else(|| "".as_ref()) - .to_string_lossy(); - let extension = path - .extension() - .unwrap_or_else(|| "".as_ref()) - .to_string_lossy(); - - dict.insert_untagged("stem", UntaggedValue::string(stem)); - dict.insert_untagged("extension", UntaggedValue::string(extension)); - } - } - - dict.into_value() -} - -#[cfg(test)] -mod tests { - use super::PathParse; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathParse {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/relative_to.rs b/old_nushell/crates/nu-command/src/commands/path/relative_to.rs deleted file mode 100644 index d62b262db..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/relative_to.rs +++ /dev/null @@ -1,133 +0,0 @@ -use super::{column_paths_from_args, operate, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use std::path::{Path, PathBuf}; - -pub struct PathRelativeTo; - -struct PathRelativeToArguments { - path: Tagged, - columns: Vec, -} - -impl PathSubcommandArguments for PathRelativeToArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathRelativeTo { - fn name(&self) -> &str { - "path relative-to" - } - - fn signature(&self) -> Signature { - Signature::build("path relative-to") - .required( - "path", - SyntaxShape::FilePath, - "Parent shared with the input path", - ) - .named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - } - - fn usage(&self) -> &str { - "Get a path as relative to another path." - } - - fn extra_usage(&self) -> &str { - r#"Can be used only when the input and the argument paths are either both -absolute or both relative. The argument path needs to be a parent of the input -path."# - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathRelativeToArguments { - path: args.req(0)?, - columns: column_paths_from_args(&args)?, - }); - - Ok(operate(args.input, &action, tag.span, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Find a relative path from two absolute paths", - example: r"'C:\Users\viking' | path relative-to 'C:\Users'", - result: Some(vec![Value::from(UntaggedValue::filepath(r"viking"))]), - }, - Example { - description: "Find a relative path from two absolute paths in a column", - example: "ls ~ | path relative-to ~ -c [ name ]", - result: None, - }, - Example { - description: "Find a relative path from two relative paths", - example: r"'eggs\bacon\sausage\spam' | path relative-to 'eggs\bacon\sausage'", - result: Some(vec![Value::from(UntaggedValue::filepath(r"spam"))]), - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Find a relative path from two absolute paths", - example: r"'/home/viking' | path relative-to '/home'", - result: Some(vec![Value::from(UntaggedValue::filepath(r"viking"))]), - }, - Example { - description: "Find a relative path from two absolute paths in a column", - example: "ls ~ | path relative-to ~ -c [ name ]", - result: None, - }, - Example { - description: "Find a relative path from two relative paths", - example: r"'eggs/bacon/sausage/spam' | path relative-to 'eggs/bacon/sausage'", - result: Some(vec![Value::from(UntaggedValue::filepath(r"spam"))]), - }, - ] - } -} - -fn action(path: &Path, tag: Tag, args: &PathRelativeToArguments) -> Value { - match path.strip_prefix(&args.path.item) { - Ok(p) => UntaggedValue::filepath(p).into_value(tag), - Err(_) => Value::error(ShellError::labeled_error_with_secondary( - format!( - "'{}' is not a subpath of '{}'", - path.to_string_lossy(), - &args.path.item.to_string_lossy() - ), - "should be a parent of the input path", - args.path.tag.span, - "originates from here", - tag.span, - )), - } -} - -#[cfg(test)] -mod tests { - use super::PathRelativeTo; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathRelativeTo {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/split.rs b/old_nushell/crates/nu-command/src/commands/path/split.rs deleted file mode 100644 index d51505b2d..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/split.rs +++ /dev/null @@ -1,149 +0,0 @@ -use super::{column_paths_from_args, handle_value, operate_column_paths, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use std::path::Path; - -pub struct PathSplit; - -struct PathSplitArguments { - columns: Vec, -} - -impl PathSubcommandArguments for PathSplitArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathSplit { - fn name(&self) -> &str { - "path split" - } - - fn signature(&self) -> Signature { - Signature::build("path split").named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - } - - fn usage(&self) -> &str { - "Split a path into parts by a separator." - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathSplitArguments { - columns: column_paths_from_args(&args)?, - }); - - Ok(operate_split(args.input, &action, tag.span, cmd_args)) - } - - #[cfg(windows)] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Split a path into parts", - example: r"'C:\Users\viking\spam.txt' | path split", - result: Some(vec![ - Value::from(UntaggedValue::string("C:")), - Value::from(UntaggedValue::string(r"\")), - Value::from(UntaggedValue::string("Users")), - Value::from(UntaggedValue::string("viking")), - Value::from(UntaggedValue::string("spam.txt")), - ]), - }, - Example { - description: "Split all paths under the 'name' column", - example: r"ls ('.' | path expand) | path split -c [ name ]", - result: None, - }, - ] - } - - #[cfg(not(windows))] - fn examples(&self) -> Vec { - vec![ - Example { - description: "Split a path into parts", - example: r"'/home/viking/spam.txt' | path split", - result: Some(vec![ - Value::from(UntaggedValue::string("/")), - Value::from(UntaggedValue::string("home")), - Value::from(UntaggedValue::string("viking")), - Value::from(UntaggedValue::string("spam.txt")), - ]), - }, - Example { - description: "Split all paths under the 'name' column", - example: r"ls ('.' | path expand) | path split -c [ name ]", - result: None, - }, - ] - } -} - -fn operate_split( - input: crate::InputStream, - action: &'static F, - span: Span, - args: Arc, -) -> OutputStream -where - T: PathSubcommandArguments + Send + Sync + 'static, - F: Fn(&Path, Tag, &T) -> Value + Send + Sync + 'static, -{ - if args.get_column_paths().is_empty() { - // Do not wrap result into a table - input - .flat_map(move |v| { - let split_result = handle_value(&action, &v, span, Arc::clone(&args)); - - match split_result { - Ok(Value { - value: UntaggedValue::Table(parts), - .. - }) => parts.into_iter().into_output_stream(), - Err(e) => OutputStream::one(Value::error(e)), - _ => OutputStream::one(Value::error(ShellError::labeled_error( - "Internal Error", - "unexpected result from the split function", - span, - ))), - } - }) - .into_output_stream() - } else { - operate_column_paths(input, action, span, args) - } -} - -fn action(path: &Path, tag: Tag, _args: &PathSplitArguments) -> Value { - let parts: Vec = path - .components() - .map(|comp| { - let s = comp.as_os_str().to_string_lossy(); - UntaggedValue::string(s).into_value(&tag) - }) - .collect(); - - UntaggedValue::table(&parts).into_value(tag) -} - -#[cfg(test)] -mod tests { - use super::PathSplit; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathSplit {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/path/type.rs b/old_nushell/crates/nu-command/src/commands/path/type.rs deleted file mode 100644 index 041f9fbf0..000000000 --- a/old_nushell/crates/nu-command/src/commands/path/type.rs +++ /dev/null @@ -1,85 +0,0 @@ -use super::{column_paths_from_args, operate, PathSubcommandArguments}; -use crate::prelude::*; -use nu_engine::filesystem::filesystem_shell::get_file_type; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Signature, SyntaxShape, UntaggedValue, Value}; -use std::path::Path; - -pub struct PathType; - -struct PathTypeArguments { - columns: Vec, -} - -impl PathSubcommandArguments for PathTypeArguments { - fn get_column_paths(&self) -> &Vec { - &self.columns - } -} - -impl WholeStreamCommand for PathType { - fn name(&self) -> &str { - "path type" - } - - fn signature(&self) -> Signature { - Signature::build("path type").named( - "columns", - SyntaxShape::Table, - "Optionally operate by column path", - Some('c'), - ) - } - - fn usage(&self) -> &str { - "Get the type of the object a path refers to (e.g., file, dir, symlink)" - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let cmd_args = Arc::new(PathTypeArguments { - columns: column_paths_from_args(&args)?, - }); - - Ok(operate(args.input, &action, tag.span, cmd_args)) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Show type of a filepath", - example: "'.' | path type", - result: Some(vec![Value::from("Dir")]), - }, - Example { - description: "Show type of a filepath in a column", - example: "ls | path type -c [ name ]", - result: None, - }, - ] - } -} - -fn action(path: &Path, tag: Tag, _args: &PathTypeArguments) -> Value { - let meta = std::fs::symlink_metadata(path); - let untagged = UntaggedValue::string(match &meta { - Ok(md) => get_file_type(md), - Err(_) => "", - }); - - untagged.into_value(tag) -} - -#[cfg(test)] -mod tests { - use super::PathType; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(PathType {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/pathvar/add.rs b/old_nushell/crates/nu-command/src/commands/pathvar/add.rs deleted file mode 100644 index 4605a626f..000000000 --- a/old_nushell/crates/nu-command/src/commands/pathvar/add.rs +++ /dev/null @@ -1,71 +0,0 @@ -use super::get_var; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; -use nu_test_support::NATIVE_PATH_ENV_SEPARATOR; -use std::path::PathBuf; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "pathvar add" - } - - fn signature(&self) -> Signature { - Signature::build("pathvar add") - .required("path", SyntaxShape::FilePath, "path to add") - .named( - "var", - SyntaxShape::String, - "Use a different variable than PATH", - Some('v'), - ) - } - - fn usage(&self) -> &str { - "Add a filepath to the start of the pathvar" - } - - fn run(&self, args: CommandArgs) -> Result { - add(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Add /usr/local/bin to the pathvar", - example: "pathvar add /usr/local/bin", - result: None, - }] - } -} - -pub fn add(args: CommandArgs) -> Result { - let ctx = &args.context; - - let var = get_var(&args)?; - let path_to_add: Tagged = args.req(0)?; - let path = path_to_add.item.into_os_string().into_string(); - - if let Ok(mut path) = path { - path.push(NATIVE_PATH_ENV_SEPARATOR); - if let Some(old_pathvar) = ctx.scope.get_env(&var) { - path.push_str(&old_pathvar); - ctx.scope.add_env_var(&var.item, path); - Ok(OutputStream::empty()) - } else { - Err(ShellError::unexpected(&format!( - "Variable {} not set", - &var.item - ))) - } - } else { - Err(ShellError::labeled_error( - "Invalid path.", - "cannot convert to string", - path_to_add.tag, - )) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/pathvar/append.rs b/old_nushell/crates/nu-command/src/commands/pathvar/append.rs deleted file mode 100644 index 855cb179c..000000000 --- a/old_nushell/crates/nu-command/src/commands/pathvar/append.rs +++ /dev/null @@ -1,71 +0,0 @@ -use super::get_var; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; -use nu_test_support::NATIVE_PATH_ENV_SEPARATOR; -use std::path::PathBuf; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "pathvar append" - } - - fn signature(&self) -> Signature { - Signature::build("pathvar append") - .required("path", SyntaxShape::FilePath, "path to append") - .named( - "var", - SyntaxShape::String, - "Use a different variable than PATH", - Some('v'), - ) - } - - fn usage(&self) -> &str { - "Add a path to the end of the pathvar" - } - - fn run(&self, args: CommandArgs) -> Result { - add(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Append /bin to the pathvar", - example: "pathvar append /bin", - result: None, - }] - } -} - -pub fn add(args: CommandArgs) -> Result { - let ctx = &args.context; - - let var = get_var(&args)?; - let path_to_append_arg: Tagged = args.req(0)?; - let path_to_append = path_to_append_arg.item.into_os_string().into_string(); - - if let Ok(path) = path_to_append { - if let Some(mut pathvar) = ctx.scope.get_env(&var) { - pathvar.push(NATIVE_PATH_ENV_SEPARATOR); - pathvar.push_str(&path); - ctx.scope.add_env_var(&var.item, pathvar); - Ok(OutputStream::empty()) - } else { - Err(ShellError::unexpected(&format!( - "Variable {} not set", - &var.item - ))) - } - } else { - Err(ShellError::labeled_error( - "Invalid path.", - "cannot convert to string", - path_to_append_arg.tag, - )) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/pathvar/command.rs b/old_nushell/crates/nu-command/src/commands/pathvar/command.rs deleted file mode 100644 index 74d84eff4..000000000 --- a/old_nushell/crates/nu-command/src/commands/pathvar/command.rs +++ /dev/null @@ -1,75 +0,0 @@ -use super::get_var; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; -use nu_test_support::NATIVE_PATH_ENV_SEPARATOR; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "pathvar" - } - - fn signature(&self) -> Signature { - Signature::build("pathvar").named( - "var", - SyntaxShape::String, - "Use a different variable than PATH", - Some('v'), - ) - } - - fn usage(&self) -> &str { - r#"Manipulate the PATH variable (pathvar) or a different variable following the -same rules."# - } - - fn run(&self, args: CommandArgs) -> Result { - get_pathvar(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Display the current session's pathvar", - example: "pathvar", - result: None, - }, - Example { - description: "Display the current session's LD_LIBRARY_PATH", - example: "pathvar -v LD_LIBRARY_PATH", - result: None, - }, - Example { - description: "Add /usr/bin to the pathvar", - example: "pathvar add /usr/bin", - result: None, - }, - Example { - description: "Remove the 3rd path in the pathvar", - example: "pathvar remove 2", - result: None, - }, - ] - } -} - -pub fn get_pathvar(args: CommandArgs) -> Result { - let var = get_var(&args)?; - - if let Some(pathvar) = args.context.scope.get_env(&var) { - let pathvar: Vec = pathvar - .split(NATIVE_PATH_ENV_SEPARATOR) - .map(Value::from) - .collect(); - - Ok(OutputStream::from(pathvar)) - } else { - Err(ShellError::unexpected(&format!( - "Variable {} not set", - &var.item - ))) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/pathvar/mod.rs b/old_nushell/crates/nu-command/src/commands/pathvar/mod.rs deleted file mode 100644 index 9825ccefd..000000000 --- a/old_nushell/crates/nu-command/src/commands/pathvar/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -pub mod add; -pub mod append; -pub mod command; -pub mod remove; -pub mod reset; -pub mod save; - -pub use add::SubCommand as PathvarAdd; -pub use append::SubCommand as PathvarAppend; -pub use command::Command as Pathvar; -pub use remove::SubCommand as PathvarRemove; -pub use reset::SubCommand as PathvarReset; -pub use save::SubCommand as PathvarSave; - -use nu_engine::CommandArgs; -use nu_errors::ShellError; -use nu_source::{Tagged, TaggedItem}; -use nu_test_support::NATIVE_PATH_ENV_VAR; - -fn get_var(args: &CommandArgs) -> Result, ShellError> { - Ok(args - .get_flag("var")? - .unwrap_or_else(|| String::from(NATIVE_PATH_ENV_VAR)) - .tagged_unknown()) -} diff --git a/old_nushell/crates/nu-command/src/commands/pathvar/remove.rs b/old_nushell/crates/nu-command/src/commands/pathvar/remove.rs deleted file mode 100644 index 035004843..000000000 --- a/old_nushell/crates/nu-command/src/commands/pathvar/remove.rs +++ /dev/null @@ -1,79 +0,0 @@ -use super::get_var; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; -use nu_test_support::NATIVE_PATH_ENV_SEPARATOR; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "pathvar remove" - } - - fn signature(&self) -> Signature { - Signature::build("pathvar remove") - .required( - "index", - SyntaxShape::Int, - "index of the path to remove (starting at 0)", - ) - .named( - "var", - SyntaxShape::String, - "Use a different variable than PATH", - Some('v'), - ) - } - - fn usage(&self) -> &str { - "Remove a path from the pathvar" - } - - fn run(&self, args: CommandArgs) -> Result { - remove(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Remove the second path from the pathvar", - example: "pathvar remove 1", - result: None, - }] - } -} - -pub fn remove(args: CommandArgs) -> Result { - let ctx = &args.context; - - let var = get_var(&args)?; - let index_to_remove_arg: Tagged = args.req(0)?; - let index_to_remove = index_to_remove_arg.item as usize; - - if let Some(old_pathvar) = ctx.scope.get_env(&var) { - let mut paths: Vec<&str> = old_pathvar.split(NATIVE_PATH_ENV_SEPARATOR).collect(); - - if index_to_remove >= paths.len() { - return Err(ShellError::labeled_error( - "Index out of bounds", - format!("the index must be between 0 and {}", paths.len() - 1), - index_to_remove_arg.tag, - )); - } - - paths.remove(index_to_remove); - ctx.scope.add_env_var( - &var.item, - paths.join(&NATIVE_PATH_ENV_SEPARATOR.to_string()), - ); - - Ok(OutputStream::empty()) - } else { - Err(ShellError::unexpected(&format!( - "Variable {} not set", - &var.item - ))) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/pathvar/reset.rs b/old_nushell/crates/nu-command/src/commands/pathvar/reset.rs deleted file mode 100644 index e8038e13f..000000000 --- a/old_nushell/crates/nu-command/src/commands/pathvar/reset.rs +++ /dev/null @@ -1,63 +0,0 @@ -use super::get_var; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_test_support::NATIVE_PATH_ENV_SEPARATOR; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "pathvar reset" - } - - fn signature(&self) -> Signature { - Signature::build("pathvar reset").named( - "var", - SyntaxShape::String, - "Use a different variable than PATH", - Some('v'), - ) - } - - fn usage(&self) -> &str { - "Reset the pathvar to the one specified in the config" - } - - fn run(&self, args: CommandArgs) -> Result { - reset(args) - } -} - -pub fn reset(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let var = get_var(&args)?; - let var_lower = var.clone().map(|s| s.to_lowercase()); - - if let Some(global_cfg) = &mut ctx.configs().lock().global_config { - let default_pathvar = global_cfg.vars.get(&var_lower.item); - if let Some(pathvar) = default_pathvar { - if let UntaggedValue::Table(paths) = &pathvar.value { - let pathvar_str = paths - .iter() - .map(|x| x.as_string().expect("Error converting path to string")) - .join(&NATIVE_PATH_ENV_SEPARATOR.to_string()); - ctx.scope.add_env_var(&var.item, pathvar_str); - } - } else { - return Err(ShellError::untagged_runtime_error(&format!( - "Default {} is not set in config file.", - &var_lower.item - ))); - } - Ok(OutputStream::empty()) - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/pathvar/save.rs b/old_nushell/crates/nu-command/src/commands/pathvar/save.rs deleted file mode 100644 index 5684019a2..000000000 --- a/old_nushell/crates/nu-command/src/commands/pathvar/save.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::get_var; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_test_support::NATIVE_PATH_ENV_SEPARATOR; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "pathvar save" - } - - fn signature(&self) -> Signature { - Signature::build("pathvar save").named( - "var", - SyntaxShape::String, - "Use a different variable than PATH", - Some('v'), - ) - } - - fn usage(&self) -> &str { - "Save the current pathvar to the config file" - } - - fn run(&self, args: CommandArgs) -> Result { - save(args) - } -} -pub fn save(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let ctx = &args.context; - - let var = get_var(&args)?; - let var_lower = var.clone().map(|s| s.to_lowercase()); - - if let Some(global_cfg) = &mut ctx.configs().lock().global_config { - if let Some(pathvar) = ctx.scope.get_env(&var) { - let paths: Vec = pathvar - .split(NATIVE_PATH_ENV_SEPARATOR) - .map(Value::from) - .collect(); - - let span_range = 0..paths.len(); - let row = Value::new( - UntaggedValue::Table(paths), - Tag::from(Span::from(&span_range)), - ); - - global_cfg.vars.insert(var_lower.item, row); - global_cfg.write()?; - ctx.reload_config(global_cfg)?; - - Ok(OutputStream::empty()) - } else { - Err(ShellError::unexpected(&format!( - "Variable {} not set", - &var.item - ))) - } - } else { - let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present()) - .into_value(name); - - Ok(OutputStream::one(value)) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/ansi/command.rs b/old_nushell/crates/nu-command/src/commands/platform/ansi/command.rs deleted file mode 100644 index 3c1e2ceef..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/ansi/command.rs +++ /dev/null @@ -1,362 +0,0 @@ -use crate::prelude::*; -use nu_ansi_term::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "ansi" - } - - fn signature(&self) -> Signature { - Signature::build("ansi") - .optional( - "code", - SyntaxShape::Any, - "the name of the code to use like 'green' or 'reset' to reset the color", - ) - .named( - "escape", // \x1b[ - SyntaxShape::Any, - "escape sequence without the escape character(s)", - Some('e'), - ) - .named( - "osc", // \x1b] - SyntaxShape::Any, - "operating system command (ocs) escape sequence without the escape character(s)", - Some('o'), - ) - } - - fn usage(&self) -> &str { - "Output ANSI codes to change color." - } - - fn extra_usage(&self) -> &str { - r#"For escape sequences: -Escape: '\x1b[' is not required for --escape parameter -Format: #(;#)m -Example: 1;31m for bold red or 2;37;41m for dimmed white fg with red bg -There can be multiple text formatting sequence numbers -separated by a ; and ending with an m where the # is of the -following values: - attributes - 0 reset / normal display - 1 bold or increased intensity - 2 faint or decreased intensity - 3 italic on (non-mono font) - 4 underline on - 5 slow blink on - 6 fast blink on - 7 reverse video on - 8 nondisplayed (invisible) on - 9 strike-through on - - foreground/bright colors background/bright colors - 30/90 black 40/100 black - 31/91 red 41/101 red - 32/92 green 42/102 green - 33/93 yellow 43/103 yellow - 34/94 blue 44/104 blue - 35/95 magenta 45/105 magenta - 36/96 cyan 46/106 cyan - 37/97 white 47/107 white - https://en.wikipedia.org/wiki/ANSI_escape_code - -OSC: '\x1b]' is not required for --osc parameter -Example: echo [(ansi -o '0') 'some title' (char bel)] | str collect -Format: # - 0 Set window title and icon name - 1 Set icon name - 2 Set window title - 4 Set/read color palette - 9 iTerm2 Grown notifications - 10 Set foreground color (x11 color spec) - 11 Set background color (x11 color spec) - ... others"# - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Change color to green", - example: r#"ansi green"#, - result: Some(vec![Value::from("\u{1b}[32m")]), - }, - Example { - description: "Reset the color", - example: r#"ansi reset"#, - result: Some(vec![Value::from("\u{1b}[0m")]), - }, - Example { - description: - "Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)", - example: r#"echo [(ansi rb) Hello " " (ansi gb) Nu " " (ansi pb) World] | str collect"#, - result: Some(vec![Value::from( - "\u{1b}[1;31mHello \u{1b}[1;32mNu \u{1b}[1;35mWorld", - )]), - }, - Example { - description: - "Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)", - example: r#"echo [(ansi -e '3;93;41m') Hello (ansi reset) " " (ansi gb) Nu " " (ansi pb) World] | str collect"#, - result: Some(vec![Value::from( - "\u{1b}[3;93;41mHello\u{1b}[0m \u{1b}[1;32mNu \u{1b}[1;35mWorld", - )]), - }, - ] - } - - fn run(&self, args: CommandArgs) -> Result { - let code: Option> = args.opt(0)?; - let escape: Option> = args.get_flag("escape")?; - let osc: Option> = args.get_flag("osc")?; - - if let Some(e) = escape { - let esc_vec: Vec = e.item.chars().collect(); - if esc_vec[0] == '\\' { - return Err(ShellError::labeled_error( - "no need for escape characters", - "no need for escape characters", - e.tag(), - )); - } - let output = format!("\x1b[{}", e.item); - return Ok(OutputStream::one( - UntaggedValue::string(output).into_value(e.tag()), - )); - } - - if let Some(o) = osc { - let osc_vec: Vec = o.item.chars().collect(); - if osc_vec[0] == '\\' { - return Err(ShellError::labeled_error( - "no need for escape characters", - "no need for escape characters", - o.tag(), - )); - } - - //Operating system command aka osc ESC ] <- note the right brace, not left brace for osc - // OCS's need to end with a bell '\x07' char - let output = format!("\x1b]{};", o.item); - return Ok(OutputStream::one( - UntaggedValue::string(output).into_value(o.tag()), - )); - } - - if let Some(code) = code { - let ansi_code = str_to_ansi(&code.item); - - if let Some(output) = ansi_code { - Ok(OutputStream::one( - UntaggedValue::string(output).into_value(code.tag()), - )) - } else { - Err(ShellError::labeled_error( - "Unknown ansi code", - "unknown ansi code", - code.tag(), - )) - } - } else { - Err(ShellError::labeled_error( - "Expected ansi code", - "expect ansi code", - &args.call_info.name_tag, - )) - } - } -} - -pub fn str_to_ansi(s: &str) -> Option { - match s { - "g" | "green" => Some(Color::Green.prefix().to_string()), - "gb" | "green_bold" => Some(Color::Green.bold().prefix().to_string()), - "gu" | "green_underline" => Some(Color::Green.underline().prefix().to_string()), - "gi" | "green_italic" => Some(Color::Green.italic().prefix().to_string()), - "gd" | "green_dimmed" => Some(Color::Green.dimmed().prefix().to_string()), - "gr" | "green_reverse" => Some(Color::Green.reverse().prefix().to_string()), - - "lg" | "light_green" => Some(Color::LightGreen.prefix().to_string()), - "lgb" | "light_green_bold" => Some(Color::LightGreen.bold().prefix().to_string()), - "lgu" | "light_green_underline" => Some(Color::LightGreen.underline().prefix().to_string()), - "lgi" | "light_green_italic" => Some(Color::LightGreen.italic().prefix().to_string()), - "lgd" | "light_green_dimmed" => Some(Color::LightGreen.dimmed().prefix().to_string()), - "lgr" | "light_green_reverse" => Some(Color::LightGreen.reverse().prefix().to_string()), - - "r" | "red" => Some(Color::Red.prefix().to_string()), - "rb" | "red_bold" => Some(Color::Red.bold().prefix().to_string()), - "ru" | "red_underline" => Some(Color::Red.underline().prefix().to_string()), - "ri" | "red_italic" => Some(Color::Red.italic().prefix().to_string()), - "rd" | "red_dimmed" => Some(Color::Red.dimmed().prefix().to_string()), - "rr" | "red_reverse" => Some(Color::Red.reverse().prefix().to_string()), - - "lr" | "light_red" => Some(Color::LightRed.prefix().to_string()), - "lrb" | "light_red_bold" => Some(Color::LightRed.bold().prefix().to_string()), - "lru" | "light_red_underline" => Some(Color::LightRed.underline().prefix().to_string()), - "lri" | "light_red_italic" => Some(Color::LightRed.italic().prefix().to_string()), - "lrd" | "light_red_dimmed" => Some(Color::LightRed.dimmed().prefix().to_string()), - "lrr" | "light_red_reverse" => Some(Color::LightRed.reverse().prefix().to_string()), - - "u" | "blue" => Some(Color::Blue.prefix().to_string()), - "ub" | "blue_bold" => Some(Color::Blue.bold().prefix().to_string()), - "uu" | "blue_underline" => Some(Color::Blue.underline().prefix().to_string()), - "ui" | "blue_italic" => Some(Color::Blue.italic().prefix().to_string()), - "ud" | "blue_dimmed" => Some(Color::Blue.dimmed().prefix().to_string()), - "ur" | "blue_reverse" => Some(Color::Blue.reverse().prefix().to_string()), - - "lu" | "light_blue" => Some(Color::LightBlue.prefix().to_string()), - "lub" | "light_blue_bold" => Some(Color::LightBlue.bold().prefix().to_string()), - "luu" | "light_blue_underline" => Some(Color::LightBlue.underline().prefix().to_string()), - "lui" | "light_blue_italic" => Some(Color::LightBlue.italic().prefix().to_string()), - "lud" | "light_blue_dimmed" => Some(Color::LightBlue.dimmed().prefix().to_string()), - "lur" | "light_blue_reverse" => Some(Color::LightBlue.reverse().prefix().to_string()), - - "b" | "black" => Some(Color::Black.prefix().to_string()), - "bb" | "black_bold" => Some(Color::Black.bold().prefix().to_string()), - "bu" | "black_underline" => Some(Color::Black.underline().prefix().to_string()), - "bi" | "black_italic" => Some(Color::Black.italic().prefix().to_string()), - "bd" | "black_dimmed" => Some(Color::Black.dimmed().prefix().to_string()), - "br" | "black_reverse" => Some(Color::Black.reverse().prefix().to_string()), - - "ligr" | "light_gray" => Some(Color::LightGray.prefix().to_string()), - "ligrb" | "light_gray_bold" => Some(Color::LightGray.bold().prefix().to_string()), - "ligru" | "light_gray_underline" => Some(Color::LightGray.underline().prefix().to_string()), - "ligri" | "light_gray_italic" => Some(Color::LightGray.italic().prefix().to_string()), - "ligrd" | "light_gray_dimmed" => Some(Color::LightGray.dimmed().prefix().to_string()), - "ligrr" | "light_gray_reverse" => Some(Color::LightGray.reverse().prefix().to_string()), - - "y" | "yellow" => Some(Color::Yellow.prefix().to_string()), - "yb" | "yellow_bold" => Some(Color::Yellow.bold().prefix().to_string()), - "yu" | "yellow_underline" => Some(Color::Yellow.underline().prefix().to_string()), - "yi" | "yellow_italic" => Some(Color::Yellow.italic().prefix().to_string()), - "yd" | "yellow_dimmed" => Some(Color::Yellow.dimmed().prefix().to_string()), - "yr" | "yellow_reverse" => Some(Color::Yellow.reverse().prefix().to_string()), - - "ly" | "light_yellow" => Some(Color::LightYellow.prefix().to_string()), - "lyb" | "light_yellow_bold" => Some(Color::LightYellow.bold().prefix().to_string()), - "lyu" | "light_yellow_underline" => { - Some(Color::LightYellow.underline().prefix().to_string()) - } - "lyi" | "light_yellow_italic" => Some(Color::LightYellow.italic().prefix().to_string()), - "lyd" | "light_yellow_dimmed" => Some(Color::LightYellow.dimmed().prefix().to_string()), - "lyr" | "light_yellow_reverse" => Some(Color::LightYellow.reverse().prefix().to_string()), - - "p" | "purple" => Some(Color::Purple.prefix().to_string()), - "pb" | "purple_bold" => Some(Color::Purple.bold().prefix().to_string()), - "pu" | "purple_underline" => Some(Color::Purple.underline().prefix().to_string()), - "pi" | "purple_italic" => Some(Color::Purple.italic().prefix().to_string()), - "pd" | "purple_dimmed" => Some(Color::Purple.dimmed().prefix().to_string()), - "pr" | "purple_reverse" => Some(Color::Purple.reverse().prefix().to_string()), - - "lp" | "light_purple" => Some(Color::LightPurple.prefix().to_string()), - "lpb" | "light_purple_bold" => Some(Color::LightPurple.bold().prefix().to_string()), - "lpu" | "light_purple_underline" => { - Some(Color::LightPurple.underline().prefix().to_string()) - } - "lpi" | "light_purple_italic" => Some(Color::LightPurple.italic().prefix().to_string()), - "lpd" | "light_purple_dimmed" => Some(Color::LightPurple.dimmed().prefix().to_string()), - "lpr" | "light_purple_reverse" => Some(Color::LightPurple.reverse().prefix().to_string()), - - "c" | "cyan" => Some(Color::Cyan.prefix().to_string()), - "cb" | "cyan_bold" => Some(Color::Cyan.bold().prefix().to_string()), - "cu" | "cyan_underline" => Some(Color::Cyan.underline().prefix().to_string()), - "ci" | "cyan_italic" => Some(Color::Cyan.italic().prefix().to_string()), - "cd" | "cyan_dimmed" => Some(Color::Cyan.dimmed().prefix().to_string()), - "cr" | "cyan_reverse" => Some(Color::Cyan.reverse().prefix().to_string()), - - "lc" | "light_cyan" => Some(Color::LightCyan.prefix().to_string()), - "lcb" | "light_cyan_bold" => Some(Color::LightCyan.bold().prefix().to_string()), - "lcu" | "light_cyan_underline" => Some(Color::LightCyan.underline().prefix().to_string()), - "lci" | "light_cyan_italic" => Some(Color::LightCyan.italic().prefix().to_string()), - "lcd" | "light_cyan_dimmed" => Some(Color::LightCyan.dimmed().prefix().to_string()), - "lcr" | "light_cyan_reverse" => Some(Color::LightCyan.reverse().prefix().to_string()), - - "w" | "white" => Some(Color::White.prefix().to_string()), - "wb" | "white_bold" => Some(Color::White.bold().prefix().to_string()), - "wu" | "white_underline" => Some(Color::White.underline().prefix().to_string()), - "wi" | "white_italic" => Some(Color::White.italic().prefix().to_string()), - "wd" | "white_dimmed" => Some(Color::White.dimmed().prefix().to_string()), - "wr" | "white_reverse" => Some(Color::White.reverse().prefix().to_string()), - - "dgr" | "dark_gray" => Some(Color::DarkGray.prefix().to_string()), - "dgrb" | "dark_gray_bold" => Some(Color::DarkGray.bold().prefix().to_string()), - "dgru" | "dark_gray_underline" => Some(Color::DarkGray.underline().prefix().to_string()), - "dgri" | "dark_gray_italic" => Some(Color::DarkGray.italic().prefix().to_string()), - "dgrd" | "dark_gray_dimmed" => Some(Color::DarkGray.dimmed().prefix().to_string()), - "dgrr" | "dark_gray_reverse" => Some(Color::DarkGray.reverse().prefix().to_string()), - - "reset" => Some("\x1b[0m".to_owned()), - - // Reference for ansi codes https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 - // Another good reference http://ascii-table.com/ansi-escape-sequences.php - - // For setting title like `echo [(char title) (pwd) (char bel)] | str collect` - "title" => Some("\x1b]2;".to_string()), // ESC]2; xterm sets window title using OSC syntax escapes - - // Ansi Erase Sequences - "clear_screen" => Some("\x1b[J".to_string()), // clears the screen - "clear_screen_from_cursor_to_end" => Some("\x1b[0J".to_string()), // clears from cursor until end of screen - "clear_screen_from_cursor_to_beginning" => Some("\x1b[1J".to_string()), // clears from cursor to beginning of screen - "cls" | "clear_entire_screen" => Some("\x1b[2J".to_string()), // clears the entire screen - "erase_line" => Some("\x1b[K".to_string()), // clears the current line - "erase_line_from_cursor_to_end" => Some("\x1b[0K".to_string()), // clears from cursor to end of line - "erase_line_from_cursor_to_beginning" => Some("\x1b[1K".to_string()), // clears from cursor to start of line - "erase_entire_line" => Some("\x1b[2K".to_string()), // clears entire line - - // Turn on/off cursor - "cursor_off" => Some("\x1b[?25l".to_string()), - "cursor_on" => Some("\x1b[?25h".to_string()), - - // Turn on/off blinking - "cursor_blink_off" => Some("\x1b[?12l".to_string()), - "cursor_blink_on" => Some("\x1b[?12h".to_string()), - - // Cursor position in ESC [ ;R where r = row and c = column - "cursor_position" => Some("\x1b[6n".to_string()), - - // Report Terminal Identity - "identity" => Some("\x1b[0c".to_string()), - - // Ansi escape only - CSI command - "csi" | "escape" | "escape_left" => Some("\x1b[".to_string()), - // OSC escape (Operating system command) - "osc" | "escape_right" => Some("\x1b]".to_string()), - // OSC string terminator - "string_terminator" | "st" | "str_term" => Some("\x1b\\".to_string()), - - // Ansi Rgb - Needs to be 32;2;r;g;b or 48;2;r;g;b - // assuming the rgb will be passed via command and no here - "rgb_fg" => Some("\x1b[38;2;".to_string()), - "rgb_bg" => Some("\x1b[48;2;".to_string()), - - // Ansi color index - Needs 38;5;idx or 48;5;idx where idx = 0 to 255 - "idx_fg" | "color_idx_fg" => Some("\x1b[38;5;".to_string()), - "idx_bg" | "color_idx_bg" => Some("\x1b[48;5;".to_string()), - - // Returns terminal size like "[;R" where r is rows and c is columns - // This should work assuming your terminal is not greater than 999x999 - "size" => Some("\x1b[s\x1b[999;999H\x1b[6n\x1b[u".to_string()), - - _ => None, - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/ansi/gradient.rs b/old_nushell/crates/nu-command/src/commands/platform/ansi/gradient.rs deleted file mode 100644 index d8433ca8f..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/ansi/gradient.rs +++ /dev/null @@ -1,326 +0,0 @@ -use crate::prelude::*; -use nu_ansi_term::{build_all_gradient_text, gradient::TargetGround, Gradient, Rgb}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tag; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "ansi gradient" - } - - fn signature(&self) -> Signature { - Signature::build("ansi gradient") - .named( - "fgstart", - SyntaxShape::String, - "foreground gradient start color in hex (0x123456)", - Some('a'), - ) - .named( - "fgend", - SyntaxShape::String, - "foreground gradient end color in hex", - Some('b'), - ) - .named( - "bgstart", - SyntaxShape::String, - "background gradient start color in hex", - Some('c'), - ) - .named( - "bgend", - SyntaxShape::String, - "background gradient end color in hex", - Some('d'), - ) - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally, draw gradients using text from column paths", - ) - } - - fn usage(&self) -> &str { - "draw text with a provided start and end code making a gradient" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "draw text in a gradient with foreground start and end colors", - example: - "echo 'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart 0x40c9ff --fgend 0xe81cff", - result: None, - }, - Example { - description: "draw text in a gradient with foreground start and end colors and background start and end colors", - example: - "echo 'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart 0x40c9ff --fgend 0xe81cff --bgstart 0xe81cff --bgend 0x40c9ff", - result: None, - }, - Example { - description: "draw text in a gradient by specifying foreground start color - end color is assumed to be black", - example: - "echo 'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart 0x40c9ff", - result: None, - }, - Example { - description: "draw text in a gradient by specifying foreground end color - start color is assumed to be black", - example: - "echo 'Hello, Nushell! This is a gradient.' | ansi gradient --fgend 0xe81cff", - result: None, - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let fgstart: Option = args.get_flag("fgstart")?; - let fgend: Option = args.get_flag("fgend")?; - let bgstart: Option = args.get_flag("bgstart")?; - let bgend: Option = args.get_flag("bgend")?; - let column_paths: Vec<_> = args.rest(0)?; - - let fgs_hex = fgstart.map(|color| Rgb::from_hex_string(color.convert_to_string())); - let fge_hex = fgend.map(|color| Rgb::from_hex_string(color.convert_to_string())); - let bgs_hex = bgstart.map(|color| Rgb::from_hex_string(color.convert_to_string())); - let bge_hex = bgend.map(|color| Rgb::from_hex_string(color.convert_to_string())); - - let result: Vec = args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag(), fgs_hex, fge_hex, bgs_hex, bge_hex) - } else { - let mut ret = v; - - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| { - action(old, old.tag(), fgs_hex, fge_hex, bgs_hex, bge_hex) - }), - )?; - } - - Ok(ret) - } - }) - .collect::, _>>()?; - - Ok(OutputStream::from_stream(result.into_iter())) -} - -fn action( - input: &Value, - tag: impl Into, - fg_start: Option, - fg_end: Option, - bg_start: Option, - bg_end: Option, -) -> Result { - let tag = tag.into(); - - match &input.value { - UntaggedValue::Primitive(Primitive::String(astring)) => { - match (fg_start, fg_end, bg_start, bg_end) { - (None, None, None, None) => { - // Error - no colors - Err(ShellError::labeled_error( - "please supply color parameters", - "please supply foreground and/or background color parameters", - Tag::unknown(), - )) - } - (None, None, None, Some(bg_end)) => { - // Error - missing bg_start, so assume black - let bg_start = Rgb::new(0, 0, 0); - let gradient = Gradient::new(bg_start, bg_end); - let gradient_string = gradient.build(astring, TargetGround::Background); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (None, None, Some(bg_start), None) => { - // Error - missing bg_end, so assume black - let bg_end = Rgb::new(0, 0, 0); - let gradient = Gradient::new(bg_start, bg_end); - let gradient_string = gradient.build(astring, TargetGround::Background); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (None, None, Some(bg_start), Some(bg_end)) => { - // Background Only - let gradient = Gradient::new(bg_start, bg_end); - let gradient_string = gradient.build(astring, TargetGround::Background); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (None, Some(fg_end), None, None) => { - // Error - missing fg_start, so assume black - let fg_start = Rgb::new(0, 0, 0); - let gradient = Gradient::new(fg_start, fg_end); - let gradient_string = gradient.build(astring, TargetGround::Foreground); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (None, Some(fg_end), None, Some(bg_end)) => { - // missing fg_start and bg_start, so assume black - let fg_start = Rgb::new(0, 0, 0); - let bg_start = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (None, Some(fg_end), Some(bg_start), None) => { - // Error - missing fg_start and bg_end - let fg_start = Rgb::new(0, 0, 0); - let bg_end = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (None, Some(fg_end), Some(bg_start), Some(bg_end)) => { - // Error - missing fg_start, so assume black - let fg_start = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), None, None, None) => { - // Error - missing fg_end, so assume black - let fg_end = Rgb::new(0, 0, 0); - let gradient = Gradient::new(fg_start, fg_end); - let gradient_string = gradient.build(astring, TargetGround::Foreground); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), None, None, Some(bg_end)) => { - // Error - missing fg_end, bg_start, so assume black - let fg_end = Rgb::new(0, 0, 0); - let bg_start = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), None, Some(bg_start), None) => { - // Error - missing fg_end, bg_end, so assume black - let fg_end = Rgb::new(0, 0, 0); - let bg_end = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), None, Some(bg_start), Some(bg_end)) => { - // Error - missing fg_end, so assume black - let fg_end = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), Some(fg_end), None, None) => { - // Foreground Only - let gradient = Gradient::new(fg_start, fg_end); - let gradient_string = gradient.build(astring, TargetGround::Foreground); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), Some(fg_end), None, Some(bg_end)) => { - // Error - missing bg_start, so assume black - let bg_start = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), Some(fg_end), Some(bg_start), None) => { - // Error - missing bg_end, so assume black - let bg_end = Rgb::new(0, 0, 0); - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - (Some(fg_start), Some(fg_end), Some(bg_start), Some(bg_end)) => { - // Foreground and Background Gradient - let fg_gradient = Gradient::new(fg_start, fg_end); - let bg_gradient = Gradient::new(bg_start, bg_end); - let gradient_string = - build_all_gradient_text(astring, fg_gradient, bg_gradient); - Ok(UntaggedValue::string(gradient_string).into_value(tag)) - } - } - } - other => { - let got = format!("got {}", other.type_name()); - - Err(ShellError::labeled_error( - "value is not string", - got, - tag.span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_ansi_term::Rgb; - use nu_protocol::UntaggedValue; - use nu_source::Tag; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - // #[test] - // fn test_stripping() { - // let input_string = - // UntaggedValue::string("\u{1b}[3;93;41mHello\u{1b}[0m \u{1b}[1;32mNu \u{1b}[1;35mWorld") - // .into_untagged_value(); - // let expected = UntaggedValue::string("Hello Nu World").into_untagged_value(); - - // let actual = action(&input_string, Tag::unknown()).unwrap(); - // assert_eq!(actual, expected); - // } - - #[test] - fn test_fg_gradient() { - let input_string = UntaggedValue::string("Hello, World!").into_untagged_value(); - let expected = UntaggedValue::string("\u{1b}[38;2;64;201;255mH\u{1b}[38;2;76;187;254me\u{1b}[38;2;89;174;254ml\u{1b}[38;2;102;160;254ml\u{1b}[38;2;115;147;254mo\u{1b}[38;2;128;133;254m,\u{1b}[38;2;141;120;254m \u{1b}[38;2;153;107;254mW\u{1b}[38;2;166;94;254mo\u{1b}[38;2;179;80;254mr\u{1b}[38;2;192;67;254ml\u{1b}[38;2;205;53;254md\u{1b}[38;2;218;40;254m!\u{1b}[0m").into_untagged_value(); - let fg_start = Rgb::from_hex_string("0x40c9ff".to_string()); - let fg_end = Rgb::from_hex_string("0xe81cff".to_string()); - let actual = action( - &input_string, - Tag::unknown(), - Some(fg_start), - Some(fg_end), - None, - None, - ) - .unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/ansi/mod.rs b/old_nushell/crates/nu-command/src/commands/platform/ansi/mod.rs deleted file mode 100644 index e7bbad5b7..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/ansi/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod command; -mod gradient; -mod strip; - -pub use command::Command as Ansi; -pub use gradient::SubCommand as AnsiGradient; -pub use strip::SubCommand as AnsiStrip; diff --git a/old_nushell/crates/nu-command/src/commands/platform/ansi/strip.rs b/old_nushell/crates/nu-command/src/commands/platform/ansi/strip.rs deleted file mode 100644 index 6e59c824e..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/ansi/strip.rs +++ /dev/null @@ -1,116 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tag; -use strip_ansi_escapes::strip; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "ansi strip" - } - - fn signature(&self) -> Signature { - Signature::build("ansi strip").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally, remove ansi sequences by column paths", - ) - } - - fn usage(&self) -> &str { - "strip ansi escape sequences from string" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "strip ansi escape sequences from string", - example: "echo [(ansi gb) 'hello' (ansi reset)] | str collect | ansi strip", - result: None, - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let column_paths: Vec<_> = args.rest(0)?; - - let result: Vec = args - .input - .map(move |v| { - if column_paths.is_empty() { - action(&v, v.tag()) - } else { - let mut ret = v; - - for path in &column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .collect::, _>>()?; - - Ok(OutputStream::from_stream(result.into_iter())) -} - -fn action(input: &Value, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(astring)) => { - let stripped_string = { - if let Ok(bytes) = strip(&astring) { - String::from_utf8_lossy(&bytes).to_string() - } else { - astring.to_string() - } - }; - - Ok(UntaggedValue::string(stripped_string).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_protocol::UntaggedValue; - use nu_source::Tag; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn test_stripping() { - let input_string = - UntaggedValue::string("\u{1b}[3;93;41mHello\u{1b}[0m \u{1b}[1;32mNu \u{1b}[1;35mWorld") - .into_untagged_value(); - let expected = UntaggedValue::string("Hello Nu World").into_untagged_value(); - - let actual = action(&input_string, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/benchmark.rs b/old_nushell/crates/nu-command/src/commands/platform/benchmark.rs deleted file mode 100644 index a27586372..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/benchmark.rs +++ /dev/null @@ -1,225 +0,0 @@ -use crate::prelude::*; -// #[cfg(feature = "rich-benchmark")] -// use heim::cpu::time; -use nu_engine::run_block; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - hir::{ - Block, CapturedBlock, ClassifiedCommand, ExternalRedirection, Group, InternalCommand, - Pipeline, - }, - Dictionary, Signature, SyntaxShape, UntaggedValue, Value, -}; -use rand::{ - distributions::{Alphanumeric, Distribution}, - thread_rng, Rng, -}; -use std::time::Instant; - -pub struct Benchmark; - -#[derive(Debug)] -struct BenchmarkArgs { - block: CapturedBlock, - passthrough: Option, -} - -impl WholeStreamCommand for Benchmark { - fn name(&self) -> &str { - "benchmark" - } - - fn signature(&self) -> Signature { - Signature::build("benchmark") - .required( - "block", - SyntaxShape::Block, - "the block to run and benchmark", - ) - .named( - "passthrough", - SyntaxShape::Block, - "Display the benchmark results and pass through the block's output", - Some('p'), - ) - } - - fn usage(&self) -> &str { - "Runs a block and returns the time it took to execute it." - } - - fn run(&self, args: CommandArgs) -> Result { - benchmark(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Benchmarks a command within a block", - example: "benchmark { sleep 500ms }", - result: None, - }, - Example { - description: "Benchmarks a command within a block and passes its output through", - example: "echo 45 | benchmark { sleep 500ms } --passthrough {}", - result: Some(vec![UntaggedValue::int(45).into()]), - }, - ] - } -} - -fn benchmark(args: CommandArgs) -> Result { - let tag = args.call_info.args.span; - let mut context = args.context.clone(); - let scope = args.scope().clone(); - - let cmd_args = BenchmarkArgs { - block: args.req(0)?, - passthrough: args.get_flag("passthrough")?, - }; - - let env = scope.get_env_vars(); - let name = generate_free_name(&env); - - scope.add_env_var(name, generate_random_env_value()); - - let start_time = Instant::now(); - - // #[cfg(feature = "rich-benchmark")] - // let start = time(); - - context.scope.enter_scope(); - let result = run_block( - &cmd_args.block.block, - &context, - args.input, - ExternalRedirection::StdoutAndStderr, - ); - - context.scope.exit_scope(); - let output = result?.into_vec(); - - // #[cfg(feature = "rich-benchmark")] - // let end = time(); - - let end_time = Instant::now(); - context.clear_errors(); - - // return basic runtime - //#[cfg(not(feature = "rich-benchmark"))] - { - let mut indexmap = IndexMap::with_capacity(1); - - let real_time = (end_time - start_time).as_nanos() as i64; - indexmap.insert("real time".to_string(), real_time); - benchmark_output(indexmap, output, cmd_args.passthrough, &tag, &mut context) - } - // return advanced stats - // #[cfg(feature = "rich-benchmark")] - // if let (Ok(start), Ok(end)) = (start, end) { - // let mut indexmap = IndexMap::with_capacity(4); - - // let real_time = into_big_int(end_time - start_time); - // indexmap.insert("real time".to_string(), real_time); - - // let user_time = into_big_int(end.user() - start.user()); - // indexmap.insert("user time".to_string(), user_time); - - // let system_time = into_big_int(end.system() - start.system()); - // indexmap.insert("system time".to_string(), system_time); - - // let idle_time = into_big_int(end.idle() - start.idle()); - // indexmap.insert("idle time".to_string(), idle_time); - - // benchmark_output(indexmap, output, passthrough, &tag, &mut context) - // } else { - // Err(ShellError::untagged_runtime_error( - // "Could not retrieve CPU time", - // )) - // } -} - -fn benchmark_output( - indexmap: IndexMap, - block_output: Output, - passthrough: Option, - tag: T, - context: &mut EvaluationContext, -) -> Result -where - T: Into + Copy, - Output: Into, -{ - let value = UntaggedValue::Row(Dictionary::from( - indexmap - .into_iter() - .map(|(k, v)| (k, UntaggedValue::duration(v).into_value(tag))) - .collect::>(), - )) - .into_value(tag); - - if let Some(time_block) = passthrough { - let benchmark_output = InputStream::one(value); - - // add autoview for an empty block - let time_block = add_implicit_autoview(time_block.block); - - context.scope.enter_scope(); - let result = run_block( - &time_block, - context, - benchmark_output, - ExternalRedirection::StdoutAndStderr, - ); - context.scope.exit_scope(); - result?; - context.clear_errors(); - - Ok(block_output.into()) - } else { - let benchmark_output = OutputStream::one(value); - Ok(benchmark_output) - } -} - -fn add_implicit_autoview(mut block: Arc) -> Arc { - if let Some(block) = std::sync::Arc::::get_mut(&mut block) { - if block.block.is_empty() { - let group = Group::new( - vec![{ - let mut commands = Pipeline::new(block.span); - commands.push(ClassifiedCommand::Internal(InternalCommand::new( - "autoview".to_string(), - block.span, - block.span, - ))); - commands - }], - block.span, - ); - block.push(group); - } - } - block -} - -fn generate_random_env_value() -> String { - let mut thread_rng = thread_rng(); - let len = thread_rng.gen_range(1..16 * 1024); - Alphanumeric - .sample_iter(&mut thread_rng) - .take(len) - .map(char::from) - .collect() -} - -fn generate_free_name(env: &indexmap::IndexMap) -> String { - let mut thread_rng = thread_rng(); - loop { - let candidate_name = format!("NU_RANDOM_VALUE_{}", thread_rng.gen::()); - if !env.contains_key(&candidate_name) { - return candidate_name; - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/clear.rs b/old_nushell/crates/nu-command/src/commands/platform/clear.rs deleted file mode 100644 index e5dde549d..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/clear.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::Signature; -use std::process::Command; - -pub struct Clear; - -impl WholeStreamCommand for Clear { - fn name(&self) -> &str { - "clear" - } - - fn signature(&self) -> Signature { - Signature::build("clear") - } - - fn usage(&self) -> &str { - "Clears the terminal." - } - - fn run(&self, _: CommandArgs) -> Result { - if cfg!(windows) { - Command::new("cmd") - .args(["/C", "cls"]) - .status() - .expect("failed to execute process"); - } else if cfg!(unix) { - Command::new("/bin/sh") - .args(["-c", "clear"]) - .status() - .expect("failed to execute process"); - } - Ok(InputStream::empty()) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Clear the screen", - example: "clear", - result: None, - }] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/du.rs b/old_nushell/crates/nu-command/src/commands/platform/du.rs deleted file mode 100644 index efc508bc6..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/du.rs +++ /dev/null @@ -1,179 +0,0 @@ -use crate::prelude::*; -use glob::*; -use nu_engine::WholeStreamCommand; -use nu_engine::{DirBuilder, DirInfo, FileInfo}; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape}; -use nu_source::Tagged; -use std::path::PathBuf; - -const NAME: &str = "du"; -const GLOB_PARAMS: MatchOptions = MatchOptions { - case_sensitive: true, - require_literal_separator: true, - require_literal_leading_dot: false, -}; - -pub struct Du; - -#[derive(Deserialize, Clone)] -pub struct DuArgs { - path: Option>, - all: bool, - deref: bool, - exclude: Option>, - #[serde(rename = "max-depth")] - max_depth: Option>, - #[serde(rename = "min-size")] - min_size: Option>, -} - -impl WholeStreamCommand for Du { - fn name(&self) -> &str { - NAME - } - - fn signature(&self) -> Signature { - Signature::build(NAME) - .optional("path", SyntaxShape::GlobPattern, "starting directory") - .switch( - "all", - "Output file sizes as well as directory sizes", - Some('a'), - ) - .switch( - "deref", - "Dereference symlinks to their targets for size", - Some('r'), - ) - .named( - "exclude", - SyntaxShape::GlobPattern, - "Exclude these file names", - Some('x'), - ) - .named( - "max-depth", - SyntaxShape::Int, - "Directory recursion limit", - Some('d'), - ) - .named( - "min-size", - SyntaxShape::Int, - "Exclude files below this size", - Some('m'), - ) - } - - fn usage(&self) -> &str { - "Find disk usage sizes of specified items." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - du(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Disk usage of the current directory", - example: "du", - result: None, - }] - } -} - -fn du(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let ctrl_c = args.ctrl_c(); - let ctrl_c_copy = ctrl_c.clone(); - - let args = DuArgs { - path: args.opt(0)?, - all: args.has_flag("all"), - deref: args.has_flag("deref"), - exclude: args.get_flag("exclude")?, - max_depth: args.get_flag("max-depth")?, - min_size: args.get_flag("min_size")?, - }; - - let exclude = args.exclude.map_or(Ok(None), move |x| { - Pattern::new(&x.item) - .map(Some) - .map_err(|e| ShellError::labeled_error(e.msg, "glob error", x.tag.clone())) - })?; - - let include_files = args.all; - let paths = match args.path { - Some(p) => { - let p = p.item.to_str().expect("Why isn't this encoded properly?"); - glob::glob_with(p, GLOB_PARAMS) - } - None => glob::glob_with("*", GLOB_PARAMS), - } - .map_err(|e| ShellError::labeled_error(e.msg, "glob error", tag.clone()))? - .filter(move |p| { - if include_files { - true - } else { - match p { - Ok(f) if f.is_dir() => true, - Err(e) if e.path().is_dir() => true, - _ => false, - } - } - }) - .map(|v| v.map_err(glob_err_into)); - - let all = args.all; - let deref = args.deref; - let max_depth = args.max_depth.map(|f| f.item); - let min_size = args.min_size.map(|f| f.item); - - let params = DirBuilder { - tag: tag.clone(), - min: min_size, - deref, - exclude, - all, - }; - - let inp = paths; - - Ok(inp - .flat_map(move |path| match path { - Ok(p) => { - let mut output = vec![]; - if p.is_dir() { - output.push(Ok(ReturnSuccess::Value( - DirInfo::new(p, ¶ms, max_depth, ctrl_c.clone()).into(), - ))); - } else if let Ok(v) = FileInfo::new(p, deref, tag.clone()) { - output.push(Ok(ReturnSuccess::Value(v.into()))); - } - - output - } - Err(e) => vec![Err(e)], - }) - .interruptible(ctrl_c_copy) - .into_action_stream()) -} - -fn glob_err_into(e: GlobError) -> ShellError { - let e = e.into_error(); - ShellError::from(e) -} - -#[cfg(test)] -mod tests { - use super::Du; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Du {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/exec.rs b/old_nushell/crates/nu-command/src/commands/platform/exec.rs deleted file mode 100644 index 429b5498c..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/exec.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; - -#[cfg(unix)] -use nu_source::Tagged; -#[cfg(unix)] -use std::path::PathBuf; - -pub struct Exec; - -#[cfg(unix)] -pub struct ExecArgs { - pub command: Tagged, - pub rest: Vec>, -} - -impl WholeStreamCommand for Exec { - fn name(&self) -> &str { - "exec" - } - - fn signature(&self) -> Signature { - Signature::build("exec") - .required("command", SyntaxShape::FilePath, "the command to execute") - .rest( - "rest", - SyntaxShape::GlobPattern, - "any additional arguments for the command", - ) - } - - fn usage(&self) -> &str { - "Execute a command, replacing the current process." - } - - fn extra_usage(&self) -> &str { - "Currently supported only on Unix-based systems." - } - - fn run(&self, args: CommandArgs) -> Result { - exec(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Execute external 'ps aux' tool", - example: "exec ps aux", - result: None, - }, - Example { - description: "Execute 'nautilus'", - example: "exec nautilus", - result: None, - }, - ] - } -} - -#[cfg(unix)] -fn exec(args: CommandArgs) -> Result { - use std::os::unix::process::CommandExt; - use std::process::Command; - - let name = args.call_info.name_tag.clone(); - - let args = ExecArgs { - command: args.req(0)?, - rest: args.rest(1)?, - }; - - let mut command = Command::new(args.command.item); - for tagged_arg in args.rest { - command.arg(tagged_arg.item); - } - - let err = command.exec(); // this replaces our process, should not return - - Err(ShellError::labeled_error( - "Error on exec", - err.to_string(), - &name, - )) -} - -#[cfg(not(unix))] -fn exec(args: CommandArgs) -> Result { - Err(ShellError::labeled_error( - "Error on exec", - "exec is not supported on your platform", - &args.call_info.name_tag, - )) -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/kill.rs b/old_nushell/crates/nu-command/src/commands/platform/kill.rs deleted file mode 100644 index 2f508a1a2..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/kill.rs +++ /dev/null @@ -1,140 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; -use std::process::{Command, Stdio}; - -pub struct Kill; - -impl WholeStreamCommand for Kill { - fn name(&self) -> &str { - "kill" - } - - fn signature(&self) -> Signature { - let signature = Signature::build("kill") - .required( - "pid", - SyntaxShape::Int, - "process id of process that is to be killed", - ) - .rest("rest", SyntaxShape::Int, "rest of processes to kill") - .switch("force", "forcefully kill the process", Some('f')) - .switch("quiet", "won't print anything to the console", Some('q')); - - if cfg!(windows) { - return signature; - } - - signature.named( - "signal", - SyntaxShape::Int, - "signal decimal number to be sent instead of the default 15 (unsupported on Windows)", - Some('s'), - ) - } - - fn usage(&self) -> &str { - "Kill a process using the process id." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - kill(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Kill the pid using the most memory", - example: "ps | sort-by mem | last | kill $it.pid", - result: None, - }, - Example { - description: "Force kill a given pid", - example: "kill --force 12345", - result: None, - }, - Example { - description: "Send INT signal", - example: "kill -s 2 12345", - result: None, - }, - ] - } -} - -fn kill(args: CommandArgs) -> Result { - let pid: Tagged = args.req(0)?; - let rest: Vec> = args.rest(1)?; - let force: Option> = args.get_flag("force")?; - let quiet: bool = args.has_flag("quiet"); - let signal: Option> = args.get_flag("signal")?; - - let mut cmd = if cfg!(windows) { - let mut cmd = Command::new("taskkill"); - - if matches!(force, Some(Tagged { item: true, .. })) { - cmd.arg("/F"); - } - - cmd.arg("/PID"); - cmd.arg(pid.item().to_string()); - - // each pid must written as `/PID 0` otherwise - // taskkill will act as `killall` unix command - for id in &rest { - cmd.arg("/PID"); - cmd.arg(id.item().to_string()); - } - - cmd - } else { - let mut cmd = Command::new("kill"); - - if matches!(force, Some(Tagged { item: true, .. })) { - if let Some(signal_value) = signal { - return Err(ShellError::labeled_error_with_secondary( - "mixing force and signal options is not supported", - "signal option", - signal_value.tag(), - "force option", - force.expect("internal error: expected value").tag(), - )); - } - cmd.arg("-9"); - } else if let Some(signal_value) = signal { - cmd.arg(format!("-{}", signal_value.item())); - } - - cmd.arg(pid.item().to_string()); - - cmd.args(rest.iter().map(move |id| id.item().to_string())); - - cmd - }; - - // pipe everything to null - if quiet { - cmd.stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()); - } - - cmd.status().expect("failed to execute shell command"); - - Ok(ActionStream::empty()) -} - -#[cfg(test)] -mod tests { - use super::Kill; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Kill {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/mod.rs b/old_nushell/crates/nu-command/src/commands/platform/mod.rs deleted file mode 100644 index 03734919b..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -mod ansi; -mod benchmark; -mod clear; -mod du; -mod exec; -mod kill; -mod pwd; -mod run_external; -mod sleep; -mod termsize; -mod which_; - -pub use ansi::*; -pub use benchmark::Benchmark; -pub use clear::Clear; -pub use du::Du; -pub use exec::Exec; -pub use kill::Kill; -pub use pwd::Pwd; -pub use run_external::RunExternalCommand; -pub use sleep::Sleep; -pub use termsize::TermSize; -pub use which_::Which; diff --git a/old_nushell/crates/nu-command/src/commands/platform/pwd.rs b/old_nushell/crates/nu-command/src/commands/platform/pwd.rs deleted file mode 100644 index a9965ec93..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/pwd.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::Signature; - -pub struct Pwd; - -impl WholeStreamCommand for Pwd { - fn name(&self) -> &str { - "pwd" - } - - fn signature(&self) -> Signature { - Signature::build("pwd") - } - - fn usage(&self) -> &str { - "Output the current working directory." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - pwd(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Print the current working directory", - example: "pwd", - result: None, - }] - } -} - -pub fn pwd(args: CommandArgs) -> Result { - let shell_manager = args.shell_manager(); - - shell_manager.pwd(args) -} - -#[cfg(test)] -mod tests { - use super::Pwd; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Pwd {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/run_external.rs b/old_nushell/crates/nu-command/src/commands/platform/run_external.rs deleted file mode 100644 index ce61f999b..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/run_external.rs +++ /dev/null @@ -1,181 +0,0 @@ -use crate::classified::external; -use crate::prelude::*; - -use derive_new::new; -use std::path::PathBuf; - -use nu_engine::WholeStreamCommand; -use nu_engine::{evaluate_baseline_expr, shell::CdArgs}; -use nu_errors::ShellError; -use nu_path::{canonicalize, trim_trailing_slash}; -use nu_protocol::{ - hir::{ExternalArgs, ExternalCommand, SpannedExpression}, - Primitive, UntaggedValue, -}; -use nu_protocol::{Signature, SyntaxShape}; -use nu_source::Tagged; - -#[derive(new)] -pub struct RunExternalCommand { - /// Whether or not nushell is being used in an interactive context - pub(crate) interactive: bool, -} - -fn spanned_expression_to_string( - expr: SpannedExpression, - ctx: &EvaluationContext, -) -> Result { - let value = evaluate_baseline_expr(&expr, ctx)?; - - if let UntaggedValue::Primitive(Primitive::String(s)) = value.value { - Ok(s) - } else { - Err(ShellError::labeled_error( - "Expected string for command name", - "expected string", - expr.span, - )) - } -} - -impl WholeStreamCommand for RunExternalCommand { - fn name(&self) -> &str { - "run_external" - } - - fn signature(&self) -> Signature { - Signature::build(self.name()).rest("rest", SyntaxShape::Any, "external command arguments") - } - - fn usage(&self) -> &str { - "Runs external command (not a nushell builtin)" - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Run the external echo command", - example: "run_external echo 'nushell'", - result: None, - }] - } - - fn is_private(&self) -> bool { - true - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let positionals = args.call_info.args.positional.clone().ok_or_else(|| { - ShellError::untagged_runtime_error("positional arguments unexpectedly empty") - })?; - - let mut positionals = positionals.into_iter(); - - let external_redirection = args.call_info.args.external_redirection; - - let expr = positionals.next().ok_or_else(|| { - ShellError::untagged_runtime_error("run_external called with no arguments") - })?; - - let name = spanned_expression_to_string(expr, &args.context)?; - - let mut external_context = args.context.clone(); - - let is_interactive = self.interactive; - - let command = ExternalCommand { - name, - name_tag: args.call_info.name_tag.clone(), - args: ExternalArgs { - list: positionals.collect(), - span: args.call_info.args.span, - }, - }; - - // If we're in interactive mode, we will "auto cd". That is, instead of interpreting - // this as an external command, we will see it as a path and `cd` into it. - if is_interactive { - if let Some(path) = maybe_autocd_dir(&command, &mut external_context) { - let cd_args = CdArgs { - path: Some(Tagged { - item: PathBuf::from(path), - tag: args.call_info.name_tag.clone(), - }), - }; - - let result = external_context - .shell_manager() - .cd(cd_args, args.call_info.name_tag); - - return Ok(result?.into_action_stream()); - } - } - - let input = args.input; - let result = external::run_external_command( - command, - &mut external_context, - input, - external_redirection, - ); - - // When externals return, don't let them mess up the ansi escapes - #[cfg(windows)] - { - let _ = nu_ansi_term::enable_ansi_support(); - } - - Ok(result?.into_action_stream()) - } -} - -#[allow(unused_variables)] -fn maybe_autocd_dir(cmd: &ExternalCommand, ctx: &mut EvaluationContext) -> Option { - // We will "auto cd" if - // - the command name ends in a path separator, or - // - it's not a command on the path and no arguments were given. - let name = &cmd.name; - ctx.sync_path_to_env(); - let path_name = if name.ends_with(std::path::is_separator) - || (cmd.args.is_empty() - && PathBuf::from(name).is_dir() - && canonicalize(name).is_ok() - && !ctx.host().lock().is_external_cmd(name)) - { - Some(trim_trailing_slash(name)) - } else { - None - }; - - path_name.map(|name| { - #[cfg(windows)] - { - if name.ends_with(':') { - // This looks like a drive shortcut. We need to a) switch drives and b) go back to the previous directory we were viewing on that drive - // But first, we need to save where we are now - let current_path = ctx.shell_manager().path(); - - let split_path: Vec<_> = current_path.split(':').collect(); - if split_path.len() > 1 { - ctx.windows_drives_previous_cwd() - .lock() - .insert(split_path[0].to_string(), current_path); - } - - let name = name.to_uppercase(); - let new_drive: Vec<_> = name.split(':').collect(); - - if let Some(val) = ctx.windows_drives_previous_cwd().lock().get(new_drive[0]) { - val.to_string() - } else { - name - } - } else { - name.to_string() - } - } - #[cfg(not(windows))] - { - name.to_string() - } - }) -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/sleep.rs b/old_nushell/crates/nu-command/src/commands/platform/sleep.rs deleted file mode 100644 index 9e86d1d72..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/sleep.rs +++ /dev/null @@ -1,132 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use std::{ - sync::atomic::Ordering, - thread, - time::{Duration, Instant}, -}; - -const CTRL_C_CHECK_INTERVAL: Duration = Duration::from_millis(100); - -pub struct Sleep; - -impl WholeStreamCommand for Sleep { - fn name(&self) -> &str { - "sleep" - } - - fn signature(&self) -> Signature { - Signature::build("sleep") - .required("duration", SyntaxShape::Duration, "time to sleep") - .rest("rest", SyntaxShape::Duration, "additional time") - } - - fn usage(&self) -> &str { - "Delay for a specified amount of time." - } - - fn run(&self, args: CommandArgs) -> Result { - let ctrl_c = args.ctrl_c(); - - let duration: Tagged = args.req(0)?; - let rest: Vec> = args.rest(1)?; - - let total_dur = Duration::from_nanos(if duration.item > 0 { - duration.item as u64 - } else { - 0 - }) + rest - .iter() - .map(|val| Duration::from_nanos(if val.item > 0 { val.item as u64 } else { 0 })) - .sum::(); - - //SleepHandler::new(total_dur, ctrl_c); - // this is necessary because the following 2 commands gave different results: - // `echo | sleep 1sec` - nothing - // `sleep 1sec` - table with 0 elements - - Ok(SleepIterator::new(total_dur, ctrl_c).into_output_stream()) - - // if input.is_empty() { - // Ok(OutputStream::empty()) - // } else { - // Ok(input.into()) - // } - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Sleep for 1sec", - example: "sleep 1sec", - result: None, - }, - Example { - description: "Sleep for 3sec", - example: "sleep 1sec 1sec 1sec", - result: None, - }, - Example { - description: "Send output after 1sec", - example: "sleep 1sec; echo done", - result: Some(vec![UntaggedValue::string("done").into()]), - }, - ] - } -} - -struct SleepIterator { - total_dur: Duration, - ctrl_c: Arc, -} - -impl SleepIterator { - pub fn new(total_dur: Duration, ctrl_c: Arc) -> Self { - Self { total_dur, ctrl_c } - } -} - -impl Iterator for SleepIterator { - type Item = Value; - - fn next(&mut self) -> Option { - let start = Instant::now(); - loop { - thread::sleep(CTRL_C_CHECK_INTERVAL); - if start.elapsed() >= self.total_dur { - break; - } - - if self.ctrl_c.load(Ordering::SeqCst) { - break; - } - } - - None - } -} - -#[cfg(test)] -mod tests { - use super::Sleep; - use nu_errors::ShellError; - use std::time::Instant; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - let start = Instant::now(); - let results = test_examples(Sleep {}); - let elapsed = start.elapsed(); - println!("{:?}", elapsed); - // only examples with actual output are run - assert!(elapsed >= std::time::Duration::from_secs(1)); - assert!(elapsed < std::time::Duration::from_secs(2)); - - results - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/termsize.rs b/old_nushell/crates/nu-command/src/commands/platform/termsize.rs deleted file mode 100644 index 482857bf3..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/termsize.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::prelude::*; -use indexmap::IndexMap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Signature, UntaggedValue}; - -pub struct TermSize; - -impl WholeStreamCommand for TermSize { - fn name(&self) -> &str { - "term size" - } - - fn signature(&self) -> Signature { - Signature::build("term size") - .switch("wide", "Report only the width of the terminal", Some('w')) - .switch("tall", "Report only the height of the terminal", Some('t')) - } - - fn usage(&self) -> &str { - "Returns the terminal size as W H" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let wide = args.has_flag("wide"); - let tall = args.has_flag("tall"); - - let size = term_size::dimensions(); - match size { - Some((w, h)) => { - if wide && !tall { - Ok(ActionStream::one( - UntaggedValue::int(w as i64).into_value(tag), - )) - } else if !wide && tall { - Ok(ActionStream::one( - UntaggedValue::int(h as i64).into_value(tag), - )) - } else { - let mut indexmap = IndexMap::with_capacity(2); - indexmap.insert( - "width".to_string(), - UntaggedValue::int(w as i64).into_value(&tag), - ); - indexmap.insert( - "height".to_string(), - UntaggedValue::int(h as i64).into_value(&tag), - ); - let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag); - Ok(ActionStream::one(value)) - } - } - _ => Ok(ActionStream::one( - UntaggedValue::string("0 0".to_string()).into_value(tag), - )), - } - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Return the width height of the terminal", - example: "term size", - result: None, - }, - Example { - description: "Return the width of the terminal", - example: "term size -w", - result: None, - }, - Example { - description: "Return the height (t for tall) of the terminal", - example: "term size -t", - result: None, - }, - ] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/platform/which_.rs b/old_nushell/crates/nu-command/src/commands/platform/which_.rs deleted file mode 100644 index 45a0a3f9e..000000000 --- a/old_nushell/crates/nu-command/src/commands/platform/which_.rs +++ /dev/null @@ -1,239 +0,0 @@ -use crate::prelude::*; -use indexmap::map::IndexMap; -use log::trace; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct Which; - -impl WholeStreamCommand for Which { - fn name(&self) -> &str { - "which" - } - - fn signature(&self) -> Signature { - Signature::build("which") - .required("application", SyntaxShape::String, "application") - .rest("rest", SyntaxShape::String, "additional applications") - .switch("all", "list all executables", Some('a')) - } - - fn usage(&self) -> &str { - "Finds a program file, alias or custom command." - } - - fn run(&self, args: CommandArgs) -> Result { - which(args) - } -} - -/// Shortcuts for creating an entry to the output table -fn entry(arg: impl Into, path: Value, builtin: bool, tag: Tag) -> Value { - let mut map = IndexMap::new(); - map.insert( - "arg".to_string(), - UntaggedValue::Primitive(Primitive::String(arg.into())).into_value(tag.clone()), - ); - map.insert("path".to_string(), path); - map.insert( - "builtin".to_string(), - UntaggedValue::boolean(builtin).into_value(tag.clone()), - ); - - UntaggedValue::row(map).into_value(tag) -} - -macro_rules! create_entry { - ($arg:expr, $path:expr, $tag:expr, $is_builtin:expr) => { - entry( - $arg.clone(), - UntaggedValue::Primitive(Primitive::String($path.to_string())).into_value($tag.clone()), - $is_builtin, - $tag, - ) - }; -} - -fn get_entries_in_aliases(scope: &Scope, name: &str, tag: Tag) -> Vec { - let aliases = scope - .get_aliases_with_name(name) - .unwrap_or_default() - .into_iter() - .map(|spans| { - spans - .into_iter() - .map(|span| span.item) - .collect::>() - .join(" ") - }) - .map(|alias| { - create_entry!( - name, - format!("Nushell alias: {}", alias), - tag.clone(), - false - ) - }) - .collect::>(); - trace!("Found {} aliases", aliases.len()); - aliases -} - -fn get_entries_in_custom_command(scope: &Scope, name: &str, tag: Tag) -> Vec { - scope - .get_custom_commands_with_name(name) - .unwrap_or_default() - .into_iter() - .map(|_| create_entry!(name, "Nushell custom command", tag.clone(), false)) - .collect() -} - -fn get_entry_in_commands(scope: &Scope, name: &str, tag: Tag) -> Option { - if scope.has_command(name) { - Some(create_entry!(name, "Nushell built-in command", tag, true)) - } else { - None - } -} - -fn get_entries_in_nu( - scope: &Scope, - name: &str, - tag: Tag, - skip_after_first_found: bool, -) -> Vec { - let mut all_entries = vec![]; - - all_entries.extend(get_entries_in_aliases(scope, name, tag.clone())); - if !all_entries.is_empty() && skip_after_first_found { - return all_entries; - } - - all_entries.extend(get_entries_in_custom_command(scope, name, tag.clone())); - if !all_entries.is_empty() && skip_after_first_found { - return all_entries; - } - - if let Some(entry) = get_entry_in_commands(scope, name, tag) { - all_entries.push(entry); - } - - all_entries -} - -#[allow(unused)] -macro_rules! entry_path { - ($arg:expr, $path:expr, $tag:expr) => { - entry( - $arg.clone(), - UntaggedValue::Primitive(Primitive::FilePath($path)).into_value($tag.clone()), - false, - $tag, - ) - }; -} - -#[cfg(feature = "which")] -fn get_first_entry_in_path(item: &str, tag: Tag) -> Option { - which::which(item) - .map(|path| entry_path!(item, path, tag)) - .ok() -} - -#[cfg(not(feature = "which"))] -fn get_first_entry_in_path(_: &str, _: Tag) -> Option { - None -} - -#[cfg(feature = "which")] -fn get_all_entries_in_path(item: &str, tag: Tag) -> Vec { - which::which_all(&item) - .map(|iter| { - iter.map(|path| entry_path!(item, path, tag.clone())) - .collect() - }) - .unwrap_or_default() -} -#[cfg(not(feature = "which"))] -fn get_all_entries_in_path(_: &str, _: Tag) -> Vec { - vec![] -} - -#[derive(Debug)] -struct WhichArgs { - applications: Vec>, - all: bool, -} - -fn which_single(application: Tagged, all: bool, scope: &Scope) -> Vec { - let (external, prog_name) = if application.starts_with('^') { - (true, application.item[1..].to_string()) - } else { - (false, application.item.clone()) - }; - - //If prog_name is an external command, don't search for nu-specific programs - //If all is false, we can save some time by only searching for the first matching - //program - //This match handles all different cases - match (all, external) { - (true, true) => get_all_entries_in_path(&prog_name, application.tag), - (true, false) => { - let mut output: Vec = vec![]; - output.extend(get_entries_in_nu( - scope, - &prog_name, - application.tag.clone(), - false, - )); - output.extend(get_all_entries_in_path(&prog_name, application.tag)); - output - } - (false, true) => { - if let Some(entry) = get_first_entry_in_path(&prog_name, application.tag) { - return vec![entry]; - } - vec![] - } - (false, false) => { - let nu_entries = get_entries_in_nu(scope, &prog_name, application.tag.clone(), true); - if !nu_entries.is_empty() { - return vec![nu_entries[0].clone()]; - } else if let Some(entry) = get_first_entry_in_path(&prog_name, application.tag) { - return vec![entry]; - } - vec![] - } - } -} - -fn which(args: CommandArgs) -> Result { - let which_args = WhichArgs { - applications: args.rest_with_minimum(0, 1)?, - all: args.has_flag("all"), - }; - - let mut output = vec![]; - - for app in which_args.applications { - let values = which_single(app, which_args.all, args.scope()); - output.extend(values); - } - - Ok(output.into_iter().into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Which; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Which {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/random/bool.rs b/old_nushell/crates/nu-command/src/commands/random/bool.rs deleted file mode 100644 index a7c8c3ed5..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/bool.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; -use rand::prelude::{thread_rng, Rng}; - -pub struct SubCommand; - -pub struct BoolArgs { - bias: Option>, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "random bool" - } - - fn signature(&self) -> Signature { - Signature::build("random bool").named( - "bias", - SyntaxShape::Number, - "Adjusts the probability of a \"true\" outcome", - Some('b'), - ) - } - - fn usage(&self) -> &str { - "Generate a random boolean value" - } - - fn run(&self, args: CommandArgs) -> Result { - bool_command(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Generate a random boolean value", - example: "random bool", - result: None, - }, - Example { - description: "Generate a random boolean value with a 75% chance of \"true\"", - example: "random bool --bias 0.75", - result: None, - }, - ] - } -} - -pub fn bool_command(args: CommandArgs) -> Result { - let cmd_args = BoolArgs { - bias: args.get_flag("bias")?, - }; - - let mut probability = 0.5; - - if let Some(prob) = cmd_args.bias { - probability = *prob as f64; - - let probability_is_valid = (0.0..=1.0).contains(&probability); - - if !probability_is_valid { - return Err(ShellError::labeled_error( - "The probability is invalid", - "invalid probability", - prob.span(), - )); - } - } - - let mut rng = thread_rng(); - let bool_result: bool = rng.gen_bool(probability); - - Ok(OutputStream::one(UntaggedValue::boolean(bool_result))) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/random/chars.rs b/old_nushell/crates/nu-command/src/commands/random/chars.rs deleted file mode 100644 index 986c8256b..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/chars.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; -use rand::distributions::{Alphanumeric, Distribution}; -use rand::thread_rng; - -pub struct SubCommand; - -pub struct CharsArgs { - length: Option>, -} - -const DEFAULT_CHARS_LENGTH: u32 = 25; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "random chars" - } - - fn signature(&self) -> Signature { - Signature::build("random chars").named( - "length", - SyntaxShape::Int, - "Number of chars", - Some('l'), - ) - } - - fn usage(&self) -> &str { - "Generate random chars" - } - - fn run(&self, args: CommandArgs) -> Result { - chars(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Generate random chars", - example: "random chars", - result: None, - }, - Example { - description: "Generate random chars with specified length", - example: "random chars -l 20", - result: None, - }, - ] - } -} - -pub fn chars(args: CommandArgs) -> Result { - let cmd_args = CharsArgs { - length: args.get_flag("length")?, - }; - - let chars_length = cmd_args.length.map_or(DEFAULT_CHARS_LENGTH, |l| l.item); - let mut rng = thread_rng(); - - let random_string: String = Alphanumeric - .sample_iter(&mut rng) - .take(chars_length as usize) - .map(char::from) - .collect(); - - Ok(OutputStream::one(UntaggedValue::string(random_string))) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/random/command.rs b/old_nushell/crates/nu-command/src/commands/random/command.rs deleted file mode 100644 index af4f70922..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/command.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "random" - } - - fn signature(&self) -> Signature { - Signature::build("random") - } - - fn usage(&self) -> &str { - "Generate random values." - } - - fn run(&self, args: CommandArgs) -> Result { - Ok(OutputStream::one(UntaggedValue::string(get_full_help( - &Command, - args.scope(), - )))) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/random/decimal.rs b/old_nushell/crates/nu-command/src/commands/random/decimal.rs deleted file mode 100644 index fbef27800..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/decimal.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Range, Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; -use rand::prelude::{thread_rng, Rng}; -use std::cmp::Ordering; - -pub struct SubCommand; - -pub struct DecimalArgs { - range: Option>, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "random decimal" - } - - fn signature(&self) -> Signature { - Signature::build("random decimal").optional("range", SyntaxShape::Range, "Range of values") - } - - fn usage(&self) -> &str { - "Generate a random decimal within a range [min..max]" - } - - fn run(&self, args: CommandArgs) -> Result { - decimal(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Generate a default decimal value between 0 and 1", - example: "random decimal", - result: None, - }, - Example { - description: "Generate a random decimal less than or equal to 500", - example: "random decimal ..500", - result: None, - }, - Example { - description: "Generate a random decimal greater than or equal to 100000", - example: "random decimal 100000..", - result: None, - }, - Example { - description: "Generate a random decimal between 1.0 and 1.1", - example: "random decimal 1.0..1.1", - result: None, - }, - ] - } -} - -pub fn decimal(args: CommandArgs) -> Result { - let cmd_args = DecimalArgs { - range: args.opt(0)?, - }; - - let (min, max) = if let Some(range) = &cmd_args.range { - (range.item.min_f64()?, range.item.max_f64()?) - } else { - (0.0, 1.0) - }; - - match min.partial_cmp(&max) { - Some(Ordering::Greater) => Err(ShellError::labeled_error( - format!("Invalid range {}..{}", min, max), - "expected a valid range", - cmd_args - .range - .expect("Unexpected ordering error in random decimal") - .span(), - )), - Some(Ordering::Equal) => Ok(OutputStream::one(UntaggedValue::decimal_from_float( - min, - Span::new(64, 64), - ))), - _ => { - let mut thread_rng = thread_rng(); - let result: f64 = thread_rng.gen_range(min..max); - - Ok(OutputStream::one(UntaggedValue::decimal_from_float( - result, - Span::new(64, 64), - ))) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/random/dice.rs b/old_nushell/crates/nu-command/src/commands/random/dice.rs deleted file mode 100644 index 1b13d2f29..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/dice.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; -use rand::prelude::{thread_rng, Rng}; - -pub struct SubCommand; - -pub struct DiceArgs { - dice: Option>, - sides: Option>, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "random dice" - } - - fn signature(&self) -> Signature { - Signature::build("random dice") - .named( - "dice", - SyntaxShape::Int, - "The amount of dice being rolled", - Some('d'), - ) - .named( - "sides", - SyntaxShape::Int, - "The amount of sides a die has", - Some('s'), - ) - } - - fn usage(&self) -> &str { - "Generate a random dice roll" - } - - fn run(&self, args: CommandArgs) -> Result { - dice(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Roll 1 dice with 6 sides each", - example: "random dice", - result: None, - }, - Example { - description: "Roll 10 dice with 12 sides each", - example: "random dice -d 10 -s 12", - result: None, - }, - ] - } -} - -pub fn dice(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let cmd_args = DiceArgs { - dice: args.get_flag("dice")?, - sides: args.get_flag("sides")?, - }; - - let dice = if let Some(dice_tagged) = cmd_args.dice { - *dice_tagged - } else { - 1 - }; - - let sides = if let Some(sides_tagged) = cmd_args.sides { - *sides_tagged - } else { - 6 - }; - - let iter = (0..dice).map(move |_| { - let mut thread_rng = thread_rng(); - UntaggedValue::int(thread_rng.gen_range(1..sides + 1)).into_value(tag.clone()) - }); - - Ok(iter.into_output_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/random/integer.rs b/old_nushell/crates/nu-command/src/commands/random/integer.rs deleted file mode 100644 index 39569472b..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/integer.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Range, Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; -use rand::prelude::{thread_rng, Rng}; -use std::cmp::Ordering; - -pub struct SubCommand; - -pub struct IntegerArgs { - range: Option>, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "random integer" - } - - fn signature(&self) -> Signature { - Signature::build("random integer").optional("range", SyntaxShape::Range, "Range of values") - } - - fn usage(&self) -> &str { - "Generate a random integer [min..max]" - } - - fn run(&self, args: CommandArgs) -> Result { - integer(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Generate an unconstrained random integer", - example: "random integer", - result: None, - }, - Example { - description: "Generate a random integer less than or equal to 500", - example: "random integer ..500", - result: None, - }, - Example { - description: "Generate a random integer greater than or equal to 100000", - example: "random integer 100000..", - result: None, - }, - Example { - description: "Generate a random integer between 1 and 10", - example: "random integer 1..10", - result: None, - }, - ] - } -} - -pub fn integer(args: CommandArgs) -> Result { - let cmd_args = IntegerArgs { - range: args.opt(0)?, - }; - - let (min, max) = if let Some(range) = &cmd_args.range { - (range.min_i64()?, range.max_i64()?) - } else { - (0, i64::MAX) - }; - - match min.cmp(&max) { - Ordering::Greater => Err(ShellError::labeled_error( - format!("Invalid range {}..{}", min, max), - "expected a valid range", - cmd_args - .range - .expect("Unexpected ordering error in random integer") - .span(), - )), - Ordering::Equal => Ok(OutputStream::one( - UntaggedValue::int(min).into_value(Tag::unknown()), - )), - _ => { - let mut thread_rng = thread_rng(); - // add 1 to max, because gen_range is right-exclusive - let max = max.saturating_add(1); - let result: i64 = thread_rng.gen_range(min..max); - - Ok(OutputStream::one( - UntaggedValue::int(result).into_value(Tag::unknown()), - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/random/mod.rs b/old_nushell/crates/nu-command/src/commands/random/mod.rs deleted file mode 100644 index 5decd9475..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub mod command; - -pub mod bool; -pub mod chars; -pub mod decimal; -pub mod dice; -pub mod integer; -#[cfg(feature = "uuid_crate")] -pub mod uuid; - -pub use command::Command as Random; - -pub use self::bool::SubCommand as RandomBool; -pub use chars::SubCommand as RandomChars; -pub use decimal::SubCommand as RandomDecimal; -pub use dice::SubCommand as RandomDice; -pub use integer::SubCommand as RandomInteger; -#[cfg(feature = "uuid_crate")] -pub use uuid::SubCommand as RandomUUID; diff --git a/old_nushell/crates/nu-command/src/commands/random/uuid.rs b/old_nushell/crates/nu-command/src/commands/random/uuid.rs deleted file mode 100644 index 47d01a3ed..000000000 --- a/old_nushell/crates/nu-command/src/commands/random/uuid.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::Signature; -use uuid_crate::Uuid; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "random uuid" - } - - fn signature(&self) -> Signature { - Signature::build("random uuid") - } - - fn usage(&self) -> &str { - "Generate a random uuid4 string" - } - - fn run(&self, args: CommandArgs) -> Result { - uuid(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Generate a random uuid4 string", - example: "random uuid", - result: None, - }] - } -} - -pub fn uuid(_args: CommandArgs) -> Result { - let uuid_4 = Uuid::new_v4().to_hyphenated().to_string(); - - Ok(OutputStream::one(uuid_4)) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/shells/command.rs b/old_nushell/crates/nu-command/src/commands/shells/command.rs deleted file mode 100644 index 8f44416f0..000000000 --- a/old_nushell/crates/nu-command/src/commands/shells/command.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, TaggedDictBuilder}; -use std::sync::atomic::Ordering; - -pub struct Shells; - -impl WholeStreamCommand for Shells { - fn name(&self) -> &str { - "shells" - } - - fn signature(&self) -> Signature { - Signature::build("shells") - } - - fn usage(&self) -> &str { - "Display the list of current shells." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(shells(args)) - } -} - -fn shells(args: CommandArgs) -> ActionStream { - let mut shells_out = VecDeque::new(); - let shell_manager = args.shell_manager(); - let tag = args.call_info.name_tag; - let active_index = shell_manager.current_shell.load(Ordering::SeqCst); - - for (index, shell) in shell_manager.shells.lock().iter().enumerate() { - let mut dict = TaggedDictBuilder::new(&tag); - - if index == active_index { - dict.insert_untagged("active", true); - } else { - dict.insert_untagged("active", false); - } - dict.insert_untagged("name", shell.name()); - dict.insert_untagged("path", shell.path()); - - shells_out.push_back(dict.into_value()); - } - - shells_out.into() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Shells; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Shells {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/shells/enter.rs b/old_nushell/crates/nu-command/src/commands/shells/enter.rs deleted file mode 100644 index 9736a666c..000000000 --- a/old_nushell/crates/nu-command/src/commands/shells/enter.rs +++ /dev/null @@ -1,163 +0,0 @@ -use crate::prelude::*; -use nu_engine::UnevaluatedCallInfo; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::hir::ExternalRedirection; -use nu_protocol::{ - CommandAction, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tagged; -use std::path::PathBuf; - -pub struct Enter; - -impl WholeStreamCommand for Enter { - fn name(&self) -> &str { - "enter" - } - - fn signature(&self) -> Signature { - Signature::build("enter") - .required( - "location", - SyntaxShape::FilePath, - "the location to create a new shell from", - ) - .named( - "encoding", - SyntaxShape::String, - "encoding to use to open file", - Some('e'), - ) - } - - fn usage(&self) -> &str { - "Create a new shell and begin at this path." - } - - fn extra_usage(&self) -> &str { - r#"Multiple encodings are supported for reading text files by using -the '--encoding ' parameter. Here is an example of a few: -big5, euc-jp, euc-kr, gbk, iso-8859-1, utf-16, cp1252, latin5 - -For a more complete list of encodings please refer to the encoding_rs -documentation link at https://docs.rs/encoding_rs/0.8.28/encoding_rs/#statics"# - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - enter(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Enter a path as a new shell", - example: "enter ../projectB", - result: None, - }, - Example { - description: "Enter a file as a new shell", - example: "enter package.json", - result: None, - }, - Example { - description: "Enters file with iso-8859-1 encoding", - example: "enter file.csv --encoding iso-8859-1", - result: None, - }, - ] - } -} - -fn enter(args: CommandArgs) -> Result { - let head = args.call_info.args.head.clone(); - let context = args.context.clone(); - let scope = args.scope().clone(); - let path = args.context.shell_manager().path(); - - let location: Tagged = args.req(0)?; - let encoding: Option> = args.get_flag("encoding")?; - let location_string = location.display().to_string(); - - if location.is_dir() { - Ok(ActionStream::one(ReturnSuccess::action( - CommandAction::EnterShell(location_string), - ))) - } else { - // If it's a file, attempt to open the file as a value and enter it - let cwd = path; - - let full_path = std::path::PathBuf::from(cwd); - let span = location.span(); - - let (file_extension, tagged_contents) = crate::commands::filesystem::open::fetch( - &full_path, - &PathBuf::from(location_string), - span, - encoding, - )?; - - match tagged_contents.value { - UntaggedValue::Primitive(Primitive::String(_)) => { - if let Some(extension) = file_extension { - let command_name = format!("from {}", extension); - if let Some(converter) = scope.get_command(&command_name) { - let tag = tagged_contents.tag.clone(); - let new_args = CommandArgs { - context, - call_info: UnevaluatedCallInfo { - args: nu_protocol::hir::Call { - head, - positional: None, - named: None, - span: Span::unknown(), - external_redirection: ExternalRedirection::Stdout, - }, - name_tag: tag.clone(), - }, - input: InputStream::one(tagged_contents), - }; - let mut result = converter.run(new_args)?; - let result_vec: Vec = result.drain_vec(); - Ok(result_vec - .into_iter() - .map(move |res| { - let Value { value, .. } = res; - Ok(ReturnSuccess::Action(CommandAction::EnterValueShell( - Value { - value, - tag: tag.clone(), - }, - ))) - }) - .into_action_stream()) - } else { - Ok(ActionStream::one(ReturnSuccess::action( - CommandAction::EnterValueShell(tagged_contents), - ))) - } - } else { - Ok(ActionStream::one(ReturnSuccess::action( - CommandAction::EnterValueShell(tagged_contents), - ))) - } - } - _ => Ok(ActionStream::one(ReturnSuccess::action( - CommandAction::EnterValueShell(tagged_contents), - ))), - } - } -} - -#[cfg(test)] -mod tests { - use super::Enter; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Enter {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/shells/exit.rs b/old_nushell/crates/nu-command/src/commands/shells/exit.rs deleted file mode 100644 index cc6754d15..000000000 --- a/old_nushell/crates/nu-command/src/commands/shells/exit.rs +++ /dev/null @@ -1,73 +0,0 @@ -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape}; - -pub struct Exit; - -impl WholeStreamCommand for Exit { - fn name(&self) -> &str { - "exit" - } - - fn signature(&self) -> Signature { - Signature::build("exit") - .optional( - "code", - SyntaxShape::Number, - "Status code to return if this was the last shell or --now was specified", - ) - .switch("now", "Exit out of the shell immediately", Some('n')) - } - - fn usage(&self) -> &str { - "Exit the current shell (or all shells)." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - exit(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Exit the current shell", - example: "exit", - result: None, - }, - Example { - description: "Exit all shells (exiting Nu)", - example: "exit --now", - result: None, - }, - ] - } -} - -pub fn exit(args: CommandArgs) -> Result { - let code = if let Some(value) = args.opt::(0)? { - value as i32 - } else { - 0 - }; - - let command_action = if args.has_flag("now") { - CommandAction::Exit(code) - } else { - CommandAction::LeaveShell(code) - }; - - Ok(ActionStream::one(ReturnSuccess::action(command_action))) -} - -#[cfg(test)] -mod tests { - use super::Exit; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Exit {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/shells/goto.rs b/old_nushell/crates/nu-command/src/commands/shells/goto.rs deleted file mode 100644 index d1396c2dc..000000000 --- a/old_nushell/crates/nu-command/src/commands/shells/goto.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape}; - -pub struct Goto; - -impl WholeStreamCommand for Goto { - fn name(&self) -> &str { - "g" - } - - fn signature(&self) -> Signature { - Signature::build("g").required("index", SyntaxShape::Int, "the shell's index to go to") - } - - fn usage(&self) -> &str { - "Go to specified shell." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - goto(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Enter the first shell", - example: "g 0", - result: None, - }] - } -} - -fn goto(args: CommandArgs) -> Result { - Ok(ActionStream::one(ReturnSuccess::action( - CommandAction::GotoShell(args.req(0)?), - ))) -} - -#[cfg(test)] -mod tests { - use super::Goto; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Goto {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/shells/mod.rs b/old_nushell/crates/nu-command/src/commands/shells/mod.rs deleted file mode 100644 index 7c4897b1f..000000000 --- a/old_nushell/crates/nu-command/src/commands/shells/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -mod command; -mod enter; -mod exit; -mod goto; -mod next; -mod prev; - -pub use command::Shells; -pub use enter::Enter; -pub use exit::Exit; -pub use goto::Goto; -pub use next::Next; -pub use prev::Previous; diff --git a/old_nushell/crates/nu-command/src/commands/shells/next.rs b/old_nushell/crates/nu-command/src/commands/shells/next.rs deleted file mode 100644 index 73df6aaa2..000000000 --- a/old_nushell/crates/nu-command/src/commands/shells/next.rs +++ /dev/null @@ -1,41 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{CommandAction, ReturnSuccess, Signature}; - -pub struct Next; - -impl WholeStreamCommand for Next { - fn name(&self) -> &str { - "n" - } - - fn signature(&self) -> Signature { - Signature::build("n") - } - - fn usage(&self) -> &str { - "Go to next shell." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(next(args)) - } -} - -fn next(_args: CommandArgs) -> ActionStream { - vec![Ok(ReturnSuccess::Action(CommandAction::NextShell))].into() -} - -#[cfg(test)] -mod tests { - use super::Next; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Next {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/shells/prev.rs b/old_nushell/crates/nu-command/src/commands/shells/prev.rs deleted file mode 100644 index d32a90422..000000000 --- a/old_nushell/crates/nu-command/src/commands/shells/prev.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{CommandAction, ReturnSuccess, Signature}; - -use nu_engine::WholeStreamCommand; - -pub struct Previous; - -impl WholeStreamCommand for Previous { - fn name(&self) -> &str { - "p" - } - - fn signature(&self) -> Signature { - Signature::build("p") - } - - fn usage(&self) -> &str { - "Go to previous shell." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(previous(args)) - } -} - -fn previous(_args: CommandArgs) -> ActionStream { - vec![Ok(ReturnSuccess::Action(CommandAction::PreviousShell))].into() -} - -#[cfg(test)] -mod tests { - use super::Previous; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Previous {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/build_string.rs b/old_nushell/crates/nu-command/src/commands/strings/build_string.rs deleted file mode 100644 index 774d3e6ad..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/build_string.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::prelude::*; -use nu_errors::ShellError; - -use nu_data::value::format_leaf; -use nu_engine::WholeStreamCommand; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; - -pub struct BuildString; - -impl WholeStreamCommand for BuildString { - fn name(&self) -> &str { - "build-string" - } - - fn signature(&self) -> Signature { - Signature::build("build-string").rest( - "rest", - SyntaxShape::Any, - "all values to form into the string", - ) - } - - fn usage(&self) -> &str { - "Builds a string from the arguments." - } - - fn run(&self, args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - let rest: Vec = args.rest(0)?; - - let mut output_string = String::new(); - - for r in rest { - output_string.push_str(&format_leaf(&r).plain_string(100_000)) - } - - Ok(OutputStream::one( - UntaggedValue::string(output_string).into_value(tag), - )) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Builds a string from a string and a number, without spaces between them", - example: "build-string 'foo' 3", - result: None, - }] - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/char_.rs b/old_nushell/crates/nu-command/src/commands/strings/char_.rs deleted file mode 100644 index 75f7bd7f3..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/char_.rs +++ /dev/null @@ -1,325 +0,0 @@ -use crate::prelude::*; -use indexmap::indexmap; -use indexmap::map::IndexMap; -use lazy_static::lazy_static; -use nu_engine::{FromValue, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tagged; - -// Character used to separate directories in a Path Environment variable on windows is ";" -#[cfg(target_family = "windows")] -const ENV_PATH_SEPARATOR_CHAR: char = ';'; -// Character used to separate directories in a Path Environment variable on linux/mac/unix is ":" -#[cfg(not(target_family = "windows"))] -const ENV_PATH_SEPARATOR_CHAR: char = ':'; - -pub struct Char; - -struct CharArgs { - name: Option>, - rest: Vec, - list: bool, - unicode: bool, -} - -lazy_static! { - static ref CHAR_MAP: IndexMap<&'static str, String> = indexmap! { - // These are some regular characters that either can't be used or - // it's just easier to use them like this. - - // This are the "normal" characters section - "newline" => '\n'.to_string(), - "enter" => '\n'.to_string(), - "nl" => '\n'.to_string(), - "tab" => '\t'.to_string(), - "sp" => ' '.to_string(), - "space" => ' '.to_string(), - "pipe" => '|'.to_string(), - "left_brace" => '{'.to_string(), - "lbrace" => '{'.to_string(), - "right_brace" => '}'.to_string(), - "rbrace" => '}'.to_string(), - "left_paren" => '('.to_string(), - "lp" => '('.to_string(), - "lparen" => '('.to_string(), - "right_paren" => ')'.to_string(), - "rp" => ')'.to_string(), - "rparen" => ')'.to_string(), - "left_bracket" => '['.to_string(), - "lbracket" => '['.to_string(), - "right_bracket" => ']'.to_string(), - "rbracket" => ']'.to_string(), - "single_quote" => '\''.to_string(), - "squote" => '\''.to_string(), - "sq" => '\''.to_string(), - "double_quote" => '\"'.to_string(), - "dquote" => '\"'.to_string(), - "dq" => '\"'.to_string(), - "path_sep" => std::path::MAIN_SEPARATOR.to_string(), - "psep" => std::path::MAIN_SEPARATOR.to_string(), - "separator" => std::path::MAIN_SEPARATOR.to_string(), - "esep" => ENV_PATH_SEPARATOR_CHAR.to_string(), - "env_sep" => ENV_PATH_SEPARATOR_CHAR.to_string(), - "tilde" => '~'.to_string(), // ~ - "twiddle" => '~'.to_string(), // ~ - "squiggly" => '~'.to_string(), // ~ - "home" => '~'.to_string(), // ~ - "hash" => '#'.to_string(), // # - "hashtag" => '#'.to_string(), // # - "pound_sign" => '#'.to_string(), // # - "sharp" => '#'.to_string(), // # - "root" => '#'.to_string(), // # - "comma" => ','.to_string(), // , comma - "semicolon" => ';'.to_string(), // ; semicolon - "dollar" => '$'.to_string(), // $ dollar - "at" => '@'.to_string(), // @ at - "minus" => '-'.to_string(), // - minus - "subtract" => '-'.to_string(), - "dash" => '-'.to_string(), - "plus" => '+'.to_string(), // + plus - "add" => '+'.to_string(), - "divide" => '/'.to_string(), // / divide, slash - "slash" => '/'.to_string(), - "backslash" => '\\'.to_string(),// \ backslash - "percent" => '%'.to_string(), // % percent - "multiply" => '*'.to_string(), // * multiply - "greater_than" => '>'.to_string(), // > greater_than - "gt" => '>'.to_string(), - "less_than" => '<'.to_string(), // < less_than - "lt" => '<'.to_string(), - "and" => '&'.to_string(), // & and, ampersand - "ampersand" => '&'.to_string(), - "equal" => '='.to_string(), // = equal - "eq" => '='.to_string(), - "double_equal" => "==".to_string(), // == double_equal - "fat_arrow" => "=>".to_string(), // => fat_arrow - "right_arrow" => "->".to_string(), // -> right_arrow - "left_arrow" => "<-".to_string(), // <- left_arrow - "question" => '?'.to_string(), // ? question, q - "q" => '?'.to_string(), - "colon" => ':'.to_string(), // : colon - "underscore" => '_'.to_string(), - "u" => '_'.to_string(), - - // This is the unicode section - // Unicode names came from https://www.compart.com/en/unicode - // Private Use Area (U+E000-U+F8FF) - // Unicode can't be mixed with Ansi or it will break width calculation - "branch" => '\u{e0a0}'.to_string(), //  - "segment" => '\u{e0b0}'.to_string(), //  - - "identical_to" => '\u{2261}'.to_string(), // ≡ - "hamburger" => '\u{2261}'.to_string(), // ≡ - "not_identical_to" => '\u{2262}'.to_string(), // ≢ - "branch_untracked" => '\u{2262}'.to_string(), // ≢ - "strictly_equivalent_to" => '\u{2263}'.to_string(), // ≣ - "branch_identical" => '\u{2263}'.to_string(), // ≣ - - "upwards_arrow" => '\u{2191}'.to_string(), // ↑ - "branch_ahead" => '\u{2191}'.to_string(), // ↑ - "downwards_arrow" => '\u{2193}'.to_string(), // ↓ - "branch_behind" => '\u{2193}'.to_string(), // ↓ - "up_down_arrow" => '\u{2195}'.to_string(), // ↕ - "branch_ahead_behind" => '\u{2195}'.to_string(), // ↕ - - "black_right_pointing_triangle" => '\u{25b6}'.to_string(), // ▶ - "prompt" => '\u{25b6}'.to_string(), // ▶ - "vector_or_cross_product" => '\u{2a2f}'.to_string(), // ⨯ - "failed" => '\u{2a2f}'.to_string(), // ⨯ - "high_voltage_sign" => '\u{26a1}'.to_string(), // ⚡ - "elevated" => '\u{26a1}'.to_string(), // ⚡ - - // This is the emoji section - // Weather symbols - "sun" => "☀️".to_string(), - "sunny" => "☀️".to_string(), - "sunrise" => "☀️".to_string(), - "moon" => "🌛".to_string(), - "cloudy" => "☁️".to_string(), - "cloud" => "☁️".to_string(), - "clouds" => "☁️".to_string(), - "rainy" => "🌦️".to_string(), - "rain" => "🌦️".to_string(), - "foggy" => "🌫️".to_string(), - "fog" => "🌫️".to_string(), - "mist" => '\u{2591}'.to_string(), - "haze" => '\u{2591}'.to_string(), - "snowy" => "❄️".to_string(), - "snow" => "❄️".to_string(), - "thunderstorm" => "🌩️".to_string(), - "thunder" => "🌩️".to_string(), - - // This is the "other" section - "bel" => '\x07'.to_string(), // Terminal Bell - "backspace" => '\x08'.to_string(), // Backspace - }; -} - -impl WholeStreamCommand for Char { - fn name(&self) -> &str { - "char" - } - - fn signature(&self) -> Signature { - Signature::build("char") - .optional( - "character", - SyntaxShape::Any, - "the name of the character to output", - ) - .rest("rest", SyntaxShape::String, "multiple Unicode bytes") - .switch("list", "List all supported character names", Some('l')) - .switch("unicode", "Unicode string i.e. 1f378", Some('u')) - } - - fn usage(&self) -> &str { - "Output special characters (e.g., 'newline')." - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Output newline", - example: r#"char newline"#, - result: Some(vec![Value::from("\n")]), - }, - Example { - description: "Output prompt character, newline and a hamburger character", - example: r#"echo (char prompt) (char newline) (char hamburger)"#, - result: Some(vec![ - UntaggedValue::string("\u{25b6}").into(), - UntaggedValue::string("\n").into(), - UntaggedValue::string("\u{2261}").into(), - ]), - }, - Example { - description: "Output Unicode character", - example: r#"char -u 1f378"#, - result: Some(vec![Value::from("\u{1f378}")]), - }, - Example { - description: "Output multi-byte Unicode character", - example: r#"char -u 1F468 200D 1F466 200D 1F466"#, - result: Some(vec![Value::from( - "\u{1F468}\u{200D}\u{1F466}\u{200D}\u{1F466}", - )]), - }, - ] - } - - fn run(&self, args: CommandArgs) -> Result { - let args_tag = args.call_info.name_tag.clone(); - let args = CharArgs { - name: args.opt(0)?, - rest: args.rest(1)?, - list: args.has_flag("list"), - unicode: args.has_flag("unicode"), - }; - - if args.list { - Ok(CHAR_MAP - .iter() - .map(move |(name, s)| { - let mut dict = TaggedDictBuilder::with_capacity(&args_tag, 2); - dict.insert_untagged("name", UntaggedValue::string(*name)); - dict.insert_untagged("character", UntaggedValue::string(s)); - let unicode_parts: Vec = - s.chars().map(|c| format!("{:x}", c as u32)).collect(); - dict.insert_untagged("unicode", UntaggedValue::string(unicode_parts.join(" "))); - dict.into_value() - }) - .into_output_stream()) - } else if let Some(name) = args.name { - if args.unicode { - if !args.rest.is_empty() { - // Setup a new buffer to put all the Unicode bytes in - let mut multi_byte = String::new(); - // Get the first byte - let decoded_char = string_to_unicode_char(&name.item, &name.tag); - match decoded_char { - Ok(ch) => multi_byte.push(ch), - Err(e) => return Err(e), - } - // Get the rest of the bytes - for byte_part in args.rest { - let byte_part: Tagged = FromValue::from_value(&byte_part)?; - let decoded_char = string_to_unicode_char(&byte_part, &byte_part.tag); - match decoded_char { - Ok(ch) => multi_byte.push(ch), - Err(e) => return Err(e), - } - } - Ok(OutputStream::one( - UntaggedValue::string(multi_byte).into_value(name.tag), - )) - } else { - let decoded_char = string_to_unicode_char(&name.item, &name.tag); - if let Ok(ch) = decoded_char { - Ok(OutputStream::one( - UntaggedValue::string(ch).into_value(name.tag()), - )) - } else { - Err(ShellError::labeled_error( - "error decoding Unicode character", - "error decoding Unicode character", - name.tag(), - )) - } - } - } else { - let special_character = str_to_character(&name.item); - if let Some(output) = special_character { - Ok(OutputStream::one( - UntaggedValue::string(output).into_value(name.tag()), - )) - } else { - Err(ShellError::labeled_error( - "error finding named character", - "error finding named character", - name.tag(), - )) - } - } - } else { - Err(ShellError::labeled_error( - "char requires the name of the character", - "missing name of the character", - &args_tag, - )) - } - } -} - -fn string_to_unicode_char(s: &str, t: &Tag) -> Result { - let decoded_char = u32::from_str_radix(s, 16) - .ok() - .and_then(std::char::from_u32); - - if let Some(ch) = decoded_char { - Ok(ch) - } else { - Err(ShellError::labeled_error( - "error decoding Unicode character", - "error decoding Unicode character", - t, - )) - } -} - -fn str_to_character(s: &str) -> Option { - CHAR_MAP.get(s).map(|s| s.into()) -} - -#[cfg(test)] -mod tests { - use super::Char; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Char {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/detect/columns.rs b/old_nushell/crates/nu-command/src/commands/strings/detect/columns.rs deleted file mode 100644 index b2a1a61eb..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/detect/columns.rs +++ /dev/null @@ -1,283 +0,0 @@ -use std::{iter::Peekable, str::CharIndices}; - -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue}; -use nu_source::Spanned; - -type Input<'t> = Peekable>; - -pub struct DetectColumns; - -impl WholeStreamCommand for DetectColumns { - fn name(&self) -> &str { - "detect columns" - } - - fn signature(&self) -> Signature { - Signature::build("detect columns") - .named( - "skip", - SyntaxShape::Int, - "number of rows to skip before detecting", - Some('s'), - ) - .switch("no_headers", "don't detect headers", Some('n')) - } - - fn usage(&self) -> &str { - "splits contents across multiple columns via the separator." - } - - fn run(&self, args: CommandArgs) -> Result { - detect_columns(args) - } -} - -fn detect_columns(args: CommandArgs) -> Result { - let name_tag = args.name_tag(); - let num_rows_to_skip: Option = args.get_flag("skip")?; - let noheader = args.has_flag("no_headers"); - let input = args.input.collect_string(name_tag.clone())?; - - let input: Vec<_> = input - .lines() - .skip(num_rows_to_skip.unwrap_or_default()) - .map(|x| x.to_string()) - .collect(); - - let mut input = input.into_iter(); - let headers = input.next(); - - if let Some(orig_headers) = headers { - let headers = find_columns(&orig_headers); - - Ok((if noheader { - vec![orig_headers].into_iter().chain(input) - } else { - vec![].into_iter().chain(input) - }) - .map(move |x| { - let row = find_columns(&x); - - let mut dict = TaggedDictBuilder::new(name_tag.clone()); - - if headers.len() == row.len() && !noheader { - for (header, val) in headers.iter().zip(row.iter()) { - dict.insert_untagged(&header.item, UntaggedValue::string(&val.item)); - } - } else { - let mut pre_output = vec![]; - - // column counts don't line up, so see if we can figure out why - for cell in row { - for header in &headers { - if cell.span.start() <= header.span.end() - && cell.span.end() > header.span.start() - { - pre_output - .push((header.item.to_string(), UntaggedValue::string(&cell.item))); - } - } - } - - for header in &headers { - let mut found = false; - for pre_o in &pre_output { - if pre_o.0 == header.item { - found = true; - break; - } - } - - if !found { - pre_output.push((header.item.to_string(), UntaggedValue::nothing())); - } - } - - if noheader { - for header in headers.iter().enumerate() { - for pre_o in &pre_output { - if pre_o.0 == header.1.item { - dict.insert_untagged(format!("Column{}", header.0), pre_o.1.clone()) - } - } - } - } else { - for header in &headers { - for pre_o in &pre_output { - if pre_o.0 == header.item { - dict.insert_untagged(&header.item, pre_o.1.clone()) - } - } - } - } - } - - dict.into_value() - }) - .into_output_stream()) - } else { - Ok(OutputStream::empty()) - } -} - -pub fn find_columns(input: &str) -> Vec> { - let mut chars = input.char_indices().peekable(); - let mut output = vec![]; - - while let Some((_, c)) = chars.peek() { - if c.is_whitespace() { - // If the next character is non-newline whitespace, skip it. - - let _ = chars.next(); - } else { - // Otherwise, try to consume an unclassified token. - - let result = baseline(&mut chars); - - output.push(result); - } - } - - output -} - -#[derive(Clone, Copy)] -enum BlockKind { - Paren, - CurlyBracket, - SquareBracket, -} - -fn baseline(src: &mut Input) -> Spanned { - let mut token_contents = String::new(); - - let start_offset = if let Some((pos, _)) = src.peek() { - *pos - } else { - 0 - }; - - // This variable tracks the starting character of a string literal, so that - // we remain inside the string literal lexer mode until we encounter the - // closing quote. - let mut quote_start: Option = None; - - // This Vec tracks paired delimiters - let mut block_level: Vec = vec![]; - - // A baseline token is terminated if it's not nested inside of a paired - // delimiter and the next character is one of: `|`, `;`, `#` or any - // whitespace. - fn is_termination(block_level: &[BlockKind], c: char) -> bool { - block_level.is_empty() && (c.is_whitespace()) - } - - // The process of slurping up a baseline token repeats: - // - // - String literal, which begins with `'`, `"` or `\``, and continues until - // the same character is encountered again. - // - Delimiter pair, which begins with `[`, `(`, or `{`, and continues until - // the matching closing delimiter is found, skipping comments and string - // literals. - // - When not nested inside of a delimiter pair, when a terminating - // character (whitespace, `|`, `;` or `#`) is encountered, the baseline - // token is done. - // - Otherwise, accumulate the character into the current baseline token. - while let Some((_, c)) = src.peek() { - let c = *c; - - if quote_start.is_some() { - // If we encountered the closing quote character for the current - // string, we're done with the current string. - if Some(c) == quote_start { - quote_start = None; - } - } else if c == '\n' { - if is_termination(&block_level, c) { - break; - } - } else if c == '\'' || c == '"' || c == '`' { - // We encountered the opening quote of a string literal. - quote_start = Some(c); - } else if c == '[' { - // We encountered an opening `[` delimiter. - block_level.push(BlockKind::SquareBracket); - } else if c == ']' { - // We encountered a closing `]` delimiter. Pop off the opening `[` - // delimiter. - if let Some(BlockKind::SquareBracket) = block_level.last() { - let _ = block_level.pop(); - } - } else if c == '{' { - // We encountered an opening `{` delimiter. - block_level.push(BlockKind::CurlyBracket); - } else if c == '}' { - // We encountered a closing `}` delimiter. Pop off the opening `{`. - if let Some(BlockKind::CurlyBracket) = block_level.last() { - let _ = block_level.pop(); - } - } else if c == '(' { - // We enceountered an opening `(` delimiter. - block_level.push(BlockKind::Paren); - } else if c == ')' { - // We encountered a closing `)` delimiter. Pop off the opening `(`. - if let Some(BlockKind::Paren) = block_level.last() { - let _ = block_level.pop(); - } - } else if is_termination(&block_level, c) { - break; - } - - // Otherwise, accumulate the character into the current token. - token_contents.push(c); - - // Consume the character. - let _ = src.next(); - } - - let span = Span::new(start_offset, start_offset + token_contents.len()); - - // If there is still unclosed opening delimiters, close them and add - // synthetic closing characters to the accumulated token. - if block_level.last().is_some() { - // let delim: char = (*block).closing(); - // let cause = ParseError::unexpected_eof(delim.to_string(), span); - - // while let Some(bk) = block_level.pop() { - // token_contents.push(bk.closing()); - // } - - return token_contents.spanned(span); - } - - if quote_start.is_some() { - // The non-lite parse trims quotes on both sides, so we add the expected quote so that - // anyone wanting to consume this partial parse (e.g., completions) will be able to get - // correct information from the non-lite parse. - // token_contents.push(delimiter); - - // return ( - // token_contents.spanned(span), - // Some(ParseError::unexpected_eof(delimiter.to_string(), span)), - // ); - return token_contents.spanned(span); - } - - token_contents.spanned(span) -} - -#[cfg(test)] -mod tests { - use super::DetectColumns; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(DetectColumns {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/detect/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/detect/mod.rs deleted file mode 100644 index 5c56257ba..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/detect/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod columns; - -pub use columns::DetectColumns; diff --git a/old_nushell/crates/nu-command/src/commands/strings/format/command.rs b/old_nushell/crates/nu-command/src/commands/strings/format/command.rs deleted file mode 100644 index eb402e3cd..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/format/command.rs +++ /dev/null @@ -1,142 +0,0 @@ -use crate::prelude::*; -use nu_engine::evaluate_baseline_expr; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; -use std::borrow::Borrow; - -pub struct Format; - -impl WholeStreamCommand for Format { - fn name(&self) -> &str { - "format" - } - - fn signature(&self) -> Signature { - Signature::build("format").required( - "pattern", - SyntaxShape::String, - "the pattern to output. Eg) \"{foo}: {bar}\"", - ) - } - - fn usage(&self) -> &str { - "Format columns into a string using a simple pattern." - } - - fn run(&self, args: CommandArgs) -> Result { - format_command(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Print filenames with their sizes", - example: "ls | format '{name}: {size}'", - result: None, - }] - } -} - -fn format_command(args: CommandArgs) -> Result { - let ctx = Arc::new(args.context.clone()); - let pattern: Tagged = args.req(0)?; - - let format_pattern = format(&pattern); - let commands = Arc::new(format_pattern); - - Ok(args - .input - .map(move |value| { - let mut output = String::new(); - let commands = commands.clone(); - let ctx = ctx.clone(); - - for command in &*commands { - match command { - FormatCommand::Text(s) => { - output.push_str(s); - } - FormatCommand::Column(c) => { - // FIXME: use the correct spans - let full_column_path = nu_parser::parse_full_column_path( - &(c.to_string()).spanned(Span::unknown()), - &ctx.scope, - ); - - ctx.scope.enter_scope(); - ctx.scope.add_var("$it", value.clone()); - let result = evaluate_baseline_expr(&full_column_path.0, &ctx); - ctx.scope.exit_scope(); - - if let Ok(c) = result { - output.push_str(&value::format_leaf(c.borrow()).plain_string(100_000)) - } else { - // That column doesn't match, so don't emit anything - } - } - } - } - - Ok(UntaggedValue::string(output).into_untagged_value()) - }) - .into_input_stream()) -} - -#[derive(Debug)] -enum FormatCommand { - Text(String), - Column(String), -} - -fn format(input: &str) -> Vec { - let mut output = vec![]; - - let mut loop_input = input.chars(); - loop { - let mut before = String::new(); - - for c in &mut loop_input { - if c == '{' { - break; - } - before.push(c); - } - - if !before.is_empty() { - output.push(FormatCommand::Text(before.to_string())); - } - // Look for column as we're now at one - let mut column = String::new(); - - for c in &mut loop_input { - if c == '}' { - break; - } - column.push(c); - } - - if !column.is_empty() { - output.push(FormatCommand::Column(column.to_string())); - } - - if before.is_empty() && column.is_empty() { - break; - } - } - - output -} - -#[cfg(test)] -mod tests { - use super::Format; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Format {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/format/format_filesize.rs b/old_nushell/crates/nu-command/src/commands/strings/format/format_filesize.rs deleted file mode 100644 index 23d56ffac..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/format/format_filesize.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::prelude::*; -use nu_data::base::shape::InlineShape; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ColumnPath, Primitive::Filesize, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; -use nu_value_ext::get_data_by_column_path; - -pub struct FileSize; - -impl WholeStreamCommand for FileSize { - fn name(&self) -> &str { - "format filesize" - } - - fn signature(&self) -> Signature { - Signature::build("format filesize") - .required( - "field", - SyntaxShape::ColumnPath, - "the name of the column to update", - ) - .required( - "format value", - SyntaxShape::String, - "the format into which convert the filesizes", - ) - } - - fn usage(&self) -> &str { - "Converts a column of filesizes to some specified format" - } - - fn run(&self, args: CommandArgs) -> Result { - filesize(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert the size row to KB", - example: "ls | format filesize size KB", - result: None, - }, - Example { - description: "Convert the apparent row to B", - example: "du | format filesize apparent B", - result: None, - }, - ] - } -} - -fn process_row( - input: Value, - format: Tagged, - field: Arc, -) -> Result { - let replace_for = get_data_by_column_path(&input, &field, move |_, _, error| error); - match replace_for { - Ok(s) => { - if let Value { - value: UntaggedValue::Primitive(Filesize(fs)), - .. - } = s - { - let byte_format = InlineShape::format_bytes(fs, Some(&format.item)); - let byte_value = Value::from(byte_format.1); - Ok(input - .replace_data_at_column_path(&field, byte_value) - .expect( - "Given that the existence check was already done, this shouldn't trigger never", - )) - } else { - Err(ShellError::labeled_error( - "the data in this row is not of the type filesize", - "invalid datatype in row", - input.tag(), - )) - } - } - Err(e) => Err(e), - } -} - -fn filesize(args: CommandArgs) -> Result { - let field: ColumnPath = args.req(0)?; - let format: Tagged = args.req(1)?; - let field = Arc::new(field); - - Ok(args - .input - .flat_map(move |input| { - let format = format.clone(); - let field = field.clone(); - - match process_row(input, format, field) { - Ok(s) => Ok(s), - Err(e) => Err(e), - } - }) - .map(Ok) - .into_input_stream()) -} - -#[cfg(test)] -mod tests { - use super::FileSize; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(FileSize {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/format/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/format/mod.rs deleted file mode 100644 index cd8267069..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/format/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod command; -pub mod format_filesize; - -pub use command::Format; -pub use format_filesize::FileSize; diff --git a/old_nushell/crates/nu-command/src/commands/strings/lines.rs b/old_nushell/crates/nu-command/src/commands/strings/lines.rs deleted file mode 100644 index 5d8a588dc..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/lines.rs +++ /dev/null @@ -1,129 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; -use parking_lot::Mutex; - -pub struct Lines; - -impl WholeStreamCommand for Lines { - fn name(&self) -> &str { - "lines" - } - - fn signature(&self) -> Signature { - Signature::build("lines") - } - - fn usage(&self) -> &str { - "Split single string into rows, one per line." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - lines(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Split multi-line string into lines", - example: r#"^echo "two\nlines" | lines"#, - result: None, - }] - } -} - -fn ends_with_line_ending(st: &str) -> bool { - let mut temp = st.to_string(); - let last = temp.pop(); - if let Some(c) = last { - c == '\n' - } else { - false - } -} - -fn lines(args: CommandArgs) -> Result { - let leftover_string = Arc::new(Mutex::new(String::new())); - let tag = args.name_tag(); - let name_span = tag.span; - - let eos = vec![UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()]; - - Ok(args - .input - .chain(eos) - .filter_map(move |item| { - let leftover_string = leftover_string.clone(); - match item { - Value { - value: UntaggedValue::Primitive(Primitive::String(st)), - .. - } => { - let mut leftover_string = leftover_string.lock(); - - let mut buffer = leftover_string.clone(); - buffer.push_str(&st); - - let mut lines: Vec = buffer.lines().map(|x| x.to_string()).collect(); - - leftover_string.clear(); - - if !ends_with_line_ending(&st) { - if let Some(last) = lines.pop() { - leftover_string.push_str(&last); - } - } - - if !lines.is_empty() { - let success_lines: Vec<_> = lines - .iter() - .map(|x| { - ReturnSuccess::value(UntaggedValue::string(x).into_untagged_value()) - }) - .collect(); - - Some(success_lines) - } else { - None - } - } - Value { - value: UntaggedValue::Primitive(Primitive::EndOfStream), - .. - } => { - let st = leftover_string.lock().clone(); - if !st.is_empty() { - Some(vec![ReturnSuccess::value( - UntaggedValue::string(st).into_untagged_value(), - )]) - } else { - None - } - } - Value { - tag: value_span, .. - } => Some(vec![Err(ShellError::labeled_error_with_secondary( - "Expected a string from pipeline", - "requires string input", - name_span, - "value originates from here", - value_span, - ))]), - } - }) - .flatten() - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::Lines; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Lines {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/mod.rs deleted file mode 100644 index b92f5e254..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -mod build_string; -mod char_; -mod detect; -mod format; -mod lines; -mod parse; -mod size; -mod split; -mod split_by; -mod str_; - -pub use build_string::BuildString; -pub use char_::Char; -pub use detect::DetectColumns; -pub use format::*; -pub use lines::Lines; -pub use parse::*; -pub use size::Size; -pub use split::*; -pub use split_by::SplitBy; -pub use str_::*; diff --git a/old_nushell/crates/nu-command/src/commands/strings/parse/command.rs b/old_nushell/crates/nu-command/src/commands/strings/parse/command.rs deleted file mode 100644 index 656555d69..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/parse/command.rs +++ /dev/null @@ -1,211 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tagged; - -use regex::{self, Regex}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "parse" - } - - fn signature(&self) -> Signature { - Signature::build("parse") - .required( - "pattern", - SyntaxShape::String, - "the pattern to match. Eg) \"{foo}: {bar}\"", - ) - .switch("regex", "use full regex syntax for patterns", Some('r')) - } - - fn usage(&self) -> &str { - "Parse columns from string data using a simple pattern." - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - let mut row = IndexMap::new(); - row.insert("foo".to_string(), Value::from("hi")); - row.insert("bar".to_string(), Value::from("there")); - vec![ - Example { - description: "Parse a string into two named columns", - example: "echo \"hi there\" | parse \"{foo} {bar}\"", - result: Some(vec![UntaggedValue::row(row.clone()).into()]), - }, - Example { - description: "Parse a string using regex pattern", - example: "echo \"hi there\" | parse -r \"(?P\\w+) (?P\\w+)\"", - result: Some(vec![UntaggedValue::row(row).into()]), - }, - ] - } -} - -pub fn operate(args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - - let pattern: Tagged = args.req(0)?; - let regex: bool = args.has_flag("regex"); - - let item_to_parse = if regex { - pattern.item.clone() - } else { - build_regex(&pattern.item, pattern.tag.clone())? - }; - - let regex_pattern = - Regex::new(&item_to_parse).map_err(|e| parse_regex_error(e, pattern.span()))?; - - let columns = column_names(®ex_pattern); - let mut parsed: VecDeque = VecDeque::new(); - - for v in args.input { - match v.as_string() { - Ok(s) => { - let results = regex_pattern.captures_iter(&s); - - for c in results { - let mut dict = TaggedDictBuilder::new(&v.tag); - - for (column_name, cap) in columns.iter().zip(c.iter().skip(1)) { - let cap_string = cap.map(|v| v.as_str()).unwrap_or("").to_string(); - dict.insert_untagged(column_name, UntaggedValue::string(cap_string)); - } - - parsed.push_back(dict.into_value()); - } - } - Err(_) => { - return Err(ShellError::labeled_error_with_secondary( - "Expected string input", - "expected string input", - &name_tag, - "value originated here", - v.tag, - )) - } - } - } - - Ok(parsed.into_iter().into_output_stream()) -} - -fn build_regex(input: &str, tag: Tag) -> Result { - let mut output = "(?s)\\A".to_string(); - - //let mut loop_input = input; - let mut loop_input = input.chars().peekable(); - loop { - let mut before = String::new(); - while let Some(c) = loop_input.next() { - if c == '{' { - // If '{{', still creating a plaintext parse command, but just for a single '{' char - if loop_input.peek() == Some(&'{') { - let _ = loop_input.next(); - } else { - break; - } - } - before.push(c); - } - - if !before.is_empty() { - output.push_str(®ex::escape(&before)); - } - - // Look for column as we're now at one - let mut column = String::new(); - while let Some(c) = loop_input.next() { - if c == '}' { - break; - } - column.push(c); - - if loop_input.peek().is_none() { - return Err(ShellError::labeled_error( - "Found opening `{` without an associated closing `}`", - "invalid parse pattern", - tag, - )); - } - } - - if !column.is_empty() { - output.push_str("(?P<"); - output.push_str(&column); - output.push_str(">.*?)"); - } - - if before.is_empty() && column.is_empty() { - break; - } - } - - output.push_str("\\z"); - Ok(output) -} - -fn column_names(regex: &Regex) -> Vec { - regex - .capture_names() - .enumerate() - .skip(1) - .map(|(i, name)| { - name.map(String::from) - .unwrap_or_else(|| format!("Capture{}", i)) - }) - .collect() -} - -fn parse_regex_error(e: regex::Error, base_span: Span) -> ShellError { - match e { - regex::Error::Syntax(msg) => { - let mut lines = msg.lines(); - - let main_msg = lines - .next() - .map(|l| l.replace(':', "")) - .expect("invalid regex pattern"); - - let span = lines.nth(1).and_then(|l| l.find('^')).map(|space| { - let start = base_span.start() + space - 3; - Span::for_char(start) - }); - - let msg = lines - .next() - .and_then(|l| l.split(':').nth(1)) - .map(|s| s.trim().to_string()); - - match (msg, span) { - (Some(msg), Some(span)) => { - ShellError::labeled_error_with_secondary(&msg, &msg, span, main_msg, span) - } - _ => ShellError::labeled_error("Invalid regex", "invalid regex", base_span), - } - } - _ => ShellError::labeled_error("Invalid regex", "invalid regex", base_span), - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/parse/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/parse/mod.rs deleted file mode 100644 index e7c608da7..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/parse/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod command; - -pub use command::Command as Parse; diff --git a/old_nushell/crates/nu-command/src/commands/strings/size.rs b/old_nushell/crates/nu-command/src/commands/strings/size.rs deleted file mode 100644 index cd48623bd..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/size.rs +++ /dev/null @@ -1,126 +0,0 @@ -extern crate unicode_segmentation; - -use crate::prelude::*; -use indexmap::indexmap; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, TaggedDictBuilder, UntaggedValue, Value}; -use unicode_segmentation::UnicodeSegmentation; - -pub struct Size; - -impl WholeStreamCommand for Size { - fn name(&self) -> &str { - "size" - } - - fn signature(&self) -> Signature { - Signature::build("size") - } - - fn usage(&self) -> &str { - "Gather word count statistics on the text." - } - - fn run(&self, args: CommandArgs) -> Result { - size(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Count the number of words in a string", - example: r#"echo "There are seven words in this sentence" | size"#, - result: Some(vec![UntaggedValue::row(indexmap! { - "lines".to_string() => UntaggedValue::int(0).into(), - "words".to_string() => UntaggedValue::int(7).into(), - "chars".to_string() => UntaggedValue::int(38).into(), - "bytes".to_string() => UntaggedValue::int(38).into(), - }) - .into()]), - }, - Example { - description: "Counts Unicode characters correctly in a string", - example: r#"echo "Amélie Amelie" | size"#, - result: Some(vec![UntaggedValue::row(indexmap! { - "lines".to_string() => UntaggedValue::int(0).into(), - "words".to_string() => UntaggedValue::int(2).into(), - "chars".to_string() => UntaggedValue::int(13).into(), - "bytes".to_string() => UntaggedValue::int(15).into(), - }) - .into()]), - }, - ] - } -} - -fn size(args: CommandArgs) -> Result { - let input = args.input; - let tag = args.call_info.name_tag; - let name_span = tag.span; - - Ok(input - .map(move |v| { - if let Ok(s) = v.as_string() { - Ok(count(&s, &v.tag)) - } else { - Err(ShellError::labeled_error_with_secondary( - "Expected a string from pipeline", - "requires string input", - name_span, - "value originates from here", - v.tag.span, - )) - } - }) - .into_input_stream()) -} - -fn count(contents: &str, tag: impl Into) -> Value { - let mut lines: i64 = 0; - let mut words: i64 = 0; - let mut chars: i64 = 0; - let bytes = contents.len() as i64; - let mut end_of_word = true; - - for c in UnicodeSegmentation::graphemes(contents, true) { - chars += 1; - - match c { - "\n" => { - lines += 1; - end_of_word = true; - } - " " => end_of_word = true, - _ => { - if end_of_word { - words += 1; - } - end_of_word = false; - } - } - } - - let mut dict = TaggedDictBuilder::new(tag); - //TODO: add back in name when we have it in the tag - //dict.insert("name", value::string(name)); - dict.insert_untagged("lines", UntaggedValue::int(lines)); - dict.insert_untagged("words", UntaggedValue::int(words)); - dict.insert_untagged("chars", UntaggedValue::int(chars)); - dict.insert_untagged("bytes", UntaggedValue::int(bytes)); - - dict.into_value() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::Size; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Size {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/split/chars.rs b/old_nushell/crates/nu-command/src/commands/strings/split/chars.rs deleted file mode 100644 index dda836bce..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/split/chars.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "split chars" - } - - fn signature(&self) -> Signature { - Signature::build("split chars") - } - - fn usage(&self) -> &str { - "splits a string's characters into separate rows" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(split_chars(args)) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Split the string's characters into separate rows", - example: "echo 'hello' | split chars", - result: Some(vec![ - Value::from("h"), - Value::from("e"), - Value::from("l"), - Value::from("l"), - Value::from("o"), - ]), - }] - } -} - -fn split_chars(args: CommandArgs) -> ActionStream { - let name = args.call_info.name_tag.clone(); - let input = args.input; - input - .flat_map(move |v| { - if let Ok(s) = v.as_string() { - s.chars() - .collect::>() - .into_iter() - .map(move |x| ReturnSuccess::value(Value::from(x.to_string()))) - .into_action_stream() - } else { - ActionStream::one(Err(ShellError::labeled_error_with_secondary( - "Expected a string from pipeline", - "requires string input", - name.span, - "value originates from here", - v.tag.span, - ))) - } - }) - .into_action_stream() -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/split/column.rs b/old_nushell/crates/nu-command/src/commands/strings/split/column.rs deleted file mode 100644 index d8c7a4665..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/split/column.rs +++ /dev/null @@ -1,111 +0,0 @@ -use crate::prelude::*; -use log::trace; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - Primitive, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, -}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "split column" - } - - fn signature(&self) -> Signature { - Signature::build("split column") - .required( - "separator", - SyntaxShape::String, - "the character that denotes what separates columns", - ) - .switch("collapse-empty", "remove empty columns", Some('c')) - .rest( - "rest", - SyntaxShape::String, - "column names to give the new columns", - ) - } - - fn usage(&self) -> &str { - "splits contents across multiple columns via the separator." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - split_column(args) - } -} - -fn split_column(args: CommandArgs) -> Result { - let name_span = args.call_info.name_tag.span; - let separator: Tagged = args.req(0)?; - let rest: Vec> = args.rest(1)?; - let collapse_empty = args.has_flag("collapse-empty"); - let input = args.input; - - Ok(input - .map(move |v| { - if let Ok(s) = v.as_string() { - let splitter = separator.replace("\\n", "\n"); - trace!("splitting with {:?}", splitter); - - let split_result: Vec<_> = if collapse_empty { - s.split(&splitter).filter(|s| !s.is_empty()).collect() - } else { - s.split(&splitter).collect() - }; - - trace!("split result = {:?}", split_result); - - let positional: Vec<_> = rest.iter().map(|f| f.item.clone()).collect(); - - // If they didn't provide column names, make up our own - if positional.is_empty() { - let mut gen_columns = vec![]; - for i in 0..split_result.len() { - gen_columns.push(format!("Column{}", i + 1)); - } - - let mut dict = TaggedDictBuilder::new(&v.tag); - for (&k, v) in split_result.iter().zip(&gen_columns) { - dict.insert_untagged(v.clone(), Primitive::String(k.into())); - } - - ReturnSuccess::value(dict.into_value()) - } else { - let mut dict = TaggedDictBuilder::new(&v.tag); - for (&k, v) in split_result.iter().zip(&positional) { - dict.insert_untagged( - v, - UntaggedValue::Primitive(Primitive::String(k.into())), - ); - } - ReturnSuccess::value(dict.into_value()) - } - } else { - Err(ShellError::labeled_error_with_secondary( - "Expected a string from pipeline", - "requires string input", - name_span, - "value originates from here", - v.tag.span, - )) - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/split/command.rs b/old_nushell/crates/nu-command/src/commands/strings/split/command.rs deleted file mode 100644 index 2e9955326..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/split/command.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; - -#[derive(Clone)] -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "split" - } - - fn signature(&self) -> Signature { - Signature::build("split") - } - - fn usage(&self) -> &str { - "Split contents across desired subcommand (like row, column) via the separator." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(ActionStream::one(Ok(ReturnSuccess::Value( - UntaggedValue::string(get_full_help(&Command, args.scope())).into_value(Tag::unknown()), - )))) - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/split/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/split/mod.rs deleted file mode 100644 index 18bc0717a..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/split/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod chars; -pub mod column; -pub mod command; -pub mod row; - -pub use chars::SubCommand as SplitChars; -pub use column::SubCommand as SplitColumn; -pub use command::Command as Split; -pub use row::SubCommand as SplitRow; diff --git a/old_nushell/crates/nu-command/src/commands/strings/split/row.rs b/old_nushell/crates/nu-command/src/commands/strings/split/row.rs deleted file mode 100644 index a86716703..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/split/row.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::prelude::*; -use log::trace; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; -use nu_source::Tagged; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "split row" - } - - fn signature(&self) -> Signature { - Signature::build("split row").required( - "separator", - SyntaxShape::String, - "the character that denotes what separates rows", - ) - } - - fn usage(&self) -> &str { - "splits contents over multiple rows via the separator." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - split_row(args) - } -} - -fn split_row(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let separator: Tagged = args.req(0)?; - let input = args.input; - - Ok(input - .flat_map(move |v| { - if let Ok(s) = v.as_string() { - let splitter = separator.item.replace("\\n", "\n"); - trace!("splitting with {:?}", splitter); - let split_result: Vec = s - .split(&splitter) - .filter_map(|s| { - if s.trim() != "" { - Some(s.to_string()) - } else { - None - } - }) - .collect(); - - trace!("split result = {:?}", split_result); - - (split_result.into_iter().map(move |s| { - ReturnSuccess::value( - UntaggedValue::Primitive(Primitive::String(s)).into_value(&v.tag), - ) - })) - .into_action_stream() - } else { - ActionStream::one(Err(ShellError::labeled_error_with_secondary( - "Expected a string from pipeline", - "requires string input", - name.span, - "value originates from here", - v.tag.span, - ))) - } - }) - .into_action_stream()) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/split_by.rs b/old_nushell/crates/nu-command/src/commands/strings/split_by.rs deleted file mode 100644 index 069ef2ac8..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/split_by.rs +++ /dev/null @@ -1,166 +0,0 @@ -use crate::prelude::*; -use crate::utils::suggestions::suggestions; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value}; -use nu_source::Tagged; -use nu_value_ext::as_string; - -pub struct SplitBy; - -impl WholeStreamCommand for SplitBy { - fn name(&self) -> &str { - "split-by" - } - - fn signature(&self) -> Signature { - Signature::build("split-by").optional( - "column_name", - SyntaxShape::String, - "the name of the column within the nested table to split by", - ) - } - - fn usage(&self) -> &str { - "Creates a new table with the data from the inner tables split by the column given." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - split_by(args) - } -} - -pub fn split_by(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - let column_name: Option> = args.opt(0)?; - - let values: Vec = args.input.collect(); - - if values.len() > 1 || values.is_empty() { - return Err(ShellError::labeled_error( - "Expected table from pipeline", - "requires a table input", - name, - )); - } - - let split = split(&column_name, &values[0], &name)?; - Ok(ActionStream::one(ReturnSuccess::value(split))) -} - -enum Grouper { - ByColumn(Option>), -} - -pub fn split( - column_name: &Option>, - values: &Value, - tag: impl Into, -) -> Result { - let name = tag.into(); - - let grouper = if let Some(column_name) = column_name { - Grouper::ByColumn(Some(column_name.clone())) - } else { - Grouper::ByColumn(None) - }; - - match grouper { - Grouper::ByColumn(Some(column_name)) => { - let block = Box::new(move |_, row: &Value| { - match row.get_data_by_key(column_name.borrow_spanned()) { - Some(group_key) => Ok(as_string(&group_key)?), - None => Err(suggestions(column_name.borrow_tagged(), row)), - } - }); - - nu_data::utils::split(values, &Some(block), &name) - } - Grouper::ByColumn(None) => { - let block = Box::new(move |_, row: &Value| as_string(row)); - - nu_data::utils::split(values, &Some(block), &name) - } - } -} - -#[cfg(test)] -mod tests { - use super::split; - use super::ShellError; - use nu_data::utils::helpers::committers_grouped_by_date; - use nu_protocol::UntaggedValue; - use nu_source::*; - use nu_test_support::value::{date, int, row, string, table}; - - #[test] - fn splits_inner_tables_by_key() { - let for_key = Some(String::from("country").tagged_unknown()); - - assert_eq!( - split(&for_key, &committers_grouped_by_date(), Tag::unknown()).unwrap(), - UntaggedValue::row(indexmap! { - "EC".into() => row(indexmap! { - "2019-07-23".into() => table(&[ - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-07-23"), "chickens".into() => int(10)}) - ]), - "2019-09-24".into() => table(&[ - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-09-24"), "chickens".into() => int(20)}) - ]), - "2019-10-10".into() => table(&[ - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => date("2019-10-10"), "chickens".into() => int(30)}) - ]) - }), - "NZ".into() => row(indexmap! { - "2019-07-23".into() => table(&[ - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-07-23"), "chickens".into() => int(5)}) - ]), - "2019-09-24".into() => table(&[ - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-09-24"), "chickens".into() => int(10)}) - ]), - "2019-10-10".into() => table(&[ - row(indexmap!{"name".into() => string("JT"), "country".into() => string("NZ"), "date".into() => date("2019-10-10"), "chickens".into() => int(15)}) - ]) - }), - "US".into() => row(indexmap! { - "2019-07-23".into() => table(&[ - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-07-23"), "chickens".into() => int(2)}) - ]), - "2019-09-24".into() => table(&[ - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-09-24"), "chickens".into() => int(4)}) - ]), - "2019-10-10".into() => table(&[ - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => date("2019-10-10"), "chickens".into() => int(6)}) - ]) - }) - }).into_untagged_value() - ); - } - - #[test] - fn errors_if_key_within_some_inner_table_is_missing() { - let for_key = Some(String::from("country").tagged_unknown()); - - let nu_releases = row(indexmap! { - "2019-07-23".into() => table(&[ - row(indexmap!{"name".into() => string("AR"), "country".into() => string("EC"), "date".into() => string("2019-07-23")}) - ]), - "2019-09-24".into() => table(&[ - row(indexmap!{"name".into() => UntaggedValue::string("JT").into_value(Tag::from(Span::new(5,10))), "date".into() => string("2019-09-24")}) - ]), - "October 10-2019".into() => table(&[ - row(indexmap!{"name".into() => string("YK"), "country".into() => string("US"), "date".into() => string("October 10-2019")}) - ]) - }); - - assert!(split(&for_key, &nu_releases, Tag::from(Span::new(5, 10))).is_err()); - } - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use super::SplitBy; - use crate::examples::test as test_examples; - - test_examples(SplitBy {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/capitalize.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/capitalize.rs deleted file mode 100644 index 176aa164a..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/capitalize.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ColumnPath, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tag; -use nu_value_ext::ValueExt; - -struct Arguments { - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str capitalize" - } - - fn signature(&self) -> Signature { - Signature::build("str capitalize").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally capitalize text by column paths", - ) - } - - fn usage(&self) -> &str { - "capitalizes text" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Capitalize contents", - example: "echo 'good day' | str capitalize", - result: Some(vec![Value::from("Good day")]), - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arguments { - column_paths: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - action(&v, v.tag()) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -fn action(input: &Value, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let mut capitalized = String::new(); - - for (idx, character) in s.chars().enumerate() { - let out = if idx == 0 { - character.to_uppercase().to_string() - } else { - character.to_lowercase().to_string() - }; - - capitalized.push_str(&out); - } - - Ok(UntaggedValue::string(capitalized).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn capitalizes() { - let word = string("andres"); - let expected = string("Andres"); - - let actual = action(&word, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/case/camel_case.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/case/camel_case.rs deleted file mode 100644 index db1b9ac62..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/case/camel_case.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::{operate, to_lower_camel_case}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str camel-case" - } - - fn signature(&self) -> Signature { - Signature::build("str camel-case").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert text to camelCase by column paths", - ) - } - - fn usage(&self) -> &str { - "converts a string to camelCase" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args, &to_lower_camel_case) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "convert a string to camelCase", - example: "echo 'NuShell' | str camel-case", - result: Some(vec![Value::from("nuShell")]), - }] - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{to_lower_camel_case, SubCommand}; - use crate::commands::strings::str_::case::action; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn camel_case_from_kebab() { - let word = string("this-is-the-first-case"); - let expected = string("thisIsTheFirstCase"); - - let actual = action(&word, Tag::unknown(), &to_lower_camel_case).unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn camel_case_from_snake() { - let word = string("this_is_the_second_case"); - let expected = string("thisIsTheSecondCase"); - - let actual = action(&word, Tag::unknown(), &to_lower_camel_case).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/case/kebab_case.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/case/kebab_case.rs deleted file mode 100644 index 9fff03865..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/case/kebab_case.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::{operate, to_kebab_case}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str kebab-case" - } - - fn signature(&self) -> Signature { - Signature::build("str kebab-case").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert text to kebab-case by column paths", - ) - } - - fn usage(&self) -> &str { - "converts a string to kebab-case" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args, &to_kebab_case) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "convert a string to kebab-case", - example: "echo 'NuShell' | str kebab-case", - result: Some(vec![Value::from("nu-shell")]), - }] - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{to_kebab_case, SubCommand}; - use crate::commands::strings::str_::case::action; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn kebab_case_from_camel() { - let word = string("thisIsTheFirstCase"); - let expected = string("this-is-the-first-case"); - - let actual = action(&word, Tag::unknown(), &to_kebab_case).unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn kebab_case_from_screaming_snake() { - let word = string("THIS_IS_THE_SECOND_CASE"); - let expected = string("this-is-the-second-case"); - - let actual = action(&word, Tag::unknown(), &to_kebab_case).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/case/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/case/mod.rs deleted file mode 100644 index 86831443f..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/case/mod.rs +++ /dev/null @@ -1,93 +0,0 @@ -pub mod camel_case; -pub mod kebab_case; -pub mod pascal_case; -pub mod screaming_snake_case; -pub mod snake_case; - -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ColumnPath, Primitive, UntaggedValue, Value}; -use nu_source::Tag; -use nu_value_ext::ValueExt; - -pub use camel_case::SubCommand as CamelCase; -pub use pascal_case::SubCommand as PascalCase; -pub use screaming_snake_case::SubCommand as ScreamingSnakeCase; -pub use snake_case::SubCommand as SnakeCase; - -use heck::ToKebabCase; -use heck::ToLowerCamelCase; -use heck::ToShoutySnakeCase; -use heck::ToSnakeCase; -use heck::ToUpperCamelCase; -macro_rules! create_heck_function { - ($func_name:ident) => { - pub fn $func_name(a_slice: &str) -> String { - a_slice.$func_name() - } - }; -} -create_heck_function!(to_upper_camel_case); -create_heck_function!(to_lower_camel_case); -create_heck_function!(to_kebab_case); -create_heck_function!(to_shouty_snake_case); -create_heck_function!(to_snake_case); - -struct Arguments { - column_paths: Vec, -} - -pub fn operate(args: CommandArgs, case_operation: &'static F) -> Result -where - F: Fn(&str) -> String + Send + Sync + 'static, -{ - let (options, input) = ( - Arguments { - column_paths: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - action(&v, v.tag(), &case_operation) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag(), &case_operation)), - )?; - } - - Ok(ret) - } - }) - .into_input_stream()) -} - -pub fn action( - input: &Value, - tag: impl Into, - case_operation: &F, -) -> Result -where - F: Fn(&str) -> String + Send + Sync + 'static, -{ - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - Ok(UntaggedValue::string(case_operation(s)).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/case/pascal_case.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/case/pascal_case.rs deleted file mode 100644 index 2a3298083..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/case/pascal_case.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::{operate, to_upper_camel_case}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str pascal-case" - } - - fn signature(&self) -> Signature { - Signature::build("str pascal-case").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert text to PascalCase by column paths", - ) - } - - fn usage(&self) -> &str { - "converts a string to PascalCase" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args, &to_upper_camel_case) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "convert a string to PascalCase", - example: "echo 'nu-shell' | str pascal-case", - result: Some(vec![Value::from("NuShell")]), - }] - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{to_upper_camel_case, SubCommand}; - use crate::commands::strings::str_::case::action; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn pascal_case_from_kebab() { - let word = string("this-is-the-first-case"); - let expected = string("ThisIsTheFirstCase"); - - let actual = action(&word, Tag::unknown(), &to_upper_camel_case).unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn pascal_case_from_snake() { - let word = string("this_is_the_second_case"); - let expected = string("ThisIsTheSecondCase"); - - let actual = action(&word, Tag::unknown(), &to_upper_camel_case).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/case/screaming_snake_case.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/case/screaming_snake_case.rs deleted file mode 100644 index 7fc4c3dcf..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/case/screaming_snake_case.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::{operate, to_shouty_snake_case}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str screaming-snake-case" - } - - fn signature(&self) -> Signature { - Signature::build("str screaming-snake-case").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert text to SCREAMING_SNAKE_CASE by column paths", - ) - } - - fn usage(&self) -> &str { - "converts a string to SCREAMING_SNAKE_CASE" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args, &to_shouty_snake_case) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "convert a string to SCREAMING_SNAKE_CASE", - example: "echo 'NuShell' | str screaming-snake-case", - result: Some(vec![Value::from("NU_SHELL")]), - }] - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{to_shouty_snake_case, SubCommand}; - use crate::commands::strings::str_::case::action; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn snake_case_from_kebab() { - let word = string("this-is-the-first-case"); - let expected = string("THIS_IS_THE_FIRST_CASE"); - - let actual = action(&word, Tag::unknown(), &to_shouty_snake_case).unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn snake_case_from_snake() { - let word = string("this_is_the_second_case"); - let expected = string("THIS_IS_THE_SECOND_CASE"); - - let actual = action(&word, Tag::unknown(), &to_shouty_snake_case).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/case/snake_case.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/case/snake_case.rs deleted file mode 100644 index b2d865520..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/case/snake_case.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::{operate, to_snake_case}; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str snake-case" - } - - fn signature(&self) -> Signature { - Signature::build("str snake-case").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert text to snake_case by column paths", - ) - } - - fn usage(&self) -> &str { - "converts a string to snake_case" - } - - fn run(&self, args: CommandArgs) -> Result { - operate(args, &to_snake_case) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "convert a string to snake_case", - example: "echo 'NuShell' | str snake-case", - result: Some(vec![Value::from("nu_shell")]), - }] - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{to_snake_case, SubCommand}; - use crate::commands::strings::str_::case::action; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn snake_case_from_kebab() { - let word = string("this-is-the-first-case"); - let expected = string("this_is_the_first_case"); - - let actual = action(&word, Tag::unknown(), &to_snake_case).unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn snake_case_from_camel() { - let word = string("thisIsTheSecondCase"); - let expected = string("this_is_the_second_case"); - - let actual = action(&word, Tag::unknown(), &to_snake_case).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/collect.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/collect.rs deleted file mode 100644 index d1d732465..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/collect.rs +++ /dev/null @@ -1,108 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_source::Tagged; - -pub struct SubCommand; - -struct Arguments { - separator: Option>, -} - -impl Arguments { - pub fn separator(&self) -> &str { - self.separator.as_ref().map_or("", |sep| &sep.item) - } -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str collect" - } - - fn signature(&self) -> Signature { - Signature::build("str collect").desc(self.usage()).optional( - "separator", - SyntaxShape::String, - "the separator to put between the different values", - ) - } - - fn usage(&self) -> &str { - "collects a list of strings into a string" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - collect(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Collect a list of string", - example: "echo ['a' 'b' 'c'] | str collect", - result: Some(vec![Value::from("abc")]), - }] - } -} - -pub fn collect(args: CommandArgs) -> Result { - let tag = args.call_info.name_tag.clone(); - - let (options, input) = ( - Arguments { - separator: args.opt(0)?, - }, - args.input, - ); - - let separator = options.separator(); - - let strings: Vec> = input.map(|value| value.as_string()).collect(); - let strings: Result, _> = strings.into_iter().collect::>(); - - match strings { - Ok(strings) => { - let output = strings.join(separator); - - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(output).into_value(tag), - ))) - } - Err(err) => match err.error { - nu_errors::ProximateShellError::TypeError { actual, .. } => { - if let Some(item) = actual.item { - Err(ShellError::labeled_error_with_secondary( - "could not convert to string", - format!("tried to convert '{}' in input to a string", item), - tag.span, - format!("'{}' value originated here", item), - actual.span, - )) - } else { - Err(ShellError::labeled_error_with_secondary( - "could not convert to string", - "failed to convert input to strings", - tag.span, - "non-string found here", - actual.span, - )) - } - } - _ => Err(err), - }, - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/command.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/command.rs deleted file mode 100644 index f2063ec0b..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/command.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "str" - } - - fn signature(&self) -> Signature { - Signature::build("str").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert by column paths", - ) - } - - fn usage(&self) -> &str { - "Apply string function." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::string(get_full_help(&Command, args.scope())).into_value(Tag::unknown()), - ))) - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/contains.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/contains.rs deleted file mode 100644 index 9660419e6..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/contains.rs +++ /dev/null @@ -1,199 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; - -struct Arguments { - pattern: Tagged, - insensitive: bool, - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str contains" - } - - fn signature(&self) -> Signature { - Signature::build("str contains") - .required("pattern", SyntaxShape::String, "the pattern to find") - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally check if string contains pattern by column paths", - ) - .switch("insensitive", "search is case insensitive", Some('i')) - } - - fn usage(&self) -> &str { - "Checks if string contains pattern" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Check if string contains pattern", - example: "echo 'my_library.rb' | str contains '.rb'", - result: Some(vec![UntaggedValue::boolean(true).into_untagged_value()]), - }, - Example { - description: "Check if string contains pattern case insensitive", - example: "echo 'my_library.rb' | str contains -i '.RB'", - result: Some(vec![UntaggedValue::boolean(true).into_untagged_value()]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arc::new(Arguments { - pattern: args.req(0)?, - insensitive: args.has_flag("insensitive"), - column_paths: args.rest(1)?, - }), - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &options, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let options = options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &options, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action( - input: &Value, - Arguments { - ref pattern, - insensitive, - .. - }: &Arguments, - tag: impl Into, -) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let contains = if *insensitive { - s.to_lowercase().contains(&pattern.to_lowercase()) - } else { - s.contains(&pattern.item) - }; - - Ok(UntaggedValue::boolean(contains).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, Arguments, SubCommand}; - use nu_protocol::UntaggedValue; - use nu_source::{Tag, TaggedItem}; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn string_contains_other_string_case_sensitive() { - let word = string("Cargo.tomL"); - - let options = Arguments { - pattern: String::from(".tomL").tagged_unknown(), - insensitive: false, - column_paths: vec![], - }; - - let expected = UntaggedValue::boolean(true).into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } - - #[test] - fn string_does_not_contain_other_string_case_sensitive() { - let word = string("Cargo.tomL"); - - let options = Arguments { - pattern: String::from("Lomt.").tagged_unknown(), - insensitive: false, - column_paths: vec![], - }; - - let expected = UntaggedValue::boolean(false).into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } - - #[test] - fn string_contains_other_string_case_insensitive() { - let word = string("Cargo.ToMl"); - - let options = Arguments { - pattern: String::from(".TOML").tagged_unknown(), - insensitive: true, - column_paths: vec![], - }; - - let expected = UntaggedValue::boolean(true).into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } - - #[test] - fn string_does_not_contain_other_string_case_insensitive() { - let word = string("Cargo.tOml"); - - let options = Arguments { - pattern: String::from("lomt.").tagged_unknown(), - insensitive: true, - column_paths: vec![], - }; - - let expected = UntaggedValue::boolean(false).into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/downcase.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/downcase.rs deleted file mode 100644 index 5d1bfe4cf..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/downcase.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tag; -use nu_value_ext::ValueExt; - -struct Arguments { - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str downcase" - } - - fn signature(&self) -> Signature { - Signature::build("str downcase").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally downcase text by column paths", - ) - } - - fn usage(&self) -> &str { - "downcases text" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Downcase contents", - example: "echo 'NU' | str downcase", - result: Some(vec![Value::from("nu")]), - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arguments { - column_paths: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - Ok(UntaggedValue::string(s.to_ascii_lowercase()).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn downcases() { - let word = string("ANDRES"); - - let actual = action(&word, Tag::unknown()).unwrap(); - assert_eq!(actual, string("andres")); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/ends_with.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/ends_with.rs deleted file mode 100644 index 648c8f6f4..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/ends_with.rs +++ /dev/null @@ -1,132 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; - -pub struct SubCommand; - -struct Arguments { - pattern: Tagged, - column_paths: Vec, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str ends-with" - } - - fn signature(&self) -> Signature { - Signature::build("str ends-with") - .required("pattern", SyntaxShape::String, "the pattern to match") - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally matches suffix of text by column paths", - ) - } - - fn usage(&self) -> &str { - "checks if string ends with pattern" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Checks if string ends with '.rb' pattern", - example: "echo 'my_library.rb' | str ends-with '.rb'", - result: Some(vec![UntaggedValue::boolean(true).into_untagged_value()]), - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arc::new(Arguments { - pattern: args.req(0)?, - column_paths: args.rest(1)?, - }), - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &options.pattern, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let options = options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &options.pattern, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, pattern: &str, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let ends_with = s.ends_with(pattern); - Ok(UntaggedValue::boolean(ends_with).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_protocol::UntaggedValue; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn str_ends_with_pattern() { - let word = string("Cargo.toml"); - let pattern = ".toml"; - let expected = UntaggedValue::boolean(true).into_untagged_value(); - - let actual = action(&word, pattern, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn str_does_not_end_with_pattern() { - let word = string("Cargo.toml"); - let pattern = "Car"; - let expected = UntaggedValue::boolean(false).into_untagged_value(); - - let actual = action(&word, pattern, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/find_replace.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/find_replace.rs deleted file mode 100644 index d0de70a32..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/find_replace.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; -use regex::Regex; - -struct Arguments { - all: bool, - find: Tagged, - replace: Tagged, - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str find-replace" - } - - fn signature(&self) -> Signature { - Signature::build("str find-replace") - .required("find", SyntaxShape::String, "the pattern to find") - .required("replace", SyntaxShape::String, "the replacement pattern") - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally find and replace text by column paths", - ) - .switch("all", "replace all occurrences of find string", Some('a')) - } - - fn usage(&self) -> &str { - "finds and replaces text" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Find and replace contents with capture group", - example: "echo 'my_library.rb' | str find-replace '(.+).rb' '$1.nu'", - result: Some(vec![Value::from("my_library.nu")]), - }, - Example { - description: "Find and replace all occurrences of find string", - example: "echo 'abc abc abc' | str find-replace -a 'b' 'z'", - result: Some(vec![Value::from("azc azc azc")]), - }, - ] - } -} - -struct FindReplace<'a>(&'a str, &'a str); - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arc::new(Arguments { - all: args.has_flag("all"), - find: args.req(0)?, - replace: args.req(1)?, - column_paths: args.rest(2)?, - }), - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &options, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let options = options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &options, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action( - input: &Value, - Arguments { - find, replace, all, .. - }: &Arguments, - tag: impl Into, -) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let FindReplace(find, replacement) = FindReplace(find, replace); - let regex = Regex::new(find); - - Ok(match regex { - Ok(re) => { - if *all { - UntaggedValue::string(re.replace_all(s, replacement).to_owned()) - } else { - UntaggedValue::string(re.replace(s, replacement).to_owned()) - } - } - Err(_) => UntaggedValue::string(s), - } - .into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, Arguments, SubCommand}; - use nu_source::{Tag, TaggedItem}; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn can_have_capture_groups() { - let word = string("Cargo.toml"); - - let options = Arguments { - find: String::from("Cargo.(.+)").tagged_unknown(), - replace: String::from("Carga.$1").tagged_unknown(), - column_paths: vec![], - all: false, - }; - - let actual = action(&word, &options, Tag::unknown()).unwrap(); - assert_eq!(actual, string("Carga.toml")); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/index_of.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/index_of.rs deleted file mode 100644 index 16d0dcef2..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/index_of.rs +++ /dev/null @@ -1,342 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::{as_string, ValueExt}; - -struct Arguments { - end: bool, - pattern: Tagged, - range: Option, - column_paths: Vec, -} - -pub struct SubCommand; - -#[derive(Clone)] -pub struct IndexOfOptionalBounds(i32, i32); - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str index-of" - } - - fn signature(&self) -> Signature { - Signature::build("str index-of") - .required( - "pattern", - SyntaxShape::String, - "the pattern to find index of", - ) - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally returns index of pattern in string by column paths", - ) - .named( - "range", - SyntaxShape::Any, - "optional start and/or end index", - Some('r'), - ) - .switch("end", "search from the end of the string", Some('e')) - } - - fn usage(&self) -> &str { - "Returns starting index of given pattern in string counting from 0. Returns -1 when there are no results." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Returns index of pattern in string", - example: "echo 'my_library.rb' | str index-of '.rb'", - result: Some(vec![UntaggedValue::int(10).into_untagged_value()]), - }, - Example { - description: "Returns index of pattern in string with start index", - example: "echo '.rb.rb' | str index-of '.rb' -r '1,'", - result: Some(vec![UntaggedValue::int(3).into_untagged_value()]), - }, - Example { - description: "Returns index of pattern in string with end index", - example: "echo '123456' | str index-of '6' -r ',4'", - result: Some(vec![UntaggedValue::int(-1).into_untagged_value()]), - }, - Example { - description: "Returns index of pattern in string with start and end index", - example: "echo '123456' | str index-of '3' -r '1,4'", - result: Some(vec![UntaggedValue::int(2).into_untagged_value()]), - }, - Example { - description: "Alternatively you can use this form", - example: "echo '123456' | str index-of '3' -r [1 4]", - result: Some(vec![UntaggedValue::int(2).into_untagged_value()]), - }, - Example { - description: "Returns index of pattern in string", - example: "echo '/this/is/some/path/file.txt' | str index-of '/' -e", - result: Some(vec![UntaggedValue::int(18).into_untagged_value()]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arc::new(Arguments { - pattern: args.req(0)?, - range: args.get_flag("range")?, - end: args.has_flag("end"), - column_paths: args.rest(1)?, - }), - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &options, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let options = options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &options, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action( - input: &Value, - Arguments { - ref pattern, - range, - end, - .. - }: &Arguments, - tag: impl Into, -) -> Result { - let tag = tag.into(); - - let range = match range { - Some(range) => range.clone(), - None => UntaggedValue::string("").into_value(&tag), - }; - - let r = process_range(input, &range)?; - - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let start_index = r.0 as usize; - let end_index = r.1 as usize; - - if *end { - if let Some(result) = s[start_index..end_index].rfind(&**pattern) { - Ok(UntaggedValue::int(result as i64 + start_index as i64).into_value(tag)) - } else { - Ok(UntaggedValue::int(-1).into_value(tag)) - } - } else if let Some(result) = s[start_index..end_index].find(&**pattern) { - Ok(UntaggedValue::int(result as i64 + start_index as i64).into_value(tag)) - } else { - Ok(UntaggedValue::int(-1).into_value(tag)) - } - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.span, - )) - } - } -} - -fn process_range(input: &Value, range: &Value) -> Result { - let input_len = match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => s.len(), - _ => 0, - }; - let min_index_str = String::from("0"); - let max_index_str = input_len.to_string(); - let r = match &range.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let indexes: Vec<&str> = s.split(',').collect(); - - let start_index = indexes.get(0).unwrap_or(&&min_index_str[..]).to_string(); - - let end_index = indexes.get(1).unwrap_or(&&max_index_str[..]).to_string(); - - Ok((start_index, end_index)) - } - UntaggedValue::Table(indexes) => { - if indexes.len() > 2 { - Err(ShellError::labeled_error( - "there shouldn't be more than two indexes", - "too many indexes", - range.tag(), - )) - } else { - let idx: Vec = indexes - .iter() - .map(|v| as_string(v).unwrap_or_else(|_| String::from(""))) - .collect(); - - let start_index = idx.get(0).unwrap_or(&min_index_str).to_string(); - let end_index = idx.get(1).unwrap_or(&max_index_str).to_string(); - - Ok((start_index, end_index)) - } - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - range.tag(), - )) - } - }?; - - let start_index = r.0.parse::().unwrap_or(0); - let end_index = r.1.parse::().unwrap_or(input_len as i32); - - if start_index < 0 || start_index > end_index { - return Err(ShellError::labeled_error( - "start index can't be negative or greater than end index", - "Invalid start index", - range.tag(), - )); - } - - if end_index < 0 || end_index < start_index || end_index > input_len as i32 { - return Err(ShellError::labeled_error( - "end index can't be negative, smaller than start index or greater than input length", - "Invalid end index", - range.tag(), - )); - } - Ok(IndexOfOptionalBounds(start_index, end_index)) -} -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, Arguments, SubCommand}; - use nu_source::{Tag, TaggedItem}; - use nu_test_support::value::{int, string}; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn returns_index_of_substring() { - let word = string("Cargo.tomL"); - - let options = Arguments { - pattern: String::from(".tomL").tagged_unknown(), - range: Some(string("")), - column_paths: vec![], - end: false, - }; - - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, int(5)); - } - #[test] - fn index_of_does_not_exist_in_string() { - let word = string("Cargo.tomL"); - - let options = Arguments { - pattern: String::from("Lm").tagged_unknown(), - range: Some(string("")), - column_paths: vec![], - end: false, - }; - - let actual = action(&word, &options, Tag::unknown()).unwrap(); - assert_eq!(actual, int(-1)); - } - - #[test] - fn returns_index_of_next_substring() { - let word = string("Cargo.Cargo"); - - let options = Arguments { - pattern: String::from("Cargo").tagged_unknown(), - range: Some(string("1,")), - column_paths: vec![], - end: false, - }; - - let actual = action(&word, &options, Tag::unknown()).unwrap(); - assert_eq!(actual, int(6)); - } - - #[test] - fn index_does_not_exist_due_to_end_index() { - let word = string("Cargo.Banana"); - - let options = Arguments { - pattern: String::from("Banana").tagged_unknown(), - range: Some(string(",5")), - column_paths: vec![], - end: false, - }; - - let actual = action(&word, &options, Tag::unknown()).unwrap(); - assert_eq!(actual, int(-1)); - } - - #[test] - fn returns_index_of_nums_in_middle_due_to_index_limit_from_both_ends() { - let word = string("123123123"); - - let options = Arguments { - pattern: String::from("123").tagged_unknown(), - range: Some(string("2,6")), - column_paths: vec![], - end: false, - }; - - let actual = action(&word, &options, Tag::unknown()).unwrap(); - assert_eq!(actual, int(3)); - } - - #[test] - fn index_does_not_exists_due_to_strict_bounds() { - let word = string("123456"); - - let options = Arguments { - pattern: String::from("1").tagged_unknown(), - range: Some(string("2,4")), - column_paths: vec![], - end: false, - }; - - let actual = action(&word, &options, Tag::unknown()).unwrap(); - assert_eq!(actual, int(-1)); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/length.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/length.rs deleted file mode 100644 index 3c6329492..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/length.rs +++ /dev/null @@ -1,111 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; - -pub struct SubCommand; - -struct Arguments { - column_paths: Vec, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str length" - } - - fn signature(&self) -> Signature { - Signature::build("str length").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally find length of text by column paths", - ) - } - - fn usage(&self) -> &str { - "outputs the lengths of the strings in the pipeline" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Return the lengths of multiple strings", - example: "echo 'hello' | str length", - result: Some(vec![UntaggedValue::int(5).into_untagged_value()]), - }, - Example { - description: "Return the lengths of multiple strings", - example: "echo 'hi' 'there' | str length", - result: Some(vec![ - UntaggedValue::int(2).into_untagged_value(), - UntaggedValue::int(5).into_untagged_value(), - ]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arguments { - column_paths: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - Ok(UntaggedValue::int(s.len() as i64).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/lpad.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/lpad.rs deleted file mode 100644 index 7ec42130e..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/lpad.rs +++ /dev/null @@ -1,189 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; - -struct Arguments { - length: Tagged, - character: Tagged, - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str lpad" - } - - fn signature(&self) -> Signature { - Signature::build("str lpad") - .required_named("length", SyntaxShape::Int, "length to pad to", Some('l')) - .required_named( - "character", - SyntaxShape::String, - "character to pad with", - Some('c'), - ) - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally check if string contains pattern by column paths", - ) - } - - fn usage(&self) -> &str { - "pad a string with a character a certain length" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Left pad a string with a character a number of places", - example: "echo 'nushell' | str lpad -l 10 -c '*'", - result: Some(vec![ - UntaggedValue::string("***nushell").into_untagged_value() - ]), - }, - Example { - description: "Left pad a string with a character a number of places", - example: "echo '123' | str lpad -l 10 -c '0'", - result: Some(vec![ - UntaggedValue::string("0000000123").into_untagged_value() - ]), - }, - Example { - description: "Use lpad to truncate a string", - example: "echo '123456789' | str lpad -l 3 -c '0'", - result: Some(vec![UntaggedValue::string("123").into_untagged_value()]), - }, - Example { - description: "Use lpad to pad Unicode", - example: "echo '▉' | str lpad -l 10 -c '▉'", - result: Some(vec![ - UntaggedValue::string("▉▉▉▉▉▉▉▉▉▉").into_untagged_value() - ]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arc::new(Arguments { - length: args.req_named("length")?, - character: args.req_named("character")?, - column_paths: args.rest(0)?, - }), - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &options, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let options = options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &options, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action( - input: &Value, - Arguments { - character, length, .. - }: &Arguments, - tag: impl Into, -) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - if **length < s.len() { - Ok( - UntaggedValue::string(s.chars().take(**length).collect::()) - .into_value(tag), - ) - } else { - let mut res = character.repeat(**length - s.chars().count()); - res += s; - Ok(UntaggedValue::string(res).into_value(tag)) - } - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::{action, Arguments, SubCommand}; - use nu_errors::ShellError; - use nu_protocol::UntaggedValue; - use nu_source::{Tag, TaggedItem}; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn left_pad_with_zeros() { - let word = string("123"); - - let options = Arguments { - character: String::from("0").tagged_unknown(), - length: 10_usize.tagged_unknown(), - column_paths: vec![], - }; - - let expected = UntaggedValue::string("0000000123").into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } - - #[test] - fn left_pad_but_truncate() { - let word = string("123456789"); - - let options = Arguments { - character: String::from("0").tagged_unknown(), - length: 3_usize.tagged_unknown(), - column_paths: vec![], - }; - - let expected = UntaggedValue::string("123").into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/mod.rs deleted file mode 100644 index 5fcc4da11..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -mod capitalize; -mod case; -mod collect; -mod command; -mod contains; -mod downcase; -mod ends_with; -mod find_replace; -mod index_of; -mod length; -mod lpad; -mod reverse; -mod rpad; -mod starts_with; -mod substring; -mod to_datetime; -mod to_decimal; -mod to_integer; -mod trim; -mod upcase; - -pub use capitalize::SubCommand as StrCapitalize; -pub use case::camel_case::SubCommand as StrCamelCase; -pub use case::kebab_case::SubCommand as StrKebabCase; -pub use case::pascal_case::SubCommand as StrPascalCase; -pub use case::screaming_snake_case::SubCommand as StrScreamingSnakeCase; -pub use case::snake_case::SubCommand as StrSnakeCase; -pub use collect::SubCommand as StrCollect; -pub use command::Command as Str; -pub use contains::SubCommand as StrContains; -pub use downcase::SubCommand as StrDowncase; -pub use ends_with::SubCommand as StrEndsWith; -pub use find_replace::SubCommand as StrFindReplace; -pub use index_of::SubCommand as StrIndexOf; -pub use length::SubCommand as StrLength; -pub use lpad::SubCommand as StrLPad; -pub use reverse::SubCommand as StrReverse; -pub use rpad::SubCommand as StrRPad; -pub use starts_with::SubCommand as StrStartsWith; -pub use substring::SubCommand as StrSubstring; -pub use to_datetime::SubCommand as StrToDatetime; -pub use to_decimal::SubCommand as StrToDecimal; -pub use to_integer::SubCommand as StrToInteger; -pub use trim::Trim as StrTrim; -pub use upcase::SubCommand as StrUpcase; diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/reverse.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/reverse.rs deleted file mode 100644 index 7bc78b794..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/reverse.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; - -pub struct SubCommand; - -struct Arguments { - column_paths: Vec, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str reverse" - } - - fn signature(&self) -> Signature { - Signature::build("str reverse").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally reverse text by column paths", - ) - } - - fn usage(&self) -> &str { - "outputs the reversals of the strings in the pipeline" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Return the reversals of multiple strings", - example: "echo 'Nushell' | str reverse", - result: Some(vec![UntaggedValue::string("llehsuN").into_untagged_value()]), - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arguments { - column_paths: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - Ok(UntaggedValue::string(s.chars().rev().collect::()).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/rpad.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/rpad.rs deleted file mode 100644 index 35b639100..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/rpad.rs +++ /dev/null @@ -1,189 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; - -struct Arguments { - length: Tagged, - character: Tagged, - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str rpad" - } - - fn signature(&self) -> Signature { - Signature::build("str rpad") - .required_named("length", SyntaxShape::Int, "length to pad to", Some('l')) - .required_named( - "character", - SyntaxShape::String, - "character to pad with", - Some('c'), - ) - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally check if string contains pattern by column paths", - ) - } - - fn usage(&self) -> &str { - "pad a string with a character a certain length" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Right pad a string with a character a number of places", - example: "echo 'nushell' | str rpad -l 10 -c '*'", - result: Some(vec![ - UntaggedValue::string("nushell***").into_untagged_value() - ]), - }, - Example { - description: "Right pad a string with a character a number of places", - example: "echo '123' | str rpad -l 10 -c '0'", - result: Some(vec![ - UntaggedValue::string("1230000000").into_untagged_value() - ]), - }, - Example { - description: "Use rpad to truncate a string", - example: "echo '123456789' | str rpad -l 3 -c '0'", - result: Some(vec![UntaggedValue::string("123").into_untagged_value()]), - }, - Example { - description: "Use rpad to pad Unicode", - example: "echo '▉' | str rpad -l 10 -c '▉'", - result: Some(vec![ - UntaggedValue::string("▉▉▉▉▉▉▉▉▉▉").into_untagged_value() - ]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arc::new(Arguments { - length: args.req_named("length")?, - character: args.req_named("character")?, - column_paths: args.rest(0)?, - }), - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &options, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let options = options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &options, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action( - input: &Value, - Arguments { - length, character, .. - }: &Arguments, - tag: impl Into, -) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - if **length < s.len() { - Ok( - UntaggedValue::string(s.chars().take(**length).collect::()) - .into_value(tag), - ) - } else { - let mut res = s.to_string(); - res += &character.repeat(**length - s.chars().count()); - Ok(UntaggedValue::string(res).into_value(tag)) - } - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::{action, Arguments, SubCommand}; - use nu_errors::ShellError; - use nu_protocol::UntaggedValue; - use nu_source::{Tag, TaggedItem}; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn right_pad_with_zeros() { - let word = string("123"); - - let options = Arguments { - character: String::from("0").tagged_unknown(), - length: 10_usize.tagged_unknown(), - column_paths: vec![], - }; - - let expected = UntaggedValue::string("1230000000").into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } - - #[test] - fn right_pad_but_truncate() { - let word = string("123456789"); - - let options = Arguments { - character: String::from("0").tagged_unknown(), - length: 3_usize.tagged_unknown(), - column_paths: vec![], - }; - - let expected = UntaggedValue::string("123").into_untagged_value(); - let actual = action(&word, &options, Tag::unknown()).unwrap(); - - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/starts_with.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/starts_with.rs deleted file mode 100644 index 2a3311b81..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/starts_with.rs +++ /dev/null @@ -1,132 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; - -pub struct SubCommand; - -struct Arguments { - pattern: Tagged, - column_paths: Vec, -} - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str starts-with" - } - - fn signature(&self) -> Signature { - Signature::build("str starts-with") - .required("pattern", SyntaxShape::String, "the pattern to match") - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally matches prefix of text by column paths", - ) - } - - fn usage(&self) -> &str { - "checks if string starts with pattern" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Checks if string starts with 'my' pattern", - example: "echo 'my_library.rb' | str starts-with 'my'", - result: Some(vec![UntaggedValue::boolean(true).into_untagged_value()]), - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arc::new(Arguments { - pattern: args.req(0)?, - column_paths: args.rest(1)?, - }), - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &options.pattern, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let options = options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &options.pattern, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, pattern: &str, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let starts_with = s.starts_with(pattern); - Ok(UntaggedValue::boolean(starts_with).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_protocol::UntaggedValue; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn str_starts_with_pattern() { - let word = string("Cargo.toml"); - let pattern = "Car"; - let expected = UntaggedValue::boolean(true).into_untagged_value(); - - let actual = action(&word, pattern, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn str_does_not_start_with_pattern() { - let word = string("Cargo.toml"); - let pattern = ".toml"; - let expected = UntaggedValue::boolean(false).into_untagged_value(); - - let actual = action(&word, pattern, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/substring.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/substring.rs deleted file mode 100644 index 594654006..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/substring.rs +++ /dev/null @@ -1,353 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tag; -use nu_value_ext::{as_string, ValueExt}; - -use std::cmp::Ordering; -use std::convert::TryInto; - -struct Arguments { - range: Value, - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str substring" - } - - fn signature(&self) -> Signature { - Signature::build("str substring") - .required( - "range", - SyntaxShape::Any, - "the indexes to substring [start end]", - ) - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally substring text by column paths", - ) - } - - fn usage(&self) -> &str { - "substrings text" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Get a substring from the text", - example: "echo 'good nushell' | str substring [5 12]", - result: Some(vec![Value::from("nushell")]), - }, - Example { - description: "Alternatively, you can use the form", - example: "echo 'good nushell' | str substring '5,12'", - result: Some(vec![Value::from("nushell")]), - }, - Example { - description: "Drop the last `n` characters from the string", - example: "echo 'good nushell' | str substring ',-5'", - result: Some(vec![Value::from("good nu")]), - }, - Example { - description: "Get the remaining characters from a starting index", - example: "echo 'good nushell' | str substring '5,'", - result: Some(vec![Value::from("nushell")]), - }, - Example { - description: "Get the characters from the beginning until ending index", - example: "echo 'good nushell' | str substring ',7'", - result: Some(vec![Value::from("good nu")]), - }, - ] - } -} - -#[derive(Clone)] -struct Substring(isize, isize); - -impl From<(isize, isize)> for Substring { - fn from(input: (isize, isize)) -> Substring { - Substring(input.0, input.1) - } -} - -struct SubstringText(String, String); - -fn operate(args: CommandArgs) -> Result { - let name = args.call_info.name_tag.clone(); - - let (options, input) = ( - Arguments { - range: args.req(0)?, - column_paths: args.rest(1)?, - }, - args.input, - ); - - let indexes = Arc::new(process_arguments(&options, name)?.into()); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &indexes, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let indexes = indexes.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &indexes, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, options: &Substring, tag: impl Into) -> Result { - let tag = tag.into(); - - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let len: isize = s.len().try_into().map_err(|_| { - ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - tag.span, - ) - })?; - - let start: isize = if options.0 < 0 { - options.0 + len - } else { - options.0 - }; - let end: isize = if options.1 < 0 { - std::cmp::max(len + options.1, 0) - } else { - options.1 - }; - - if start < len && end >= 0 { - match start.cmp(&end) { - Ordering::Equal => Ok(UntaggedValue::string("").into_value(tag)), - Ordering::Greater => Err(ShellError::labeled_error( - "End must be greater than or equal to Start", - "End must be greater than or equal to Start", - tag.span, - )), - Ordering::Less => Ok(UntaggedValue::string(if end == isize::max_value() { - s.chars().skip(start as usize).collect::() - } else { - s.chars() - .skip(start as usize) - .take((end - start) as usize) - .collect::() - }) - .into_value(tag)), - } - } else { - Ok(UntaggedValue::string("").into_value(tag)) - } - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.span, - )) - } - } -} - -fn process_arguments( - options: &Arguments, - name: impl Into, -) -> Result<(isize, isize), ShellError> { - let name = name.into(); - - let search = match &options.range.value { - UntaggedValue::Table(indexes) => { - if indexes.len() > 2 { - Err(ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - )) - } else { - let idx: Vec = indexes - .iter() - .map(|v| as_string(v).unwrap_or_else(|_| String::from(""))) - .collect(); - - let start = idx - .get(0) - .ok_or_else(|| { - ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - ) - })? - .to_string(); - let end = idx - .get(1) - .ok_or_else(|| { - ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - ) - })? - .to_string(); - - Ok(SubstringText(start, end)) - } - } - UntaggedValue::Primitive(Primitive::String(indexes)) => { - let idx: Vec<&str> = indexes.split(',').collect(); - - let start = idx - .get(0) - .ok_or_else(|| { - ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - ) - })? - .to_string(); - let end = idx - .get(1) - .ok_or_else(|| { - ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - ) - })? - .to_string(); - - Ok(SubstringText(start, end)) - } - _ => Err(ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - )), - }?; - - let start = match &search { - SubstringText(start, _) if start.is_empty() || start == "_" => 0, - SubstringText(start, _) => start.trim().parse().map_err(|_| { - ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - ) - })?, - }; - - let end = match &search { - SubstringText(_, end) if end.is_empty() || end == "_" => isize::max_value(), - SubstringText(_, end) => end.trim().parse().map_err(|_| { - ShellError::labeled_error( - "could not perform substring", - "could not perform substring", - name.span, - ) - })?, - }; - - Ok((start, end)) -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand, Substring}; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - struct Expectation<'a> { - options: (isize, isize), - expected: &'a str, - } - - impl Expectation<'_> { - fn options(&self) -> Substring { - Substring(self.options.0, self.options.1) - } - } - - fn expectation(word: &str, indexes: (isize, isize)) -> Expectation { - Expectation { - options: indexes, - expected: word, - } - } - - #[test] - fn substrings_indexes() { - let word = string("andres"); - - let cases = vec![ - expectation("a", (0, 1)), - expectation("an", (0, 2)), - expectation("and", (0, 3)), - expectation("andr", (0, 4)), - expectation("andre", (0, 5)), - expectation("andres", (0, 6)), - expectation("", (0, -6)), - expectation("a", (0, -5)), - expectation("an", (0, -4)), - expectation("and", (0, -3)), - expectation("andr", (0, -2)), - expectation("andre", (0, -1)), - // str substring [ -4 , _ ] - // str substring -4 , - expectation("dres", (-4, isize::max_value())), - expectation("", (0, -110)), - expectation("", (6, 0)), - expectation("", (6, -1)), - expectation("", (6, -2)), - expectation("", (6, -3)), - expectation("", (6, -4)), - expectation("", (6, -5)), - expectation("", (6, -6)), - ]; - - for expectation in &cases { - let expected = expectation.expected; - let actual = action(&word, &expectation.options(), Tag::unknown()).unwrap(); - - assert_eq!(actual, string(expected)); - } - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/to_datetime.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/to_datetime.rs deleted file mode 100644 index d88b1337a..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/to_datetime.rs +++ /dev/null @@ -1,373 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, ShellTypeName, Signature, SyntaxShape, UntaggedValue, - Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; - -use chrono::{DateTime, FixedOffset, Local, LocalResult, Offset, TimeZone, Utc}; - -struct Arguments { - timezone: Option>, - offset: Option>, - format: Option>, - column_paths: Vec, -} - -// In case it may be confused with chrono::TimeZone -#[derive(Clone)] -enum Zone { - Utc, - Local, - East(u8), - West(u8), - Error, // we want the nullshell to cast it instead of rust -} - -impl Zone { - fn new(i: i16) -> Self { - if i.abs() <= 12 { - // guanranteed here - if i >= 0 { - Self::East(i as u8) // won't go out of range - } else { - Self::West(-i as u8) // same here - } - } else { - Self::Error // Out of range - } - } - fn from_string(s: String) -> Self { - match s.to_lowercase().as_str() { - "utc" | "u" => Self::Utc, - "local" | "l" => Self::Local, - _ => Self::Error, - } - } -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str to-datetime" - } - - fn signature(&self) -> Signature { - Signature::build("str to-datetime") - .named( - "timezone", - SyntaxShape::String, - "Specify timezone if the input is timestamp, like 'UTC/u' or 'LOCAL/l'", - Some('z'), - ) - .named( - "offset", - SyntaxShape::Int, - "Specify timezone by offset if the input is timestamp, like '+8', '-4', prior than timezone", - Some('o'), - ) - .named( - "format", - SyntaxShape::String, - "Specify date and time formatting", - Some('f'), - ) - .rest( -"rest", - SyntaxShape::Any, - "optionally convert text into datetime by column paths", - ) - } - - fn usage(&self) -> &str { - "converts text into datetime" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert to datetime", - example: "echo '16.11.1984 8:00 am +0000' | str to-datetime", - result: None, - }, - Example { - description: "Convert to datetime", - example: "echo '2020-08-04T16:39:18+00:00' | str to-datetime", - result: None, - }, - Example { - description: "Convert to datetime using a custom format", - example: "echo '20200904_163918+0000' | str to-datetime -f '%Y%m%d_%H%M%S%z'", - result: None, - }, - Example { - description: "Convert timestamp (no larger than 8e+12) to datetime using a specified timezone", - example: "echo '1614434140' | str to-datetime -z 'UTC'", - result: None, - }, - Example { - description: - "Convert timestamp (no larger than 8e+12) to datetime using a specified timezone offset (between -12 and 12)", - example: "echo '1614434140' | str to-datetime -o '+9'", - result: None, - }, - ] - } -} - -#[derive(Clone)] -struct DatetimeFormat(String); - -fn operate(args: CommandArgs) -> Result { - let options = Arguments { - timezone: args.get_flag("timezone")?, - offset: args.get_flag("offset")?, - format: args.get_flag("format")?, - column_paths: args.rest(0)?, - }; - let input = args.input; - - // if zone-offset is specified, then zone will be neglected - let zone_options = if let Some(Tagged { - item: zone_offset, - tag, - }) = &options.offset - { - Some(Tagged { - item: Zone::new(*zone_offset), - tag: tag.into(), - }) - } else if let Some(Tagged { item: zone, tag }) = &options.timezone { - Some(Tagged { - item: Zone::from_string(zone.clone()), - tag: tag.into(), - }) - } else { - None - }; - - let format_options = if let Some(Tagged { item: fmt, .. }) = &options.format { - Some(DatetimeFormat(fmt.to_string())) - } else { - None - }; - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, &zone_options, &format_options, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - let zone_options = zone_options.clone(); - let format_options = format_options.clone(); - - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, &zone_options, &format_options, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action( - input: &Value, - timezone: &Option>, - dateformat: &Option, - tag: impl Into, -) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let ts = s.parse::(); - // if timezone if specified, first check if the input is a timestamp. - if let Some(tz) = timezone { - const TIMESTAMP_BOUND: i64 = 8.2e+12 as i64; - // Since the timestamp method of chrono itself don't throw an error (it just panicked) - // We have to manually guard it. - if let Ok(t) = ts { - if t.abs() > TIMESTAMP_BOUND { - return Err(ShellError::labeled_error( - "could not parse input as a valid timestamp", - "given timestamp is out of range, it should between -8e+12 and 8e+12", - tag.into().span, - )); - } - const HOUR: i32 = 3600; - let stampout = match tz.item { - Zone::Utc => UntaggedValue::date(Utc.timestamp(t, 0)), - Zone::Local => UntaggedValue::date(Local.timestamp(t, 0)), - Zone::East(i) => { - let eastoffset = FixedOffset::east((i as i32) * HOUR); - UntaggedValue::date(eastoffset.timestamp(t, 0)) - } - Zone::West(i) => { - let westoffset = FixedOffset::west((i as i32) * HOUR); - UntaggedValue::date(westoffset.timestamp(t, 0)) - } - Zone::Error => { - return Err(ShellError::labeled_error( - "could not continue to convert timestamp", - "given timezone or offset is invalid", - tz.tag().span, - )); - } - }; - return Ok(stampout.into_value(tag)); - } - }; - // if it's not, continue and negelect the timezone option. - let out = match dateformat { - Some(dt) => match DateTime::parse_from_str(s, &dt.0) { - Ok(d) => UntaggedValue::date(d), - Err(reason) => { - return Err(ShellError::labeled_error( - format!("could not parse as datetime using format '{}'", dt.0), - reason.to_string(), - tag.into().span, - )) - } - }, - None => match dtparse::parse(s) { - Ok((native_dt, fixed_offset)) => { - let offset = match fixed_offset { - Some(fo) => fo, - None => FixedOffset::east(0).fix(), - }; - match offset.from_local_datetime(&native_dt) { - LocalResult::Single(d) => UntaggedValue::date(d), - LocalResult::Ambiguous(d, _) => UntaggedValue::date(d), - LocalResult::None => { - return Err(ShellError::labeled_error( - "could not convert to a timezone-aware datetime", - "local time representation is invalid", - tag.into().span, - )) - } - } - } - Err(reason) => { - return Err(ShellError::labeled_error( - "could not parse as datetime", - reason.to_string(), - tag.into().span, - )) - } - }, - }; - - Ok(out.into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, DatetimeFormat, SubCommand, Zone}; - use nu_protocol::{Primitive, UntaggedValue}; - use nu_source::{Tag, Tagged}; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn takes_a_date_format() { - let date_str = string("16.11.1984 8:00 am +0000"); - - let fmt_options = Some(DatetimeFormat("%d.%m.%Y %H:%M %P %z".to_string())); - - let actual = action(&date_str, &None, &fmt_options, Tag::unknown()).unwrap(); - - match actual.value { - UntaggedValue::Primitive(Primitive::Date(_)) => {} - _ => panic!("Didn't convert to date"), - } - } - - #[test] - fn takes_iso8601_date_format() { - let date_str = string("2020-08-04T16:39:18+00:00"); - let actual = action(&date_str, &None, &None, Tag::unknown()).unwrap(); - match actual.value { - UntaggedValue::Primitive(Primitive::Date(_)) => {} - _ => panic!("Didn't convert to date"), - } - } - - #[test] - fn takes_timestamp_offset() { - let date_str = string("1614434140"); - let timezone_option = Some(Tagged { - item: Zone::East(8), - tag: Tag::unknown(), - }); - let actual = action(&date_str, &timezone_option, &None, Tag::unknown()).unwrap(); - match actual.value { - UntaggedValue::Primitive(Primitive::Date(_)) => {} - _ => panic!("Didn't convert to date"), - } - } - - #[test] - fn takes_timestamp() { - let date_str = string("1614434140"); - let timezone_option = Some(Tagged { - item: Zone::Local, - tag: Tag::unknown(), - }); - let actual = action(&date_str, &timezone_option, &None, Tag::unknown()).unwrap(); - match actual.value { - UntaggedValue::Primitive(Primitive::Date(_)) => {} - _ => panic!("Didn't convert to date"), - } - } - - #[test] - fn takes_invalid_timestamp() { - let date_str = string("10440970000000"); - let timezone_option = Some(Tagged { - item: Zone::Utc, - tag: Tag::unknown(), - }); - let actual = action(&date_str, &timezone_option, &None, Tag::unknown()); - - assert!(actual.is_err()); - } - - #[test] - fn communicates_parsing_error_given_an_invalid_datetimelike_string() { - let date_str = string("16.11.1984 8:00 am Oops0000"); - - let fmt_options = Some(DatetimeFormat("%d.%m.%Y %H:%M %P %z".to_string())); - - let actual = action(&date_str, &None, &fmt_options, Tag::unknown()); - - assert!(actual.is_err()); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/to_decimal.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/to_decimal.rs deleted file mode 100644 index a61779e59..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/to_decimal.rs +++ /dev/null @@ -1,137 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tag; -use nu_value_ext::ValueExt; - -use bigdecimal::BigDecimal; -use std::str::FromStr; - -struct Arguments { - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str to-decimal" - } - - fn signature(&self) -> Signature { - Signature::build("str to-decimal").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert text into decimal by column paths", - ) - } - - fn usage(&self) -> &str { - "converts text into decimal" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Convert to decimal", - example: "echo '3.1415' | str to-decimal", - result: None, - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arguments { - column_paths: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let other = s.trim(); - let out = match BigDecimal::from_str(other) { - Ok(v) => UntaggedValue::decimal(v), - Err(reason) => { - return Err(ShellError::labeled_error( - "could not parse as decimal", - reason.to_string(), - tag.into().span, - )) - } - }; - Ok(out.into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_source::Tag; - use nu_test_support::value::{decimal_from_float, string}; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - #[allow(clippy::approx_constant)] - fn turns_to_integer() { - let word = string("3.1415"); - let expected = decimal_from_float(3.1415); - - let actual = action(&word, Tag::unknown()).unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn communicates_parsing_error_given_an_invalid_decimallike_string() { - let decimal_str = string("11.6anra"); - - let actual = action(&decimal_str, Tag::unknown()); - - assert!(actual.is_err()); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/to_integer.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/to_integer.rs deleted file mode 100644 index 5d976dac6..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/to_integer.rs +++ /dev/null @@ -1,201 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; - -struct Arguments { - radix: Option>, - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str to-int" - } - - fn signature(&self) -> Signature { - Signature::build("str to-int") - .named("radix", SyntaxShape::Number, "radix of integer", Some('r')) - .rest( - "rest", - SyntaxShape::ColumnPath, - "optionally convert text into integer by column paths", - ) - } - - fn usage(&self) -> &str { - "converts text into integer" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Convert to an integer", - example: "echo '255' | str to-int", - result: Some(vec![UntaggedValue::int(255).into()]), - }, - Example { - description: "Convert str column to an integer", - example: "echo [['count']; ['255']] | str to-int count | get count", - result: Some(vec![UntaggedValue::int(255).into()]), - }, - Example { - description: "Convert to integer from binary", - example: "echo '1101' | str to-int -r 2", - result: Some(vec![UntaggedValue::int(13).into()]), - }, - Example { - description: "Convert to integer from hex", - example: "echo 'FF' | str to-int -r 16", - result: Some(vec![UntaggedValue::int(255).into()]), - }, - ] - } -} - -fn operate(args: CommandArgs) -> Result { - let options = Arguments { - radix: args.get_flag("radix")?, - column_paths: args.rest(0)?, - }; - let input = args.input; - - let radix = options.radix.as_ref().map(|r| r.item).unwrap_or(10); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, v.tag(), radix)?) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag(), radix)), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, tag: impl Into, radix: u32) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - let trimmed = s.trim(); - - let out = match trimmed { - b if b.starts_with("0b") => { - let num = match i64::from_str_radix(b.trim_start_matches("0b"), 2) { - Ok(n) => n, - Err(reason) => { - return Err(ShellError::labeled_error( - "could not parse as integer", - reason.to_string(), - tag.into().span, - )) - } - }; - UntaggedValue::int(num) - } - h if h.starts_with("0x") => { - let num = match i64::from_str_radix(h.trim_start_matches("0x"), 16) { - Ok(n) => n, - Err(reason) => { - return Err(ShellError::labeled_error( - "could not parse as int", - reason.to_string(), - tag.into().span, - )) - } - }; - UntaggedValue::int(num) - } - _ => { - let num = match i64::from_str_radix(trimmed, radix) { - Ok(n) => n, - Err(reason) => { - return Err(ShellError::labeled_error( - "could not parse as int", - reason.to_string(), - tag.into().span, - )) - } - }; - UntaggedValue::int(num) - } - }; - - Ok(out.into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_source::Tag; - use nu_test_support::value::{int, string}; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn turns_to_integer() { - let word = string("10"); - let expected = int(10); - - let actual = action(&word, Tag::unknown(), 10).unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn turns_binary_to_integer() { - let s = string("0b101"); - let actual = action(&s, Tag::unknown(), 10).unwrap(); - assert_eq!(actual, int(5)); - } - - #[test] - fn turns_hex_to_integer() { - let s = string("0xFF"); - let actual = action(&s, Tag::unknown(), 16).unwrap(); - assert_eq!(actual, int(255)); - } - - #[test] - fn communicates_parsing_error_given_an_invalid_integerlike_string() { - let integer_str = string("36anra"); - - let actual = action(&integer_str, Tag::unknown(), 10); - - assert!(actual.is_err()); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/trim/command.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/trim/command.rs deleted file mode 100644 index a0898acb9..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/trim/command.rs +++ /dev/null @@ -1,851 +0,0 @@ -use super::operate; -use crate::commands::strings::str_::trim::ClosureFlags; -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, Value}; -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str trim" - } - - fn signature(&self) -> Signature { - Signature::build("str trim") - .rest( -"rest", - SyntaxShape::ColumnPath, - "optionally trim text by column paths", - ) - .named( - "char", - SyntaxShape::String, - "character to trim (default: whitespace)", - Some('c'), - ) - .switch( - "left", - "trims characters only from the beginning of the string (default: whitespace)", - Some('l'), - ) - .switch( - "right", - "trims characters only from the end of the string (default: whitespace)", - Some('r'), - ) - .switch( - "all", - "trims all characters from both sides of the string *and* in the middle (default: whitespace)", - Some('a'), - ) - .switch("both", "trims all characters from left and right side of the string (default: whitespace)", Some('b')) - .switch("format", "trims spaces replacing multiple characters with singles in the middle (default: whitespace)", Some('f')) - } - fn usage(&self) -> &str { - "trims text" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args, &trim) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Trim whitespace", - example: "echo 'Nu shell ' | str trim", - result: Some(vec![Value::from("Nu shell")]), - }, - Example { - description: "Trim a specific character", - example: "echo '=== Nu shell ===' | str trim -c '=' | str trim", - result: Some(vec![Value::from("Nu shell")]), - }, - Example { - description: "Trim all characters", - example: "echo ' Nu shell ' | str trim -a", - result: Some(vec![Value::from("Nushell")]), - }, - Example { - description: "Trim whitespace from the beginning of string", - example: "echo ' Nu shell ' | str trim -l", - result: Some(vec![Value::from("Nu shell ")]), - }, - Example { - description: "Trim a specific character", - example: "echo '=== Nu shell ===' | str trim -c '='", - result: Some(vec![Value::from(" Nu shell ")]), - }, - Example { - description: "Trim whitespace from the end of string", - example: "echo ' Nu shell ' | str trim -r", - result: Some(vec![Value::from(" Nu shell")]), - }, - Example { - description: "Trim a specific character", - example: "echo '=== Nu shell ===' | str trim -r -c '='", - result: Some(vec![Value::from("=== Nu shell ")]), - }, - ] - } -} - -fn trim(s: &str, char_: Option, closure_flags: &ClosureFlags) -> String { - let ClosureFlags { - left_trim, - right_trim, - all_flag, - both_flag, - format_flag, - } = closure_flags; - let delimiters = match char_ { - Some(c) => vec![c], - // Trying to make this trim work like rust default trim() - // which uses is_whitespace() as a default - None => vec![ - ' ', // space - '\x09', // horizontal tab - '\x0A', // new line, line feed - '\x0B', // vertical tab - '\x0C', // form feed, new page - '\x0D', // carriage return - ], //whitespace - }; - - if *left_trim { - s.trim_start_matches(&delimiters[..]).to_string() - } else if *right_trim { - s.trim_end_matches(&delimiters[..]).to_string() - } else if *all_flag { - s.split(&delimiters[..]) - .filter(|s| !s.is_empty()) - .collect::() - } else if *both_flag { - s.trim_matches(&delimiters[..]).to_string() - } else if *format_flag { - // The idea here is to use regex to go through these delimiters and - // where there are multiple, replace them with singles - - // create our return string which is a copy of the original string - let mut return_string = String::from(s); - // Iterate through the delimiters replacing them with regex friendly names - for r in &delimiters { - let reg = match r { - ' ' => r"\s".to_string(), - '\x09' => r"\t".to_string(), - '\x0A' => r"\n".to_string(), - '\x0B' => r"\v".to_string(), - '\x0C' => r"\f".to_string(), - '\x0D' => r"\r".to_string(), - _ => format!(r"\{}", r), - }; - // create a regex string that looks for 2 or more of each of these characters - let re_str = format!("{}{{2,}}", reg); - // create the regex - let re = regex::Regex::new(&re_str).expect("Error creating regular expression"); - // replace all multiple occurrences with single occurrences represented by r - let new_str = re.replace_all(&return_string, r.to_string()); - // update the return string so the next loop has the latest changes - return_string = new_str.to_string(); - } - // for good measure, trim_matches, which gets the start and end - // theoretically we shouldn't have to do this but from my testing, we do. - return_string.trim_matches(&delimiters[..]).to_string() - } else { - s.trim().to_string() - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::SubCommand; - use crate::commands::strings::str_::trim::command::trim; - use crate::commands::strings::str_::trim::{action, ActionMode, ClosureFlags}; - use nu_protocol::row; - use nu_source::Tag; - use nu_test_support::value::{int, string, table}; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - test_examples(SubCommand {}) - } - - #[test] - fn trims() { - let word = string("andres "); - let expected = string("andres"); - let closure_flags = ClosureFlags { - both_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_global() { - let word = string(" global "); - let expected = string("global"); - let closure_flags = ClosureFlags { - both_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_ignores_numbers() { - let number = int(2020); - let expected = int(2020); - let closure_flags = ClosureFlags { - both_flag: true, - ..Default::default() - }; - - let actual = action( - &number, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_row() { - let row = row!["a".to_string() => string(" c "), " b ".to_string() => string(" d ")]; - let expected = row!["a".to_string() => string("c"), " b ".to_string() => string("d")]; - let closure_flags = ClosureFlags { - both_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_table() { - let row = table(&[string(" a "), int(65), string(" d")]); - let expected = table(&[string("a"), int(65), string("d")]); - let closure_flags = ClosureFlags { - both_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_custom_character_both_ends() { - let word = string("!#andres#!"); - let expected = string("#andres#"); - let closure_flags = ClosureFlags { - both_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some('!'), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn trims_all_white_space() { - let word = string(" Value1 a lot of spaces "); - let expected = string("Value1alotofspaces"); - let closure_flags = ClosureFlags { - all_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some(' '), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trims_row_all_white_space() { - let row = row!["a".to_string() => string(" nu shell "), " b ".to_string() => string(" b c d e ")]; - let expected = - row!["a".to_string() => string("nushell"), " b ".to_string() => string("bcde")]; - let closure_flags = ClosureFlags { - all_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trims_table_all_white_space() { - let row = table(&[string(" nu shell "), int(65), string(" d")]); - let expected = table(&[string("nushell"), int(65), string("d")]); - let closure_flags = ClosureFlags { - all_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_all_custom_character() { - let word = string(".Value1.a.lot..of...dots."); - let expected = string("Value1alotofdots"); - let closure_flags = ClosureFlags { - all_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some('.'), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trims_row_all_custom_character() { - let row = row!["a".to_string() => string("!!!!nu!!shell!!!"), " b ".to_string() => string("!!b!c!!d!e!!")]; - let expected = - row!["a".to_string() => string("nushell"), " b ".to_string() => string("bcde")]; - let closure_flags = ClosureFlags { - all_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - Some('!'), - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trims_table_all_custom_character() { - let row = table(&[string("##nu####shell##"), int(65), string("#d")]); - let expected = table(&[string("nushell"), int(65), string("d")]); - let closure_flags = ClosureFlags { - all_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - Some('#'), - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn trims_whitespace_from_left() { - let word = string(" andres "); - let expected = string("andres "); - let closure_flags = ClosureFlags { - left_trim: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_left_ignores_numbers() { - let number = int(2020); - let expected = int(2020); - let closure_flags = ClosureFlags { - left_trim: true, - ..Default::default() - }; - - let actual = action( - &number, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_left_global() { - let word = string(" global "); - let expected = string("global "); - let closure_flags = ClosureFlags { - left_trim: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_left_row() { - let row = row!["a".to_string() => string(" c "), " b ".to_string() => string(" d ")]; - let expected = row!["a".to_string() => string("c "), " b ".to_string() => string("d ")]; - let closure_flags = ClosureFlags { - left_trim: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_left_table() { - let row = table(&[string(" a "), int(65), string(" d")]); - let expected = table(&[string("a "), int(65), string("d")]); - let closure_flags = ClosureFlags { - left_trim: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_custom_chars_from_left() { - let word = string("!!! andres !!!"); - let expected = string(" andres !!!"); - let closure_flags = ClosureFlags { - left_trim: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some('!'), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn trims_whitespace_from_right() { - let word = string(" andres "); - let expected = string(" andres"); - let closure_flags = ClosureFlags { - right_trim: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_right_global() { - let word = string(" global "); - let expected = string(" global"); - let closure_flags = ClosureFlags { - right_trim: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_right_ignores_numbers() { - let number = int(2020); - let expected = int(2020); - let closure_flags = ClosureFlags { - right_trim: true, - ..Default::default() - }; - - let actual = action( - &number, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_right_row() { - let row = row!["a".to_string() => string(" c "), " b ".to_string() => string(" d ")]; - let expected = row!["a".to_string() => string(" c"), " b ".to_string() => string(" d")]; - let closure_flags = ClosureFlags { - right_trim: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_right_table() { - let row = table(&[string(" a "), int(65), string(" d")]); - let expected = table(&[string(" a"), int(65), string(" d")]); - let closure_flags = ClosureFlags { - right_trim: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_custom_chars_from_right() { - let word = string("#@! andres !@#"); - let expected = string("#@! andres !@"); - let closure_flags = ClosureFlags { - right_trim: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some('#'), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_whitespace_format_flag() { - let word = string(" nushell is great "); - let expected = string("nushell is great"); - let closure_flags = ClosureFlags { - format_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some(' '), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_format_flag_global() { - let word = string("global "); - let expected = string("global"); - let closure_flags = ClosureFlags { - format_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some(' '), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - #[test] - fn global_trim_format_flag_ignores_numbers() { - let number = int(2020); - let expected = int(2020); - let closure_flags = ClosureFlags { - format_flag: true, - ..Default::default() - }; - - let actual = action( - &number, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_format_flag_row() { - let row = row!["a".to_string() => string(" c "), " b ".to_string() => string(" b c d e ")]; - let expected = row!["a".to_string() => string("c"), " b ".to_string() => string("b c d e")]; - let closure_flags = ClosureFlags { - format_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn global_trim_format_flag_table() { - let row = table(&[ - string(" a b c d "), - int(65), - string(" b c d e f"), - ]); - let expected = table(&[string("a b c d"), int(65), string("b c d e f")]); - let closure_flags = ClosureFlags { - format_flag: true, - ..Default::default() - }; - - let actual = action( - &row, - Tag::unknown(), - None, - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_custom_chars_format_flag() { - let word = string(".Value1.a..lot...of....dots."); - let expected = string("Value1.a.lot.of.dots"); - let closure_flags = ClosureFlags { - format_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some('.'), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_all_format_flag_whitespace() { - let word = string(" nushell is great "); - let expected = string("nushellisgreat"); - let closure_flags = ClosureFlags { - format_flag: true, - all_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some(' '), - &closure_flags, - &trim, - ActionMode::Local, - ) - .unwrap(); - assert_eq!(actual, expected); - } - - #[test] - fn trims_all_format_flag_global() { - let word = string(" nushell is great "); - let expected = string("nushellisgreat"); - let closure_flags = ClosureFlags { - format_flag: true, - all_flag: true, - ..Default::default() - }; - - let actual = action( - &word, - Tag::unknown(), - Some(' '), - &closure_flags, - &trim, - ActionMode::Global, - ) - .unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/trim/mod.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/trim/mod.rs deleted file mode 100644 index 115b3572d..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/trim/mod.rs +++ /dev/null @@ -1,144 +0,0 @@ -mod command; -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ColumnPath, Primitive, ReturnSuccess, UntaggedValue, Value}; -use nu_source::{Tag, Tagged}; -use nu_value_ext::ValueExt; -use std::iter::FromIterator; - -pub use command::SubCommand as Trim; - -struct Arguments { - character: Option>, - column_paths: Vec, -} - -#[derive(Default, Debug, Copy, Clone)] -pub struct ClosureFlags { - all_flag: bool, - left_trim: bool, - right_trim: bool, - format_flag: bool, - both_flag: bool, -} - -pub fn operate(args: CommandArgs, trim_operation: &'static F) -> Result -where - F: Fn(&str, Option, &ClosureFlags) -> String + Send + Sync + 'static, -{ - let (options, closure_flags, input) = ( - Arc::new(Arguments { - character: args.get_flag("char")?, - column_paths: args.rest(0)?, - }), - ClosureFlags { - all_flag: args.has_flag("all"), - left_trim: args.has_flag("left"), - right_trim: args.has_flag("right"), - format_flag: args.has_flag("format"), - both_flag: args.has_flag("both") - || (!args.has_flag("all") - && !args.has_flag("left") - && !args.has_flag("right") - && !args.has_flag("format")), // this is the case if no flags are provided - }, - args.input, - ); - let to_trim = options.character.as_ref().map(|tagged| tagged.item); - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action( - &v, - v.tag(), - to_trim, - &closure_flags, - &trim_operation, - ActionMode::Global, - )?) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| { - action( - old, - old.tag(), - to_trim, - &closure_flags, - &trim_operation, - ActionMode::Local, - ) - }), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -#[derive(Debug, Copy, Clone)] -pub enum ActionMode { - Local, - Global, -} - -pub fn action( - input: &Value, - tag: impl Into, - char_: Option, - closure_flags: &ClosureFlags, - trim_operation: &F, - mode: ActionMode, -) -> Result -where - F: Fn(&str, Option, &ClosureFlags) -> String + Send + Sync + 'static, -{ - let tag = tag.into(); - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - Ok(UntaggedValue::string(trim_operation(s, char_, closure_flags)).into_value(tag)) - } - other => match mode { - ActionMode::Global => match other { - UntaggedValue::Row(dictionary) => { - let results: Result, ShellError> = dictionary - .entries() - .iter() - .map(|(k, v)| -> Result<_, ShellError> { - Ok(( - k.clone(), - action(v, tag.clone(), char_, closure_flags, trim_operation, mode)?, - )) - }) - .collect(); - let indexmap = IndexMap::from_iter(results?); - Ok(UntaggedValue::Row(indexmap.into()).into_value(tag)) - } - UntaggedValue::Table(values) => { - let values: Result, ShellError> = values - .iter() - .map(|v| -> Result<_, ShellError> { - action(v, tag.clone(), char_, closure_flags, trim_operation, mode) - }) - .collect(); - Ok(UntaggedValue::Table(values?).into_value(tag)) - } - _ => Ok(input.clone()), - }, - ActionMode::Local => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.span, - )) - } - }, - } -} diff --git a/old_nushell/crates/nu-command/src/commands/strings/str_/upcase.rs b/old_nushell/crates/nu-command/src/commands/strings/str_/upcase.rs deleted file mode 100644 index 285e55ee3..000000000 --- a/old_nushell/crates/nu-command/src/commands/strings/str_/upcase.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::prelude::*; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::ShellTypeName; -use nu_protocol::{ - ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::Tag; -use nu_value_ext::ValueExt; - -struct Arguments { - column_paths: Vec, -} - -pub struct SubCommand; - -impl WholeStreamCommand for SubCommand { - fn name(&self) -> &str { - "str upcase" - } - - fn signature(&self) -> Signature { - Signature::build("str upcase").rest( - "rest", - SyntaxShape::ColumnPath, - "optionally upcase text by column paths", - ) - } - - fn usage(&self) -> &str { - "upcases text" - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - operate(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Upcase contents", - example: "echo 'nu' | str upcase", - result: Some(vec![Value::from("NU")]), - }] - } -} - -fn operate(args: CommandArgs) -> Result { - let (options, input) = ( - Arguments { - column_paths: args.rest(0)?, - }, - args.input, - ); - - Ok(input - .map(move |v| { - if options.column_paths.is_empty() { - ReturnSuccess::value(action(&v, v.tag())?) - } else { - let mut ret = v; - - for path in &options.column_paths { - ret = ret.swap_data_by_column_path( - path, - Box::new(move |old| action(old, old.tag())), - )?; - } - - ReturnSuccess::value(ret) - } - }) - .into_action_stream()) -} - -fn action(input: &Value, tag: impl Into) -> Result { - match &input.value { - UntaggedValue::Primitive(Primitive::String(s)) => { - Ok(UntaggedValue::string(s.to_ascii_uppercase()).into_value(tag)) - } - other => { - let got = format!("got {}", other.type_name()); - Err(ShellError::labeled_error( - "value is not string", - got, - tag.into().span, - )) - } - } -} - -#[cfg(test)] -mod tests { - use super::ShellError; - use super::{action, SubCommand}; - use nu_source::Tag; - use nu_test_support::value::string; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(SubCommand {}) - } - - #[test] - fn upcases() { - let word = string("andres"); - - let actual = action(&word, Tag::unknown()).unwrap(); - assert_eq!(actual, string("ANDRES")); - } -} diff --git a/old_nushell/crates/nu-command/src/commands/system/mod.rs b/old_nushell/crates/nu-command/src/commands/system/mod.rs deleted file mode 100644 index 6fd20a936..000000000 --- a/old_nushell/crates/nu-command/src/commands/system/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[cfg(feature = "ps")] -mod ps; -#[cfg(feature = "ps")] -pub use ps::Command as Ps; - -#[cfg(feature = "sys")] -mod sys; -#[cfg(feature = "sys")] -pub use sys::Command as Sys; diff --git a/old_nushell/crates/nu-command/src/commands/system/ps.rs b/old_nushell/crates/nu-command/src/commands/system/ps.rs deleted file mode 100644 index aca2c62c5..000000000 --- a/old_nushell/crates/nu-command/src/commands/system/ps.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{Signature, TaggedDictBuilder, UntaggedValue}; -use sysinfo::{PidExt, ProcessExt, System, SystemExt}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "ps" - } - - fn signature(&self) -> Signature { - Signature::build("ps") - .desc("View information about system processes.") - .switch( - "long", - "list all available columns for each entry", - Some('l'), - ) - .filter() - } - - fn usage(&self) -> &str { - "View information about system processes." - } - - fn run(&self, args: CommandArgs) -> Result { - run_ps(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "List the system processes", - example: "ps", - result: None, - }] - } -} - -fn run_ps(args: CommandArgs) -> Result { - let long = args.has_flag("long"); - let mut sys = System::new_all(); - sys.refresh_all(); - - let mut output = vec![]; - - let result: Vec<_> = sys.processes().iter().map(|x| *x.0).collect(); - - for pid in result { - if let Some(result) = sys.process(pid) { - let mut dict = TaggedDictBuilder::new(args.name_tag()); - dict.insert_untagged("pid", UntaggedValue::int(pid.as_u32() as i64)); - dict.insert_untagged("name", UntaggedValue::string(result.name())); - dict.insert_untagged( - "status", - UntaggedValue::string(format!("{:?}", result.status())), - ); - dict.insert_untagged( - "cpu", - UntaggedValue::decimal_from_float(result.cpu_usage() as f64, args.name_tag().span), - ); - dict.insert_untagged("mem", UntaggedValue::filesize(result.memory() * 1000)); - dict.insert_untagged( - "virtual", - UntaggedValue::filesize(result.virtual_memory() * 1000), - ); - - if long { - if let Some(parent) = result.parent() { - dict.insert_untagged("parent", UntaggedValue::int(parent.as_u32() as i64)); - } else { - dict.insert_untagged("parent", UntaggedValue::nothing()); - } - dict.insert_untagged("exe", UntaggedValue::filepath(result.exe())); - dict.insert_untagged("command", UntaggedValue::string(result.cmd().join(" "))); - } - - output.push(dict.into_value()); - } - } - - Ok(output.into_iter().into_output_stream()) -} diff --git a/old_nushell/crates/nu-command/src/commands/system/sys.rs b/old_nushell/crates/nu-command/src/commands/system/sys.rs deleted file mode 100644 index 9ca64f515..000000000 --- a/old_nushell/crates/nu-command/src/commands/system/sys.rs +++ /dev/null @@ -1,248 +0,0 @@ -use crate::prelude::*; -use nu_errors::ShellError; -use nu_protocol::{Signature, TaggedDictBuilder, UntaggedValue}; -use sysinfo::{ComponentExt, DiskExt, NetworkExt, ProcessorExt, System, SystemExt, UserExt}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "sys" - } - - fn signature(&self) -> Signature { - Signature::build("sys") - .desc("View information about the current system.") - .filter() - } - - fn usage(&self) -> &str { - "View information about the system." - } - - fn run(&self, args: CommandArgs) -> Result { - run_sys(args) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Show info about the system", - example: "sys", - result: None, - }] - } -} - -fn run_sys(args: CommandArgs) -> Result { - let tag = args.name_tag(); - let mut sys = System::new(); - - let mut sysinfo = TaggedDictBuilder::with_capacity(&tag, 6); - - if let Some(host) = host(&mut sys, tag.clone()) { - sysinfo.insert_value("host", host); - } - if let Some(cpus) = cpu(&mut sys, tag.clone()) { - sysinfo.insert_value("cpu", cpus); - } - if let Some(disks) = disks(&mut sys, tag.clone()) { - sysinfo.insert_value("disks", disks); - } - if let Some(mem) = mem(&mut sys, tag.clone()) { - sysinfo.insert_value("mem", mem); - } - if let Some(temp) = temp(&mut sys, tag.clone()) { - sysinfo.insert_value("temp", temp); - } - if let Some(net) = net(&mut sys, tag) { - sysinfo.insert_value("net", net); - } - - Ok(vec![sysinfo.into_value()].into_iter().into_output_stream()) -} - -pub fn trim_cstyle_null(s: String) -> String { - s.trim_matches(char::from(0)).to_string() -} - -pub fn disks(sys: &mut System, tag: Tag) -> Option { - sys.refresh_disks(); - sys.refresh_disks_list(); - - let mut output = vec![]; - for disk in sys.disks() { - let mut dict = TaggedDictBuilder::new(&tag); - dict.insert_untagged( - "device", - UntaggedValue::string(trim_cstyle_null(disk.name().to_string_lossy().to_string())), - ); - dict.insert_untagged( - "type", - UntaggedValue::string(trim_cstyle_null( - String::from_utf8_lossy(disk.file_system()).to_string(), - )), - ); - dict.insert_untagged("mount", UntaggedValue::filepath(disk.mount_point())); - dict.insert_untagged("total", UntaggedValue::filesize(disk.total_space())); - dict.insert_untagged("free", UntaggedValue::filesize(disk.available_space())); - output.push(dict.into_value()); - } - if !output.is_empty() { - Some(UntaggedValue::Table(output)) - } else { - None - } -} - -pub fn net(sys: &mut System, tag: Tag) -> Option { - sys.refresh_networks(); - sys.refresh_networks_list(); - - let mut output = vec![]; - for (iface, data) in sys.networks() { - let mut dict = TaggedDictBuilder::new(&tag); - dict.insert_untagged( - "name", - UntaggedValue::string(trim_cstyle_null(iface.to_string())), - ); - dict.insert_untagged("sent", UntaggedValue::filesize(data.total_transmitted())); - dict.insert_untagged("recv", UntaggedValue::filesize(data.total_received())); - - output.push(dict.into_value()); - } - if !output.is_empty() { - Some(UntaggedValue::Table(output)) - } else { - None - } -} - -pub fn cpu(sys: &mut System, tag: Tag) -> Option { - sys.refresh_cpu(); - - let mut output = vec![]; - for cpu in sys.processors() { - let mut dict = TaggedDictBuilder::new(&tag); - dict.insert_untagged( - "name", - UntaggedValue::string(trim_cstyle_null(cpu.name().to_string())), - ); - dict.insert_untagged( - "brand", - UntaggedValue::string(trim_cstyle_null(cpu.brand().to_string())), - ); - dict.insert_untagged("freq", UntaggedValue::int(cpu.frequency() as i64)); - - output.push(dict.into_value()); - } - if !output.is_empty() { - Some(UntaggedValue::Table(output)) - } else { - None - } -} - -pub fn mem(sys: &mut System, tag: Tag) -> Option { - sys.refresh_memory(); - - let mut dict = TaggedDictBuilder::new(tag); - let total_mem = sys.total_memory(); - let free_mem = sys.free_memory(); - let total_swap = sys.total_swap(); - let free_swap = sys.free_swap(); - - dict.insert_untagged("total", UntaggedValue::filesize(total_mem * 1000)); - dict.insert_untagged("free", UntaggedValue::filesize(free_mem * 1000)); - dict.insert_untagged("swap total", UntaggedValue::filesize(total_swap * 1000)); - dict.insert_untagged("swap free", UntaggedValue::filesize(free_swap * 1000)); - - Some(dict.into_untagged_value()) -} - -pub fn host(sys: &mut System, tag: Tag) -> Option { - sys.refresh_users_list(); - - let mut dict = TaggedDictBuilder::new(&tag); - if let Some(name) = sys.name() { - dict.insert_untagged("name", UntaggedValue::string(trim_cstyle_null(name))); - } - if let Some(version) = sys.os_version() { - dict.insert_untagged( - "os version", - UntaggedValue::string(trim_cstyle_null(version)), - ); - } - if let Some(version) = sys.kernel_version() { - dict.insert_untagged( - "kernel version", - UntaggedValue::string(trim_cstyle_null(version)), - ); - } - if let Some(hostname) = sys.host_name() { - dict.insert_untagged( - "hostname", - UntaggedValue::string(trim_cstyle_null(hostname)), - ); - } - dict.insert_untagged( - "uptime", - UntaggedValue::duration(1000000000 * sys.uptime() as i64), - ); - - let mut users = vec![]; - for user in sys.users() { - let mut user_dict = TaggedDictBuilder::new(&tag); - user_dict.insert_untagged( - "name", - UntaggedValue::string(trim_cstyle_null(user.name().to_string())), - ); - - let mut groups = vec![]; - for group in user.groups() { - groups - .push(UntaggedValue::string(trim_cstyle_null(group.to_string())).into_value(&tag)); - } - user_dict.insert_untagged("groups", UntaggedValue::Table(groups)); - - users.push(user_dict.into_value()); - } - if !users.is_empty() { - dict.insert_untagged("sessions", UntaggedValue::Table(users)); - } - - Some(dict.into_untagged_value()) -} - -pub fn temp(sys: &mut System, tag: Tag) -> Option { - sys.refresh_components(); - sys.refresh_components_list(); - - let mut output = vec![]; - - for component in sys.components() { - let mut dict = TaggedDictBuilder::new(&tag); - - dict.insert_untagged("unit", UntaggedValue::string(component.label())); - dict.insert_untagged( - "temp", - UntaggedValue::decimal_from_float(component.temperature() as f64, tag.span), - ); - dict.insert_untagged( - "high", - UntaggedValue::decimal_from_float(component.max() as f64, tag.span), - ); - - if let Some(critical) = component.critical() { - dict.insert_untagged( - "critical", - UntaggedValue::decimal_from_float(critical as f64, tag.span), - ); - } - output.push(dict.into_value()); - } - if !output.is_empty() { - Some(UntaggedValue::Table(output)) - } else { - None - } -} diff --git a/old_nushell/crates/nu-command/src/commands/viewers/autoview/command.rs b/old_nushell/crates/nu-command/src/commands/viewers/autoview/command.rs deleted file mode 100644 index 948533277..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/autoview/command.rs +++ /dev/null @@ -1,330 +0,0 @@ -use crate::commands::viewers::autoview::options::ConfigExtensions; -use crate::prelude::*; -use crate::primitive::get_color_config; -use nu_data::value::format_leaf; -use nu_engine::{UnevaluatedCallInfo, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::hir::{self, Expression, ExternalRedirection, Literal, SpannedExpression}; -use nu_protocol::{Primitive, Signature, UntaggedValue, Value}; -use nu_table::TextStyle; - -#[cfg(feature = "dataframe")] -use nu_protocol::dataframe::FrameStruct; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "autoview" - } - - fn signature(&self) -> Signature { - Signature::build("autoview") - } - - fn usage(&self) -> &str { - "View the contents of the pipeline as a table or list." - } - - fn run(&self, args: CommandArgs) -> Result { - autoview(args) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Automatically view the results", - example: "ls | autoview", - result: None, - }, - Example { - description: "Autoview is also implied. The above can be written as", - example: "ls", - result: None, - }, - ] - } -} - -pub fn autoview(args: CommandArgs) -> Result { - let configuration = args.configs().lock().global_config(); - let tag = args.call_info.name_tag.clone(); - - let binary = args.scope().get_command("binaryview"); - let text = args.scope().get_command("textview"); - let table = args.scope().get_command("table"); - let context = args.context; - let mut input_stream = args.input; - - if let Some(x) = input_stream.next() { - match input_stream.next() { - Some(y) => { - let ctrl_c = context.ctrl_c().clone(); - let xy = vec![x, y]; - let xy_stream = xy.into_iter().chain(input_stream).interruptible(ctrl_c); - - let stream = InputStream::from_stream(xy_stream); - - if let Some(table) = table { - let command_args = create_default_command_args(&context, stream, tag); - let result = table.run(command_args)?; - let _ = result.collect::>(); - } - } - _ => { - match x { - Value { - value: UntaggedValue::Primitive(Primitive::String(ref s)), - tag: Tag { anchor, span }, - } if anchor.is_some() => { - if let Some(text) = text { - let command_args = create_default_command_args( - &context, - InputStream::one( - UntaggedValue::string(s).into_value(Tag { anchor, span }), - ), - tag, - ); - let result = text.run_with_actions(command_args)?; - let _ = result.collect::>(); - } else { - out!("{}", s); - } - } - Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - .. - } => { - out!("{}", s); - } - Value { - value: UntaggedValue::Primitive(Primitive::FilePath(s)), - .. - } => { - out!("{}", s.display()); - } - Value { - value: UntaggedValue::Primitive(Primitive::Int(n)), - .. - } => { - out!("{}", n); - } - Value { - value: UntaggedValue::Primitive(Primitive::BigInt(n)), - .. - } => { - out!("{}", n); - } - Value { - value: UntaggedValue::Primitive(Primitive::Decimal(n)), - .. - } => { - // TODO: normalize decimal to remove trailing zeros. - // normalization will be available in next release of bigdecimal crate - let mut output = n.to_string(); - if output.contains('.') { - output = output.trim_end_matches('0').to_owned(); - } - if output.ends_with('.') { - output.push('0'); - } - out!("{}", output); - } - Value { - value: UntaggedValue::Primitive(Primitive::Boolean(b)), - .. - } => { - out!("{}", b); - } - Value { - value: UntaggedValue::Primitive(Primitive::Duration(_)), - .. - } => { - let output = format_leaf(&x).plain_string(100_000); - out!("{}", output); - } - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(_)), - .. - } => { - let output = format_leaf(&x).plain_string(100_000); - out!("{}", output); - } - Value { - value: UntaggedValue::Primitive(Primitive::Date(d)), - .. - } => { - out!("{}", d); - } - Value { - value: UntaggedValue::Primitive(Primitive::Range(_)), - .. - } => { - let output = format_leaf(&x).plain_string(100_000); - out!("{}", output); - } - - Value { - value: UntaggedValue::Primitive(Primitive::Binary(ref b)), - .. - } => { - if let Some(binary) = binary { - let command_args = - create_default_command_args(&context, InputStream::one(x), tag); - let result = binary.run_with_actions(command_args)?; - let _ = result.collect::>(); - } else { - use nu_pretty_hex::*; - out!("{:?}", b.hex_dump()); - } - } - - Value { - value: UntaggedValue::Error(e), - .. - } => { - return Err(e); - } - - Value { - value: UntaggedValue::Row(ref row), - .. - } => { - let pivot_mode = configuration.pivot_mode(); - - let term_width = context.host().lock().width(); - if pivot_mode.is_always() - || (pivot_mode.is_auto() - && (row - .entries - .iter() - .map(|(_, v)| v.convert_to_string()) - .collect::>() - .iter() - .fold(0usize, |acc, len| acc + len.len()) - + row.entries.iter().count() * 2) - > term_width) - { - let mut entries = vec![]; - for (key, value) in &row.entries { - entries.push(vec![ - nu_table::StyledString::new( - key.to_string(), - TextStyle::new() - .alignment(nu_table::Alignment::Left) - .fg(nu_ansi_term::Color::Green) - .bold(Some(true)), - ), - nu_table::StyledString::new( - format_leaf(value).plain_string(100_000), - nu_table::TextStyle::basic_left(), - ), - ]); - } - - let color_hm = get_color_config(&configuration); - - let table = - nu_table::Table::new(vec![], entries, nu_table::Theme::compact()); - - println!("{}", nu_table::draw_table(&table, term_width, &color_hm)); - } else if let Some(table) = table { - let command_args = - create_default_command_args(&context, InputStream::one(x), tag); - let result = table.run(command_args)?; - let _ = result.collect::>(); - } else { - out!("{:?}", row); - } - } - #[cfg(feature = "dataframe")] - Value { - value: UntaggedValue::DataFrame(df), - tag, - } => { - if let Some(table) = table { - // TODO. Configure the parameter rows from file. It can be - // adjusted to see a certain amount of values in the head - let command_args = - create_default_command_args(&context, df.print()?.into(), tag); - let result = table.run(command_args)?; - let _ = result.collect::>(); - } - } - #[cfg(feature = "dataframe")] - Value { - value: UntaggedValue::FrameStruct(FrameStruct::GroupBy(groupby)), - tag, - } => { - if let Some(table) = table { - // TODO. Configure the parameter rows from file. It can be - // adjusted to see a certain amount of values in the head - let command_args = - create_default_command_args(&context, groupby.print()?.into(), tag); - let result = table.run(command_args)?; - let _ = result.collect::>(); - } - } - Value { - value: UntaggedValue::Primitive(Primitive::Nothing), - .. - } => { - // Do nothing - } - Value { - value: ref item, .. - } => { - if let Some(table) = table { - let command_args = - create_default_command_args(&context, InputStream::one(x), tag); - let result = table.run(command_args)?; - let _ = result.collect::>(); - } else { - out!("{:?}", item); - } - } - } - } - } - } - - Ok(InputStream::empty()) -} - -fn create_default_command_args( - context: &EvaluationContext, - input: InputStream, - tag: Tag, -) -> CommandArgs { - let span = tag.span; - CommandArgs { - context: context.clone(), - call_info: UnevaluatedCallInfo { - args: hir::Call { - head: Box::new(SpannedExpression::new( - Expression::Literal(Literal::String(String::new())), - span, - )), - positional: None, - named: None, - span, - external_redirection: ExternalRedirection::Stdout, - }, - name_tag: tag, - }, - input, - } -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/viewers/autoview/mod.rs b/old_nushell/crates/nu-command/src/commands/viewers/autoview/mod.rs deleted file mode 100644 index 5cb35ceb1..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/autoview/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod command; -mod options; - -pub use command::Command as Autoview; diff --git a/old_nushell/crates/nu-command/src/commands/viewers/autoview/options.rs b/old_nushell/crates/nu-command/src/commands/viewers/autoview/options.rs deleted file mode 100644 index ad6aa5fca..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/autoview/options.rs +++ /dev/null @@ -1,51 +0,0 @@ -pub use nu_data::config::NuConfig; -use std::fmt::Debug; - -#[derive(PartialEq, Debug)] -pub enum AutoPivotMode { - Auto, - Always, - Never, -} - -impl AutoPivotMode { - pub fn is_auto(&self) -> bool { - matches!(self, AutoPivotMode::Auto) - } - - pub fn is_always(&self) -> bool { - matches!(self, AutoPivotMode::Always) - } - - #[allow(unused)] - pub fn is_never(&self) -> bool { - matches!(self, AutoPivotMode::Never) - } -} - -pub trait ConfigExtensions: Debug + Send { - fn pivot_mode(&self) -> AutoPivotMode; -} - -pub fn pivot_mode(config: &NuConfig) -> AutoPivotMode { - let vars = &config.vars; - - if let Some(mode) = vars.get("pivot_mode") { - let mode = match mode.as_string() { - Ok(m) if m.to_lowercase() == "auto" => AutoPivotMode::Auto, - Ok(m) if m.to_lowercase() == "always" => AutoPivotMode::Always, - Ok(m) if m.to_lowercase() == "never" => AutoPivotMode::Never, - _ => AutoPivotMode::Never, - }; - - return mode; - } - - AutoPivotMode::Never -} - -impl ConfigExtensions for NuConfig { - fn pivot_mode(&self) -> AutoPivotMode { - pivot_mode(self) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/viewers/bat_constants.rs b/old_nushell/crates/nu-command/src/commands/viewers/bat_constants.rs deleted file mode 100644 index 0b7ca91a5..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/bat_constants.rs +++ /dev/null @@ -1,358 +0,0 @@ -pub const BAT_LANGUAGES: &[&str] = &[ - "as", - "csv", - "tsv", - "applescript", - "script editor", - "s", - "S", - "adoc", - "asciidoc", - "asc", - "asa", - "yasm", - "nasm", - "asm", - "inc", - "mac", - "awk", - "bat", - "cmd", - "bib", - "sh", - "bash", - "zsh", - ".bash_aliases", - ".bash_completions", - ".bash_functions", - ".bash_login", - ".bash_logout", - ".bash_profile", - ".bash_variables", - ".bashrc", - ".profile", - ".textmate_init", - ".zshrc", - "PKGBUILD", - ".ebuild", - ".eclass", - "c", - "h", - "cs", - "csx", - "cpp", - "cc", - "cp", - "cxx", - "c++", - "C", - "h", - "hh", - "hpp", - "hxx", - "h++", - "inl", - "ipp", - "cabal", - "clj", - "cljc", - "cljs", - "edn", - "CMakeLists.txt", - "cmake", - "h.in", - "hh.in", - "hpp.in", - "hxx.in", - "h++.in", - "CMakeCache.txt", - "cr", - "css", - "css.erb", - "css.liquid", - "d", - "di", - "dart", - "diff", - "patch", - "Dockerfile", - "dockerfile", - "ex", - "exs", - "elm", - "erl", - "hrl", - "Emakefile", - "emakefile", - "fs", - "fsi", - "fsx", - "fs", - "fsi", - "fsx", - "fish", - "attributes", - "gitattributes", - ".gitattributes", - "COMMIT_EDITMSG", - "MERGE_MSG", - "TAG_EDITMSG", - "gitconfig", - ".gitconfig", - ".gitmodules", - "exclude", - "gitignore", - ".gitignore", - ".git", - "gitlog", - "git-rebase-todo", - "go", - "dot", - "DOT", - "gv", - "groovy", - "gvy", - "gradle", - "Jenkinsfile", - "hs", - "hs", - "hsc", - "show-nonprintable", - "html", - "htm", - "shtml", - "xhtml", - "asp", - "html.eex", - "yaws", - "rails", - "rhtml", - "erb", - "html.erb", - "adp", - "twig", - "html.twig", - "ini", - "INI", - "INF", - "reg", - "REG", - "lng", - "cfg", - "CFG", - "desktop", - "url", - "URL", - ".editorconfig", - ".hgrc", - "hgrc", - "java", - "bsh", - "properties", - "jsp", - "js", - "htc", - "js", - "jsx", - "babel", - "es6", - "js.erb", - "json", - "sublime-settings", - "sublime-menu", - "sublime-keymap", - "sublime-mousemap", - "sublime-theme", - "sublime-build", - "sublime-project", - "sublime-completions", - "sublime-commands", - "sublime-macro", - "sublime-color-scheme", - "ipynb", - "Pipfile.lock", - "jsonnet", - "libsonnet", - "libjsonnet", - "jl", - "kt", - "kts", - "tex", - "ltx", - "less", - "css.less", - "lisp", - "cl", - "clisp", - "l", - "mud", - "el", - "scm", - "ss", - "lsp", - "fasl", - "lhs", - "lua", - "make", - "GNUmakefile", - "makefile", - "Makefile", - "makefile.am", - "Makefile.am", - "makefile.in", - "Makefile.in", - "OCamlMakefile", - "mak", - "mk", - "md", - "mdown", - "markdown", - "markdn", - "matlab", - "build", - "nix", - "m", - "h", - "mm", - "M", - "h", - "ml", - "mli", - "mll", - "mly", - "pas", - "p", - "dpr", - "pl", - "pm", - "pod", - "t", - "PL", - "php", - "php3", - "php4", - "php5", - "php7", - "phps", - "phpt", - "phtml", - "txt", - "ps1", - "psm1", - "psd1", - "proto", - "protodevel", - "pb.txt", - "proto.text", - "textpb", - "pbtxt", - "prototxt", - "pp", - "epp", - "purs", - "py", - "py3", - "pyw", - "pyi", - "pyx", - "pyx.in", - "pxd", - "pxd.in", - "pxi", - "pxi.in", - "rpy", - "cpy", - "SConstruct", - "Sconstruct", - "sconstruct", - "SConscript", - "gyp", - "gypi", - "Snakefile", - "wscript", - "R", - "r", - "s", - "S", - "Rprofile", - "rd", - "re", - "rst", - "rest", - "robot", - "rb", - "Appfile", - "Appraisals", - "Berksfile", - "Brewfile", - "capfile", - "cgi", - "Cheffile", - "config.ru", - "Deliverfile", - "Fastfile", - "fcgi", - "Gemfile", - "gemspec", - "Guardfile", - "irbrc", - "jbuilder", - "Podfile", - "podspec", - "prawn", - "rabl", - "rake", - "Rakefile", - "Rantfile", - "rbx", - "rjs", - "ruby.rail", - "Scanfile", - "simplecov", - "Snapfile", - "thor", - "Thorfile", - "Vagrantfile", - "haml", - "sass", - "rxml", - "builder", - "rs", - "scala", - "sbt", - "sql", - "ddl", - "dml", - "erbsql", - "sql.erb", - "swift", - "log", - "tcl", - "tf", - "tfvars", - "hcl", - "sty", - "cls", - "textile", - "toml", - "tml", - "Cargo.lock", - "Gopkg.lock", - "Pipfile", - "ts", - "tsx", - "varlink", - "vim", - ".vimrc", - "xml", - "xsd", - "xslt", - "tld", - "dtml", - "rss", - "opml", - "svg", - "yaml", - "yml", - "sublime-syntax", -]; diff --git a/old_nushell/crates/nu-command/src/commands/viewers/mod.rs b/old_nushell/crates/nu-command/src/commands/viewers/mod.rs deleted file mode 100644 index ddd1b9c67..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod autoview; -mod bat_constants; -mod table; - -pub use autoview::*; -pub use bat_constants::BAT_LANGUAGES; -pub use table::*; diff --git a/old_nushell/crates/nu-command/src/commands/viewers/table/command.rs b/old_nushell/crates/nu-command/src/commands/viewers/table/command.rs deleted file mode 100644 index 6caa91c6d..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/table/command.rs +++ /dev/null @@ -1,267 +0,0 @@ -use crate::commands::viewers::table::options::{ConfigExtensions, NuConfig}; -use crate::prelude::*; -use crate::primitive::get_color_config; -use futures::executor::block_on; -use nu_data::value::{format_leaf, style_leaf}; -use nu_engine::WholeStreamCommand; -use nu_errors::ShellError; -use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; -use nu_table::{draw_table, Alignment, StyledString, TextStyle}; -use std::collections::HashMap; -use std::sync::atomic::Ordering; -use std::time::Instant; - -const STREAM_PAGE_SIZE: usize = 1000; -const STREAM_TIMEOUT_CHECK_INTERVAL: usize = 100; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "table" - } - - fn signature(&self) -> Signature { - Signature::build("table").named( - "start_number", - SyntaxShape::Number, - "row number to start viewing from", - Some('n'), - ) - } - - fn usage(&self) -> &str { - "View the contents of the pipeline as a table." - } - - fn run(&self, args: CommandArgs) -> Result { - table(args) - } -} - -pub fn from_list( - values: &[Value], - configuration: &NuConfig, - starting_idx: usize, - color_hm: &HashMap, -) -> nu_table::Table { - let header_style = configuration.header_style(); - let mut headers: Vec = nu_protocol::merge_descriptors(values) - .into_iter() - .map(|x| StyledString::new(x, header_style)) - .collect(); - let entries = values_to_entries(values, &mut headers, configuration, starting_idx, color_hm); - nu_table::Table { - headers, - data: entries, - theme: configuration.table_mode(), - } -} - -fn values_to_entries( - values: &[Value], - headers: &mut Vec, - configuration: &NuConfig, - starting_idx: usize, - color_hm: &HashMap, -) -> Vec> { - let disable_indexes = configuration.disabled_indexes(); - let mut entries = vec![]; - - if headers.is_empty() { - headers.push(StyledString::new("".to_string(), TextStyle::basic_left())); - } - - for (idx, value) in values.iter().enumerate() { - let mut row: Vec = headers - .iter() - .map(|d: &StyledString| { - if d.contents.is_empty() { - match value { - Value { - value: UntaggedValue::Row(..), - .. - } => StyledString::new( - format_leaf(&UntaggedValue::nothing()).plain_string(100_000), - style_leaf(&UntaggedValue::nothing(), color_hm), - ), - _ => StyledString::new( - format_leaf(value).plain_string(100_000), - style_leaf(value, color_hm), - ), - } - } else { - match value { - Value { - value: UntaggedValue::Row(..), - .. - } => { - let data = value.get_data(&d.contents); - - StyledString::new( - format_leaf(data.borrow()).plain_string(100_000), - style_leaf(data.borrow(), color_hm), - ) - } - _ => StyledString::new( - format_leaf(&UntaggedValue::nothing()).plain_string(100_000), - style_leaf(&UntaggedValue::nothing(), color_hm), - ), - } - } - }) - .collect(); - - // Indices are green, bold, right-aligned: - // unless we change them :) - if !disable_indexes { - row.insert( - 0, - StyledString::new( - (starting_idx + idx).to_string(), - TextStyle::new().alignment(Alignment::Right).style( - color_hm - .get("index_color") - .unwrap_or( - &nu_ansi_term::Style::default() - .bold() - .fg(nu_ansi_term::Color::Green), - ) - .to_owned(), - ), - ), - ); - } - - entries.push(row); - } - - if !disable_indexes { - headers.insert( - 0, - StyledString::new( - "#".to_string(), - TextStyle::new().alignment(Alignment::Center).style( - color_hm - .get("header_color") - .unwrap_or( - &nu_ansi_term::Style::default() - .bold() - .fg(nu_ansi_term::Color::Green), - ) - .to_owned(), - ), - ), - ); - } - - entries -} - -fn table(mut args: CommandArgs) -> Result { - let configuration = args.configs().lock().global_config(); - - // Ideally, get_color_config would get all the colors configured in the config.toml - // and create a style based on those settings. However, there are few places where - // this just won't work right now, like header styling, because a style needs to know - // more than just color, it needs fg & bg color, bold, dimmed, italic, underline, - // blink, reverse, hidden, strikethrough and most of those aren't available in the - // config.toml.... yet. - let color_hm = get_color_config(&configuration); - - let mut start_number = if let Some(f) = args.get_flag("start_number")? { - f - } else { - 0 - }; - - let mut delay_slot = None; - - let term_width = args.host().lock().width(); - - let stream_data = async { - let finished = Arc::new(AtomicBool::new(false)); - // we are required to clone finished, for use within the callback, otherwise we get borrow errors - while !finished.clone().load(Ordering::Relaxed) { - let mut new_input: VecDeque = VecDeque::new(); - - let start_time = Instant::now(); - for idx in 0..STREAM_PAGE_SIZE { - if let Some(val) = delay_slot { - new_input.push_back(val); - delay_slot = None; - } else { - match args.input.next() { - Some(a) => { - if !new_input.is_empty() { - if let Some(descs) = new_input.get(0) { - let descs = descs.data_descriptors(); - let compare = a.data_descriptors(); - if descs != compare { - delay_slot = Some(a); - break; - } else { - new_input.push_back(a); - } - } else { - new_input.push_back(a); - } - } else { - new_input.push_back(a); - } - } - _ => { - finished.store(true, Ordering::Relaxed); - break; - } - } - - // Check if we've gone over our buffering threshold - if (idx + 1) % STREAM_TIMEOUT_CHECK_INTERVAL == 0 { - let end_time = Instant::now(); - - // If we've been buffering over a second, go ahead and send out what we have so far - if (end_time - start_time).as_secs() >= 1 { - break; - } - - if finished.load(Ordering::Relaxed) { - break; - } - } - } - } - - let input: Vec = new_input.into(); - - if !input.is_empty() { - let t = from_list(&input, &configuration, start_number, &color_hm); - let output = draw_table(&t, term_width, &color_hm); - - println!("{}", output); - } - - start_number += input.len(); - } - - Result::<_, ShellError>::Ok(()) - }; - - block_on(stream_data) - .map_err(|_| ShellError::untagged_runtime_error("Error streaming data"))?; - - Ok(OutputStream::empty()) -} - -#[cfg(test)] -mod tests { - use super::Command; - use super::ShellError; - - #[test] - fn examples_work_as_expected() -> Result<(), ShellError> { - use crate::examples::test as test_examples; - - test_examples(Command {}) - } -} diff --git a/old_nushell/crates/nu-command/src/commands/viewers/table/mod.rs b/old_nushell/crates/nu-command/src/commands/viewers/table/mod.rs deleted file mode 100644 index 96f007aac..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/table/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod command; -mod options; - -pub use command::Command as Table; diff --git a/old_nushell/crates/nu-command/src/commands/viewers/table/options.rs b/old_nushell/crates/nu-command/src/commands/viewers/table/options.rs deleted file mode 100644 index cafb34951..000000000 --- a/old_nushell/crates/nu-command/src/commands/viewers/table/options.rs +++ /dev/null @@ -1,108 +0,0 @@ -pub use nu_data::config::NuConfig; -use nu_data::primitive::lookup_ansi_color_style; -use nu_protocol::Value; -use nu_table::{Alignment, TextStyle}; -use std::fmt::Debug; - -pub trait ConfigExtensions: Debug + Send { - fn table_mode(&self) -> nu_table::Theme; - fn disabled_indexes(&self) -> bool; - fn header_style(&self) -> TextStyle; -} - -pub fn header_alignment_from_value(align_value: Option<&Value>) -> nu_table::Alignment { - match align_value { - Some(v) => match v - .as_string() - .unwrap_or_else(|_| "none".to_string()) - .as_ref() - { - "l" | "left" => nu_table::Alignment::Left, - "c" | "center" => nu_table::Alignment::Center, - "r" | "right" => nu_table::Alignment::Right, - _ => nu_table::Alignment::Center, - }, - _ => nu_table::Alignment::Center, - } -} - -pub fn get_color_from_key_and_subkey(config: &NuConfig, key: &str, subkey: &str) -> Option { - let vars = &config.vars; - - if let Some(config_vars) = vars.get(key) { - for (kee, value) in config_vars.row_entries() { - if kee == subkey { - return Some(value.clone()); - } - } - } - - None -} - -pub fn header_bold_from_value(bold_value: Option<&Value>) -> bool { - bold_value - .map(|x| x.as_bool().unwrap_or(true)) - .unwrap_or(true) -} - -pub fn table_mode(config: &NuConfig) -> nu_table::Theme { - let vars = &config.vars; - - vars.get("table_mode") - .map_or(nu_table::Theme::compact(), |mode| match mode.as_string() { - Ok(m) if m == "basic" => nu_table::Theme::basic(), - Ok(m) if m == "compact" => nu_table::Theme::compact(), - Ok(m) if m == "light" => nu_table::Theme::light(), - Ok(m) if m == "thin" => nu_table::Theme::thin(), - Ok(m) if m == "with_love" => nu_table::Theme::with_love(), - Ok(m) if m == "compact_double" => nu_table::Theme::compact_double(), - Ok(m) if m == "rounded" => nu_table::Theme::rounded(), - Ok(m) if m == "reinforced" => nu_table::Theme::reinforced(), - Ok(m) if m == "heavy" => nu_table::Theme::heavy(), - Ok(m) if m == "none" => nu_table::Theme::none(), - _ => nu_table::Theme::compact(), - }) -} - -pub fn disabled_indexes(config: &NuConfig) -> bool { - let vars = &config.vars; - - vars.get("disable_table_indexes") - .map_or(false, |x| x.as_bool().unwrap_or(false)) -} - -impl ConfigExtensions for NuConfig { - fn header_style(&self) -> TextStyle { - // FIXME: I agree, this is the long way around, please suggest and alternative. - let head_color = get_color_from_key_and_subkey(self, "color_config", "header_color"); - let (head_color_style, head_bold_bool) = match head_color { - Some(s) => ( - lookup_ansi_color_style(s.as_string().unwrap_or_else(|_| "green".to_string())), - header_bold_from_value(Some(&s)), - ), - None => (nu_ansi_term::Color::Green.normal(), true), - }; - - let head_align = get_color_from_key_and_subkey(self, "color_config", "header_align"); - let head_alignment = match head_align { - Some(a) => header_alignment_from_value(Some(&a)), - None => Alignment::Center, - }; - - TextStyle::new() - .alignment(head_alignment) - .bold(Some(head_bold_bool)) - .fg(head_color_style - .foreground - .unwrap_or(nu_ansi_term::Color::Green)) - } - - fn table_mode(&self) -> nu_table::Theme { - table_mode(self) - } - - fn disabled_indexes(&self) -> bool { - disabled_indexes(self) - } -} diff --git a/old_nushell/crates/nu-command/src/default_context.rs b/old_nushell/crates/nu-command/src/default_context.rs deleted file mode 100644 index 9d091957e..000000000 --- a/old_nushell/crates/nu-command/src/default_context.rs +++ /dev/null @@ -1,372 +0,0 @@ -use crate::prelude::*; -use nu_engine::whole_stream_command; -use std::error::Error; - -pub fn create_default_context(interactive: bool) -> Result> { - let context = EvaluationContext::basic(); - - { - use crate::commands::*; - - context.add_commands(vec![ - // Fundamentals - whole_stream_command(NuPlugin), - whole_stream_command(Let), - whole_stream_command(LetEnv), - whole_stream_command(UnletEnv), - whole_stream_command(LoadEnv), - whole_stream_command(Def), - whole_stream_command(Source), - whole_stream_command(Alias), - whole_stream_command(Unalias), - whole_stream_command(Ignore), - whole_stream_command(Tutor), - whole_stream_command(Find), - // System/file operations - whole_stream_command(ErrorMake), - whole_stream_command(Exec), - whole_stream_command(Pwd), - whole_stream_command(Ls), - whole_stream_command(Du), - whole_stream_command(Cd), - whole_stream_command(Remove), - whole_stream_command(Open), - whole_stream_command(Pathvar), - whole_stream_command(PathvarAdd), - whole_stream_command(PathvarRemove), - whole_stream_command(PathvarReset), - whole_stream_command(PathvarAppend), - whole_stream_command(PathvarSave), - whole_stream_command(Config), - whole_stream_command(ConfigGet), - whole_stream_command(ConfigSet), - whole_stream_command(ConfigSetInto), - whole_stream_command(ConfigClear), - whole_stream_command(ConfigRemove), - whole_stream_command(ConfigPath), - whole_stream_command(Help), - whole_stream_command(History), - whole_stream_command(Save), - whole_stream_command(Touch), - whole_stream_command(Cpy), - whole_stream_command(Date), - whole_stream_command(DateListTimeZone), - whole_stream_command(DateNow), - whole_stream_command(DateToTable), - whole_stream_command(DateToTimeZone), - whole_stream_command(DateFormat), - whole_stream_command(DateHumanize), - whole_stream_command(Cal), - whole_stream_command(Mkdir), - whole_stream_command(Mv), - whole_stream_command(Kill), - whole_stream_command(Version), - whole_stream_command(Clear), - whole_stream_command(Describe), - whole_stream_command(Which), - whole_stream_command(Debug), - whole_stream_command(WithEnv), - whole_stream_command(Do), - whole_stream_command(Sleep), - // Statistics - whole_stream_command(Size), - whole_stream_command(Length), - whole_stream_command(Benchmark), - // Metadata - whole_stream_command(Tags), - // Shells - whole_stream_command(Next), - whole_stream_command(Previous), - whole_stream_command(Goto), - whole_stream_command(Shells), - whole_stream_command(Enter), - whole_stream_command(Exit), - // Viz - whole_stream_command(Chart), - // Viewers - whole_stream_command(Autoview), - whole_stream_command(Table), - // Text manipulation - whole_stream_command(Hash), - whole_stream_command(HashBase64), - whole_stream_command(HashMd5::default()), - whole_stream_command(HashSha256::default()), - whole_stream_command(Split), - whole_stream_command(SplitColumn), - whole_stream_command(SplitRow), - whole_stream_command(SplitChars), - whole_stream_command(Lines), - whole_stream_command(Echo), - whole_stream_command(Parse), - whole_stream_command(Str), - whole_stream_command(StrToDecimal), - whole_stream_command(StrToInteger), - whole_stream_command(StrDowncase), - whole_stream_command(StrUpcase), - whole_stream_command(StrCapitalize), - whole_stream_command(StrFindReplace), - whole_stream_command(StrSubstring), - whole_stream_command(StrToDatetime), - whole_stream_command(StrContains), - whole_stream_command(StrIndexOf), - whole_stream_command(StrTrim), - whole_stream_command(StrStartsWith), - whole_stream_command(StrEndsWith), - whole_stream_command(StrCollect), - whole_stream_command(StrLength), - whole_stream_command(StrLPad), - whole_stream_command(StrReverse), - whole_stream_command(StrRPad), - whole_stream_command(StrCamelCase), - whole_stream_command(StrPascalCase), - whole_stream_command(StrKebabCase), - whole_stream_command(StrSnakeCase), - whole_stream_command(StrScreamingSnakeCase), - whole_stream_command(BuildString), - whole_stream_command(Ansi), - whole_stream_command(AnsiStrip), - whole_stream_command(AnsiGradient), - whole_stream_command(Char), - whole_stream_command(DetectColumns), - // Column manipulation - whole_stream_command(DropColumn), - whole_stream_command(MoveColumn), - whole_stream_command(Reject), - whole_stream_command(Select), - whole_stream_command(Get), - whole_stream_command(Update), - whole_stream_command(UpdateCells), - whole_stream_command(Insert), - whole_stream_command(Into), - whole_stream_command(IntoBinary), - whole_stream_command(IntoColumnPath), - whole_stream_command(IntoInt), - whole_stream_command(IntoFilepath), - whole_stream_command(IntoFilesize), - whole_stream_command(IntoString), - whole_stream_command(SplitBy), - // Row manipulation - whole_stream_command(All), - whole_stream_command(Any), - whole_stream_command(Reverse), - whole_stream_command(Append), - whole_stream_command(Prepend), - whole_stream_command(SortBy), - whole_stream_command(GroupBy), - whole_stream_command(GroupByDate), - whole_stream_command(First), - whole_stream_command(Last), - whole_stream_command(Every), - whole_stream_command(Nth), - whole_stream_command(Drop), - whole_stream_command(DropNth), - whole_stream_command(Format), - whole_stream_command(FileSize), - whole_stream_command(Where), - whole_stream_command(If), - whole_stream_command(Compact), - whole_stream_command(Default), - whole_stream_command(Skip), - whole_stream_command(SkipUntil), - whole_stream_command(SkipWhile), - whole_stream_command(Keep), - whole_stream_command(KeepUntil), - whole_stream_command(KeepWhile), - whole_stream_command(Range), - whole_stream_command(Rename), - whole_stream_command(Uniq), - whole_stream_command(Each), - whole_stream_command(EachGroup), - whole_stream_command(EachWindow), - whole_stream_command(Empty), - whole_stream_command(ForIn), - // Table manipulation - whole_stream_command(Flatten), - whole_stream_command(Merge), - whole_stream_command(Shuffle), - whole_stream_command(Wrap), - whole_stream_command(Pivot), - whole_stream_command(Headers), - whole_stream_command(Reduce), - whole_stream_command(Roll), - whole_stream_command(RollColumn), - whole_stream_command(RollUp), - whole_stream_command(Rotate), - whole_stream_command(RotateCounterClockwise), - whole_stream_command(Zip), - whole_stream_command(Collect), - // Data processing - whole_stream_command(Histogram), - whole_stream_command(Autoenv), - whole_stream_command(AutoenvTrust), - whole_stream_command(AutoenvUntrust), - whole_stream_command(Math), - whole_stream_command(MathAbs), - whole_stream_command(MathAverage), - whole_stream_command(MathEval), - whole_stream_command(MathMedian), - whole_stream_command(MathMinimum), - whole_stream_command(MathMode), - whole_stream_command(MathMaximum), - whole_stream_command(MathStddev), - whole_stream_command(MathSummation), - whole_stream_command(MathVariance), - whole_stream_command(MathProduct), - whole_stream_command(MathRound), - whole_stream_command(MathFloor), - whole_stream_command(MathCeil), - whole_stream_command(MathSqrt), - // File format output - whole_stream_command(To), - whole_stream_command(ToCsv), - whole_stream_command(ToHtml), - whole_stream_command(ToJson), - whole_stream_command(ToMarkdown), - whole_stream_command(ToToml), - whole_stream_command(ToTsv), - whole_stream_command(ToUrl), - whole_stream_command(ToYaml), - whole_stream_command(ToXml), - // File format input - whole_stream_command(From), - whole_stream_command(FromCsv), - whole_stream_command(FromEml), - whole_stream_command(FromTsv), - whole_stream_command(FromSsv), - whole_stream_command(FromIni), - whole_stream_command(FromJson), - whole_stream_command(FromOds), - whole_stream_command(FromToml), - whole_stream_command(FromUrl), - whole_stream_command(FromXlsx), - whole_stream_command(FromXml), - whole_stream_command(FromYaml), - whole_stream_command(FromYml), - whole_stream_command(FromIcs), - whole_stream_command(FromVcf), - // "Private" commands (not intended to be accessed directly) - whole_stream_command(RunExternalCommand { interactive }), - // Random value generation - whole_stream_command(Random), - whole_stream_command(RandomBool), - whole_stream_command(RandomDice), - #[cfg(feature = "uuid_crate")] - whole_stream_command(RandomUUID), - whole_stream_command(RandomInteger), - whole_stream_command(RandomDecimal), - whole_stream_command(RandomChars), - // Path - whole_stream_command(PathBasename), - whole_stream_command(PathCommand), - whole_stream_command(PathDirname), - whole_stream_command(PathExists), - whole_stream_command(PathExpand), - whole_stream_command(PathJoin), - whole_stream_command(PathParse), - whole_stream_command(PathRelativeTo), - whole_stream_command(PathSplit), - whole_stream_command(PathType), - // Url - whole_stream_command(UrlCommand), - whole_stream_command(UrlScheme), - whole_stream_command(UrlPath), - whole_stream_command(UrlHost), - whole_stream_command(UrlQuery), - whole_stream_command(Seq), - whole_stream_command(SeqDates), - whole_stream_command(TermSize), - // Network - #[cfg(feature = "fetch")] - whole_stream_command(Fetch), - #[cfg(feature = "post")] - whole_stream_command(Post), - // System - #[cfg(feature = "ps")] - whole_stream_command(Ps), - #[cfg(feature = "sys")] - whole_stream_command(Sys), - ]); - - //Dataframe commands - #[cfg(feature = "dataframe")] - context.add_commands(vec![ - whole_stream_command(DataFrame), - whole_stream_command(DataFrameOpen), - whole_stream_command(DataFrameList), - whole_stream_command(DataFrameGroupBy), - whole_stream_command(DataFrameAggregate), - whole_stream_command(DataFrameShow), - whole_stream_command(DataFrameSample), - whole_stream_command(DataFrameJoin), - whole_stream_command(DataFrameDrop), - whole_stream_command(DataFrameSelect), - whole_stream_command(DataFrameDTypes), - whole_stream_command(DataFrameDummies), - whole_stream_command(DataFrameFirst), - whole_stream_command(DataFrameLast), - whole_stream_command(DataFrameSlice), - whole_stream_command(DataFrameMelt), - whole_stream_command(DataFramePivot), - whole_stream_command(DataFrameWhere), - whole_stream_command(DataFrameToDF), - whole_stream_command(DataFrameToParquet), - whole_stream_command(DataFrameToCsv), - whole_stream_command(DataFrameSort), - whole_stream_command(DataFrameGet), - whole_stream_command(DataFrameDropDuplicates), - whole_stream_command(DataFrameDropNulls), - whole_stream_command(DataFrameColumn), - whole_stream_command(DataFrameWithColumn), - whole_stream_command(DataFrameFilter), - whole_stream_command(DataFrameSeriesRename), - whole_stream_command(DataFrameValueCounts), - whole_stream_command(DataFrameIsNull), - whole_stream_command(DataFrameIsNotNull), - whole_stream_command(DataFrameAllTrue), - whole_stream_command(DataFrameAllFalse), - whole_stream_command(DataFrameArgMax), - whole_stream_command(DataFrameArgMin), - whole_stream_command(DataFrameArgTrue), - whole_stream_command(DataFrameArgUnique), - whole_stream_command(DataFrameArgSort), - whole_stream_command(DataFrameUnique), - whole_stream_command(DataFrameNUnique), - whole_stream_command(DataFrameNNull), - whole_stream_command(DataFrameIsUnique), - whole_stream_command(DataFrameIsDuplicated), - whole_stream_command(DataFrameIsIn), - whole_stream_command(DataFrameShift), - whole_stream_command(DataFrameSet), - whole_stream_command(DataFrameNot), - whole_stream_command(DataFrameTake), - whole_stream_command(DataFrameSetWithIdx), - whole_stream_command(DataFrameShape), - whole_stream_command(DataFrameReplace), - whole_stream_command(DataFrameReplaceAll), - whole_stream_command(DataFrameStringLengths), - whole_stream_command(DataFrameContains), - whole_stream_command(DataFrameToLowercase), - whole_stream_command(DataFrameToUppercase), - whole_stream_command(DataFrameStringSlice), - whole_stream_command(DataFrameConcatenate), - whole_stream_command(DataFrameAppend), - whole_stream_command(DataFrameGetHour), - whole_stream_command(DataFrameGetMinute), - whole_stream_command(DataFrameGetSecond), - whole_stream_command(DataFrameGetDay), - whole_stream_command(DataFrameGetMonth), - whole_stream_command(DataFrameGetYear), - whole_stream_command(DataFrameGetWeek), - whole_stream_command(DataFrameGetWeekDay), - whole_stream_command(DataFrameGetOrdinal), - whole_stream_command(DataFrameGetNanoSecond), - whole_stream_command(DataFrameStrFTime), - whole_stream_command(DataFrameDescribe), - whole_stream_command(DataFrameRolling), - whole_stream_command(DataFrameCumulative), - whole_stream_command(DataFrameRename), - ]); - } - - Ok(context) -} diff --git a/old_nushell/crates/nu-command/src/examples.rs b/old_nushell/crates/nu-command/src/examples.rs deleted file mode 100644 index 3ef28d77b..000000000 --- a/old_nushell/crates/nu-command/src/examples.rs +++ /dev/null @@ -1,368 +0,0 @@ -mod sample; - -mod double_echo; -mod double_ls; -mod stub_generate; - -use double_echo::Command as DoubleEcho; -use double_ls::Command as DoubleLs; -use stub_generate::{mock_path, Command as StubOpen}; - -use nu_errors::ShellError; -use nu_parser::ParserScope; -use nu_protocol::hir::{ClassifiedBlock, ExternalRedirection}; -use nu_protocol::{ShellTypeName, Value}; -use nu_source::AnchorLocation; - -#[cfg(feature = "dataframe")] -use crate::commands::{ - DataFrameDropNulls, DataFrameGroupBy, DataFrameIsNull, DataFrameShift, DataFrameToDF, - DataFrameWithColumn, StrToDatetime, -}; - -use crate::commands::{ - Append, BuildString, Collect, Each, Echo, First, Get, If, IntoInt, Keep, Last, Let, Math, - MathMode, Nth, Select, StrCollect, Wrap, -}; -use nu_engine::{run_block, whole_stream_command, Command, EvaluationContext, WholeStreamCommand}; -use nu_stream::InputStream; - -pub fn test_examples(cmd: Command) -> Result<(), ShellError> { - let examples = cmd.examples(); - - let base_context = EvaluationContext::basic(); - - base_context.add_commands(vec![ - // Command Doubles - whole_stream_command(DoubleLs {}), - // Minimal restricted commands to aid in testing - whole_stream_command(Append {}), - whole_stream_command(Echo {}), - whole_stream_command(BuildString {}), - whole_stream_command(First {}), - whole_stream_command(Get {}), - whole_stream_command(If {}), - whole_stream_command(IntoInt {}), - whole_stream_command(Keep {}), - whole_stream_command(Each {}), - whole_stream_command(Last {}), - whole_stream_command(Nth {}), - whole_stream_command(Let {}), - whole_stream_command(Select), - whole_stream_command(StrCollect), - whole_stream_command(Collect), - whole_stream_command(Wrap), - cmd, - ]); - - for sample_pipeline in examples { - let mut ctx = base_context.clone(); - - let block = parse_line(sample_pipeline.example, &ctx)?; - - if let Some(expected) = &sample_pipeline.result { - let result = evaluate_block(block, &mut ctx)?; - - ctx.with_errors(|reasons| reasons.iter().cloned().next()) - .map_or(Ok(()), Err)?; - - if expected.len() != result.len() { - let rows_returned = - format!("expected: {}\nactual: {}", expected.len(), result.len()); - let failed_call = format!("command: {}\n", sample_pipeline.example); - - panic!( - "example command produced unexpected number of results.\n {} {}", - failed_call, rows_returned - ); - } - - for (e, a) in expected.iter().zip(&result) { - if !values_equal(e, a) { - let row_errored = format!("expected: {:#?}\nactual: {:#?}", e, a); - let failed_call = format!("command: {}\n", sample_pipeline.example); - - panic!( - "example command produced unexpected result.\n {} {}", - failed_call, row_errored - ); - } - } - } - } - - Ok(()) -} - -pub fn test(cmd: impl WholeStreamCommand + 'static) -> Result<(), ShellError> { - let examples = cmd.examples(); - - let base_context = EvaluationContext::basic(); - - base_context.add_commands(vec![ - whole_stream_command(Math), - whole_stream_command(MathMode {}), - whole_stream_command(Echo {}), - whole_stream_command(BuildString {}), - whole_stream_command(Get {}), - whole_stream_command(Keep {}), - whole_stream_command(Each {}), - whole_stream_command(Let {}), - whole_stream_command(cmd), - whole_stream_command(Select), - whole_stream_command(StrCollect), - whole_stream_command(Collect), - whole_stream_command(Wrap), - ]); - - for sample_pipeline in examples { - let mut ctx = base_context.clone(); - - let block = parse_line(sample_pipeline.example, &ctx)?; - - if let Some(expected) = &sample_pipeline.result { - let start = std::time::Instant::now(); - let result = evaluate_block(block, &mut ctx)?; - - println!("input: {}", sample_pipeline.example); - println!("result: {:?}", result); - println!("done: {:?}", start.elapsed()); - - ctx.with_errors(|reasons| reasons.iter().cloned().take(1).next()) - .map_or(Ok(()), Err)?; - - if expected.len() != result.len() { - let rows_returned = - format!("expected: {}\nactual: {}", expected.len(), result.len()); - let failed_call = format!("command: {}\n", sample_pipeline.example); - - panic!( - "example command produced unexpected number of results.\n {} {}", - failed_call, rows_returned - ); - } - - for (e, a) in expected.iter().zip(&result) { - if !values_equal(e, a) { - let row_errored = format!("expected: {:#?}\nactual: {:#?}", e, a); - let failed_call = format!("command: {}\n", sample_pipeline.example); - - panic!( - "example command produced unexpected result.\n {} {}", - failed_call, row_errored - ); - } - } - } - } - - Ok(()) -} - -#[cfg(feature = "dataframe")] -pub fn test_dataframe(cmd: impl WholeStreamCommand + 'static) -> Result<(), ShellError> { - use nu_protocol::UntaggedValue; - - let examples = cmd.examples(); - - let base_context = EvaluationContext::basic(); - - base_context.add_commands(vec![ - whole_stream_command(cmd), - // Commands used with dataframe - whole_stream_command(DataFrameToDF), - whole_stream_command(DataFrameShift), - whole_stream_command(DataFrameIsNull), - whole_stream_command(DataFrameGroupBy), - whole_stream_command(DataFrameWithColumn), - whole_stream_command(DataFrameDropNulls), - // Base commands for context - whole_stream_command(Math), - whole_stream_command(MathMode {}), - whole_stream_command(Echo {}), - whole_stream_command(BuildString {}), - whole_stream_command(Get {}), - whole_stream_command(Keep {}), - whole_stream_command(Each {}), - whole_stream_command(Let {}), - whole_stream_command(Select), - whole_stream_command(StrCollect), - whole_stream_command(Collect), - whole_stream_command(Wrap), - whole_stream_command(StrToDatetime), - ]); - - for sample_pipeline in examples { - let mut ctx = base_context.clone(); - - println!("{:?}", &sample_pipeline.example); - let block = parse_line(sample_pipeline.example, &ctx)?; - - if let Some(expected) = &sample_pipeline.result { - let start = std::time::Instant::now(); - let result = evaluate_block(block, &mut ctx)?; - - println!("input: {}", sample_pipeline.example); - println!("result: {:?}", result); - println!("done: {:?}", start.elapsed()); - - let value = match result.get(0) { - Some(v) => v, - None => panic!( - "Unable to extract a value after parsing example: {}", - sample_pipeline.example - ), - }; - - let df = match &value.value { - UntaggedValue::DataFrame(df) => df, - _ => panic!( - "Unable to extract dataframe from parsed example: {}", - sample_pipeline.example - ), - }; - - let expected = match expected.get(0) { - Some(v) => v, - None => panic!("Empty vector in result example"), - }; - - let df_expected = match &expected.value { - UntaggedValue::DataFrame(df) => df, - _ => panic!("Unable to extract dataframe from example result"), - }; - - println!("expected: {:?}", df_expected); - - assert_eq!(df, df_expected) - } - } - - Ok(()) -} - -pub fn test_anchors(cmd: Command) -> Result<(), ShellError> { - let examples = cmd.examples(); - - let base_context = EvaluationContext::basic(); - - base_context.add_commands(vec![ - // Minimal restricted commands to aid in testing - whole_stream_command(StubOpen {}), - whole_stream_command(DoubleEcho {}), - whole_stream_command(DoubleLs {}), - whole_stream_command(Append {}), - whole_stream_command(BuildString {}), - whole_stream_command(First {}), - whole_stream_command(Get {}), - whole_stream_command(If {}), - whole_stream_command(IntoInt {}), - whole_stream_command(Keep {}), - whole_stream_command(Each {}), - whole_stream_command(Last {}), - whole_stream_command(Nth {}), - whole_stream_command(Let {}), - whole_stream_command(Select), - whole_stream_command(StrCollect), - whole_stream_command(Collect), - whole_stream_command(Wrap), - cmd, - ]); - - for sample_pipeline in examples { - let pipeline_with_anchor = format!("stub open --path | {}", sample_pipeline.example); - - let mut ctx = base_context.clone(); - - let block = parse_line(&pipeline_with_anchor, &ctx)?; - - if sample_pipeline.result.is_some() { - let result = evaluate_block(block, &mut ctx)?; - - ctx.with_errors(|reasons| reasons.iter().cloned().next()) - .map_or(Ok(()), Err)?; - - for actual in &result { - if !is_anchor_carried(actual, mock_path()) { - let failed_call = format!("command: {}\n", pipeline_with_anchor); - - panic!( - "example command didn't carry anchor tag correctly.\n {} {:#?} {:#?}", - failed_call, - actual, - mock_path() - ); - } - } - } - } - - Ok(()) -} - -/// Parse and run a nushell pipeline -fn parse_line(line: &str, ctx: &EvaluationContext) -> Result { - //FIXME: do we still need this? - let line = if let Some(line) = line.strip_suffix('\n') { - line - } else { - line - }; - - let (lite_result, err) = nu_parser::lex(line, 0, nu_parser::NewlineMode::Normal); - if let Some(err) = err { - return Err(err.into()); - } - let (lite_result, err) = nu_parser::parse_block(lite_result); - if let Some(err) = err { - return Err(err.into()); - } - - // TODO ensure the command whose examples we're testing is actually in the pipeline - let (block, err) = nu_parser::classify_block(&lite_result, &ctx.scope); - Ok(ClassifiedBlock { block, failed: err }) -} - -fn evaluate_block( - block: ClassifiedBlock, - ctx: &mut EvaluationContext, -) -> Result, ShellError> { - let input_stream = InputStream::empty(); - - ctx.scope.enter_scope(); - - let result = run_block(&block.block, ctx, input_stream, ExternalRedirection::Stdout); - - ctx.scope.exit_scope(); - - let result = result?.drain_vec(); - Ok(result) -} - -// TODO probably something already available to do this -// TODO perhaps better panic messages when things don't compare - -// Deep value comparisons that ignore tags -fn values_equal(expected: &Value, actual: &Value) -> bool { - use nu_protocol::UntaggedValue::*; - - match (&expected.value, &actual.value) { - (Primitive(e), Primitive(a)) => e == a, - (Row(e), Row(a)) => { - if e.entries.len() != a.entries.len() { - return false; - } - - e.entries - .iter() - .zip(&a.entries) - .all(|((ek, ev), (ak, av))| ek == ak && values_equal(ev, av)) - } - (Table(e), Table(a)) => e.iter().zip(a).all(|(e, a)| values_equal(e, a)), - (e, a) => unimplemented!("{} {}", e.type_name(), a.type_name()), - } -} - -fn is_anchor_carried(actual: &Value, anchor: AnchorLocation) -> bool { - actual.tag.anchor() == Some(anchor) -} diff --git a/old_nushell/crates/nu-command/src/examples/double_echo.rs b/old_nushell/crates/nu-command/src/examples/double_echo.rs deleted file mode 100644 index e06e3ae27..000000000 --- a/old_nushell/crates/nu-command/src/examples/double_echo.rs +++ /dev/null @@ -1,86 +0,0 @@ -use nu_errors::ShellError; - -use nu_engine::{CommandArgs, WholeStreamCommand}; -use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; -use nu_stream::{ActionStream, IntoActionStream}; - -use serde::Deserialize; - -pub struct Command; - -#[derive(Deserialize)] -struct Arguments { - #[allow(unused)] - pub rest: Vec, -} - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "echo" - } - - fn signature(&self) -> Signature { - Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo") - } - - fn usage(&self) -> &str { - "Mock echo." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - let rest: Vec = args.rest(0)?; - - let mut base_value = UntaggedValue::string("Yehuda Katz in Ecuador").into_value(name_tag); - let input: Vec = args.input.collect(); - - if let Some(first) = input.get(0) { - base_value = first.clone() - } - - let stream = rest.into_iter().flat_map(move |i| { - let base_value = base_value.clone(); - match i.as_string() { - Ok(s) => ActionStream::one(Ok(ReturnSuccess::Value(Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - tag: base_value.tag, - }))), - _ => match i { - Value { - value: UntaggedValue::Table(table), - .. - } => { - if table.len() == 1 && table[0].is_table() { - let mut values: Vec = - table[0].table_entries().cloned().collect(); - - for v in &mut values { - v.tag = base_value.tag(); - } - - let subtable = - vec![UntaggedValue::Table(values).into_value(base_value.tag())]; - - (subtable.into_iter().map(ReturnSuccess::value)).into_action_stream() - } else { - (table - .into_iter() - .map(move |mut v| { - v.tag = base_value.tag(); - v - }) - .map(ReturnSuccess::value)) - .into_action_stream() - } - } - _ => ActionStream::one(Ok(ReturnSuccess::Value(Value { - value: i.value.clone(), - tag: base_value.tag, - }))), - }, - } - }); - - Ok(stream.into_action_stream()) - } -} diff --git a/old_nushell/crates/nu-command/src/examples/double_ls.rs b/old_nushell/crates/nu-command/src/examples/double_ls.rs deleted file mode 100644 index 2628f3dce..000000000 --- a/old_nushell/crates/nu-command/src/examples/double_ls.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::examples::sample::ls::file_listing; - -use nu_engine::{CommandArgs, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; -use nu_stream::{ActionStream, IntoActionStream}; - -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "ls" - } - - fn signature(&self) -> Signature { - Signature::build("ls") - } - - fn usage(&self) -> &str { - "Mock ls." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - - let mut base_value = - UntaggedValue::string("Andrés N. Robalino in Portland").into_value(name_tag); - let input: Vec = args.input.collect(); - - if let Some(first) = input.get(0) { - base_value = first.clone() - } - - Ok((file_listing() - .iter() - .map(|row| Value { - value: row.value.clone(), - tag: base_value.tag.clone(), - }) - .collect::>() - .into_iter() - .map(ReturnSuccess::value)) - .into_action_stream()) - } -} diff --git a/old_nushell/crates/nu-command/src/examples/sample.rs b/old_nushell/crates/nu-command/src/examples/sample.rs deleted file mode 100644 index d3a592c67..000000000 --- a/old_nushell/crates/nu-command/src/examples/sample.rs +++ /dev/null @@ -1,35 +0,0 @@ -use nu_protocol::{row, Value}; -use nu_test_support::value::{date, int, string}; - -pub mod ls { - use super::*; - - pub fn file_listing() -> Vec { - vec![ - row! { - "name".to_string() => string("Andres.txt"), - "type".to_string() => string("File"), - "chickens".to_string() => int(10), - "modified".to_string() => date("2019-07-23") - }, - row! { - "name".to_string() => string("Jonathan"), - "type".to_string() => string("Dir"), - "chickens".to_string() => int(5), - "modified".to_string() => date("2019-07-23") - }, - row! { - "name".to_string() => string("Darren.txt"), - "type".to_string() => string("File"), - "chickens".to_string() => int(20), - "modified".to_string() => date("2019-09-24") - }, - row! { - "name".to_string() => string("Yehuda"), - "type".to_string() => string("Dir"), - "chickens".to_string() => int(4), - "modified".to_string() => date("2019-09-24") - }, - ] - } -} diff --git a/old_nushell/crates/nu-command/src/examples/stub_generate.rs b/old_nushell/crates/nu-command/src/examples/stub_generate.rs deleted file mode 100644 index 4dbe8abb3..000000000 --- a/old_nushell/crates/nu-command/src/examples/stub_generate.rs +++ /dev/null @@ -1,48 +0,0 @@ -use nu_engine::{CommandArgs, WholeStreamCommand}; -use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; -use nu_source::{AnchorLocation, Tag}; -use nu_stream::ActionStream; -pub struct Command; - -impl WholeStreamCommand for Command { - fn name(&self) -> &str { - "stub open" - } - - fn signature(&self) -> Signature { - Signature::build("stub open").switch("path", "Add a mocked path", Some('p')) - } - - fn usage(&self) -> &str { - "Generates tables and metadata that mimics behavior of real commands in controlled ways." - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - let name_tag = args.call_info.name_tag.clone(); - - let mocked_path = args.call_info.switch_present("path"); - - let out = UntaggedValue::string("Yehuda Katz in Ecuador"); - - if mocked_path { - Ok(ActionStream::one(Ok(ReturnSuccess::Value(Value { - value: out, - tag: Tag { - anchor: Some(mock_path()), - span: name_tag.span, - }, - })))) - } else { - Ok(ActionStream::one(Ok(ReturnSuccess::Value( - out.into_value(name_tag), - )))) - } - } -} - -pub fn mock_path() -> AnchorLocation { - let path = String::from("path/to/las_best_arepas_in_the_world.txt"); - - AnchorLocation::File(path) -} diff --git a/old_nushell/crates/nu-command/src/lib.rs b/old_nushell/crates/nu-command/src/lib.rs deleted file mode 100644 index ecb91f5c2..000000000 --- a/old_nushell/crates/nu-command/src/lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![recursion_limit = "2048"] - -#[cfg(test)] -#[macro_use] -extern crate indexmap; - -#[macro_use] -mod prelude; -mod classified; -pub mod commands; -mod default_context; -pub mod utils; - -#[cfg(test)] -mod examples; - -pub use crate::default_context::create_default_context; -pub use nu_data::config; -pub use nu_data::dict::TaggedListBuilder; -pub use nu_data::primitive; -pub use nu_data::value; -pub use nu_stream::{ActionStream, InputStream, InterruptibleStream}; -pub use nu_value_ext::ValueExt; -pub use num_traits::cast::ToPrimitive; - -// TODO: Temporary redirect -pub use nu_protocol::{did_you_mean, TaggedDictBuilder}; diff --git a/old_nushell/crates/nu-command/src/prelude.rs b/old_nushell/crates/nu-command/src/prelude.rs deleted file mode 100644 index 26dc518bc..000000000 --- a/old_nushell/crates/nu-command/src/prelude.rs +++ /dev/null @@ -1,32 +0,0 @@ -#[macro_export] -macro_rules! return_err { - ($expr:expr) => { - match $expr { - Err(_) => return, - Ok(expr) => expr, - }; - }; -} - -pub(crate) use bigdecimal::BigDecimal; -pub(crate) use indexmap::{indexmap, IndexMap}; -pub(crate) use itertools::Itertools; -pub(crate) use nu_data::config; -pub(crate) use nu_data::value; -pub(crate) use nu_engine::EvaluationContext; -pub(crate) use nu_engine::Example; -pub(crate) use nu_engine::Host; -pub(crate) use nu_engine::RunnableContext; -pub(crate) use nu_engine::{get_full_help, CommandArgs, Scope, WholeStreamCommand}; -pub(crate) use nu_parser::ParserScope; -pub(crate) use nu_protocol::{out, row}; -pub(crate) use nu_source::{AnchorLocation, PrettyDebug, Span, SpannedItem, Tag, TaggedItem}; -pub(crate) use nu_stream::{ActionStream, InputStream, Interruptible, OutputStream}; -pub(crate) use nu_stream::{IntoActionStream, IntoInputStream, IntoOutputStream}; -pub(crate) use nu_value_ext::ValueExt; -pub(crate) use num_bigint::BigInt; -pub(crate) use num_traits::cast::ToPrimitive; -pub(crate) use serde::Deserialize; -pub(crate) use std::collections::VecDeque; -pub(crate) use std::sync::atomic::AtomicBool; -pub(crate) use std::sync::Arc; diff --git a/old_nushell/crates/nu-command/src/utils.rs b/old_nushell/crates/nu-command/src/utils.rs deleted file mode 100644 index ed6dc62fc..000000000 --- a/old_nushell/crates/nu-command/src/utils.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod suggestions; -pub mod test_bins; diff --git a/old_nushell/crates/nu-command/src/utils/suggestions.rs b/old_nushell/crates/nu-command/src/utils/suggestions.rs deleted file mode 100644 index b96ee86ec..000000000 --- a/old_nushell/crates/nu-command/src/utils/suggestions.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::did_you_mean; -use nu_errors::ShellError; -use nu_protocol::Value; -use nu_source::Tagged; - -pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError { - let possibilities = did_you_mean(for_value, tried.to_string()); - - match possibilities { - Some(p) => ShellError::labeled_error( - "Unknown column", - format!("did you mean '{}'?", p[0]), - tried.tag(), - ), - None => ShellError::labeled_error( - "Unknown column", - "row does not contain this column", - tried.tag(), - ), - } -} diff --git a/old_nushell/crates/nu-command/src/utils/test_bins.rs b/old_nushell/crates/nu-command/src/utils/test_bins.rs deleted file mode 100644 index b02f00e09..000000000 --- a/old_nushell/crates/nu-command/src/utils/test_bins.rs +++ /dev/null @@ -1,123 +0,0 @@ -use std::io::{self, BufRead, Write}; - -/// Echo's value of env keys from args -/// Example: nu --testbin env_echo FOO BAR -/// If it it's not present echo's nothing -pub fn echo_env() { - let args = args(); - for arg in args { - if let Ok(v) = std::env::var(arg) { - println!("{}", v); - } - } -} - -pub fn cococo() { - let args: Vec = args(); - - if args.len() > 1 { - // Write back out all the arguments passed - // if given at least 1 instead of chickens - // speaking co co co. - println!("{}", &args[1..].join(" ")); - } else { - println!("cococo"); - } -} - -pub fn meow() { - let args: Vec = args(); - - for arg in args.iter().skip(1) { - let contents = std::fs::read_to_string(arg).expect("Expected a filepath"); - println!("{}", contents); - } -} - -pub fn nonu() { - args().iter().skip(1).for_each(|arg| print!("{}", arg)); -} - -pub fn repeater() { - let mut stdout = io::stdout(); - let args = args(); - let mut args = args.iter().skip(1); - let letter = args.next().expect("needs a character to iterate"); - let count = args.next().expect("need the number of times to iterate"); - - let count: u64 = count.parse().expect("can't convert count to number"); - - for _ in 0..count { - let _ = write!(stdout, "{}", letter); - } - let _ = stdout.flush(); -} - -pub fn iecho() { - // println! panics if stdout gets closed, whereas writeln gives us an error - let mut stdout = io::stdout(); - let _ = args() - .iter() - .skip(1) - .cycle() - .try_for_each(|v| writeln!(stdout, "{}", v)); -} - -pub fn fail() { - std::process::exit(1); -} - -pub fn chop() { - if did_chop_arguments() { - // we are done and don't care about standard input. - std::process::exit(0); - } - - // if no arguments given, chop from standard input and exit. - let stdin = io::stdin(); - let mut stdout = io::stdout(); - - for given in stdin.lock().lines().flatten() { - let chopped = if given.is_empty() { - &given - } else { - let to = given.len() - 1; - &given[..to] - }; - - if let Err(_e) = writeln!(stdout, "{}", chopped) { - break; - } - } - - std::process::exit(0); -} - -fn did_chop_arguments() -> bool { - let args: Vec = args(); - - if args.len() > 1 { - let mut arguments = args.iter(); - arguments.next(); - - for arg in arguments { - let chopped = if arg.is_empty() { - &arg - } else { - let to = arg.len() - 1; - &arg[..to] - }; - - println!("{}", chopped); - } - - return true; - } - - false -} - -fn args() -> Vec { - // skip (--testbin bin_name args) - std::env::args().skip(2).collect() -} diff --git a/old_nushell/crates/nu-command/tests/commands/all.rs b/old_nushell/crates/nu-command/tests/commands/all.rs deleted file mode 100644 index 2012ff0de..000000000 --- a/old_nushell/crates/nu-command/tests/commands/all.rs +++ /dev/null @@ -1,69 +0,0 @@ -use nu_test_support::pipeline as input; -use nu_test_support::playground::{says, Playground}; - -use hamcrest2::assert_that; -use hamcrest2::prelude::*; - -#[test] -fn checks_all_rows_are_true() { - Playground::setup("all_test_1", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - echo [ "Andrés", "Andrés", "Andrés" ] - | all? $it == "Andrés" - "# - )), - says().stdout("true") - ); - }) -} - -#[test] -fn checks_all_rows_are_false_with_param() { - Playground::setup("all_test_1", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - [1, 2, 3, 4] | all? { |a| $a >= 5 } - "# - )), - says().stdout("false") - ); - }) -} - -#[test] -fn checks_all_rows_are_true_with_param() { - Playground::setup("all_test_1", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - [1, 2, 3, 4] | all? { |a| $a < 5 } - "# - )), - says().stdout("true") - ); - }) -} - -#[test] -fn checks_all_columns_of_a_table_is_true() { - Playground::setup("any_test_1", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - echo [ - [ first_name, last_name, rusty_at, likes ]; - [ Andrés, Robalino, 10/11/2013, 1 ] - [ Jonathan, Turner, 10/12/2013, 1 ] - [ Darren, Schroeder, 10/11/2013, 1 ] - [ Yehuda, Katz, 10/11/2013, 1 ] - ] - | all? likes > 0 - "# - )), - says().stdout("true") - ); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/any.rs b/old_nushell/crates/nu-command/tests/commands/any.rs deleted file mode 100644 index 255673f80..000000000 --- a/old_nushell/crates/nu-command/tests/commands/any.rs +++ /dev/null @@ -1,41 +0,0 @@ -use nu_test_support::pipeline as input; -use nu_test_support::playground::{says, Playground}; - -use hamcrest2::assert_that; -use hamcrest2::prelude::*; - -#[test] -fn checks_any_row_is_true() { - Playground::setup("any_test_1", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - echo [ "Ecuador", "USA", "New Zealand" ] - | any? $it == "New Zealand" - "# - )), - says().stdout("true") - ); - }) -} - -#[test] -fn checks_any_column_of_a_table_is_true() { - Playground::setup("any_test_1", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - echo [ - [ first_name, last_name, rusty_at, likes ]; - [ Andrés, Robalino, 10/11/2013, 1 ] - [ Jonathan, Turner, 10/12/2013, 1 ] - [ Darren, Schroeder, 10/11/2013, 1 ] - [ Yehuda, Katz, 10/11/2013, 1 ] - ] - | any? rusty_at == 10/12/2013 - "# - )), - says().stdout("true") - ); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/append.rs b/old_nushell/crates/nu-command/tests/commands/append.rs deleted file mode 100644 index 36318264a..000000000 --- a/old_nushell/crates/nu-command/tests/commands/append.rs +++ /dev/null @@ -1,21 +0,0 @@ -use nu_test_support::pipeline as input; -use nu_test_support::playground::{says, Playground}; - -use hamcrest2::assert_that; -use hamcrest2::prelude::*; - -#[test] -fn adds_a_row_to_the_end() { - Playground::setup("append_test_1", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - echo [ "Andrés N. Robalino", "Jonathan Turner", "Yehuda Katz" ] - | append "pollo loco" - | nth 3 - "# - )), - says().stdout("pollo loco") - ); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/cal.rs b/old_nushell/crates/nu-command/tests/commands/cal.rs deleted file mode 100644 index eafceb900..000000000 --- a/old_nushell/crates/nu-command/tests/commands/cal.rs +++ /dev/null @@ -1,79 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn cal_full_year() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cal -y --full-year 2010 | first | to json - "# - )); - - let first_week_2010_json = r#"{"year":2010,"sunday":null,"monday":null,"tuesday":null,"wednesday":null,"thursday":null,"friday":1,"saturday":2}"#; - - assert_eq!(actual.out, first_week_2010_json); -} - -#[test] -fn cal_february_2020_leap_year() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cal -ym --full-year 2020 --month-names | where month == "february" | to json - "# - )); - - let cal_february_json = r#"[{"year":2020,"month":"february","sunday":null,"monday":null,"tuesday":null,"wednesday":null,"thursday":null,"friday":null,"saturday":1},{"year":2020,"month":"february","sunday":2,"monday":3,"tuesday":4,"wednesday":5,"thursday":6,"friday":7,"saturday":8},{"year":2020,"month":"february","sunday":9,"monday":10,"tuesday":11,"wednesday":12,"thursday":13,"friday":14,"saturday":15},{"year":2020,"month":"february","sunday":16,"monday":17,"tuesday":18,"wednesday":19,"thursday":20,"friday":21,"saturday":22},{"year":2020,"month":"february","sunday":23,"monday":24,"tuesday":25,"wednesday":26,"thursday":27,"friday":28,"saturday":29}]"#; - - assert_eq!(actual.out, cal_february_json); -} - -#[test] -fn cal_friday_the_thirteenths_in_2015() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cal --full-year 2015 | default friday 0 | where friday == 13 | length - "# - )); - - assert!(actual.out.contains('3')); -} - -#[test] -fn cal_rows_in_2020() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cal --full-year 2020 | length - "# - )); - - assert!(actual.out.contains("62")); -} - -#[test] -fn cal_week_day_start_monday() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cal --full-year 2020 -m --month-names --week-start monday | where month == january | to json - "# - )); - - let cal_january_json = r#"[{"month":"january","monday":null,"tuesday":null,"wednesday":1,"thursday":2,"friday":3,"saturday":4,"sunday":5},{"month":"january","monday":6,"tuesday":7,"wednesday":8,"thursday":9,"friday":10,"saturday":11,"sunday":12},{"month":"january","monday":13,"tuesday":14,"wednesday":15,"thursday":16,"friday":17,"saturday":18,"sunday":19},{"month":"january","monday":20,"tuesday":21,"wednesday":22,"thursday":23,"friday":24,"saturday":25,"sunday":26},{"month":"january","monday":27,"tuesday":28,"wednesday":29,"thursday":30,"friday":31,"saturday":null,"sunday":null}]"#; - - assert_eq!(actual.out, cal_january_json); -} - -#[test] -fn cal_sees_pipeline_year() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cal --full-year 1020 | get monday | first 3 | to json - "# - )); - - assert_eq!(actual.out, "[3,10,17]"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/cd.rs b/old_nushell/crates/nu-command/tests/commands/cd.rs deleted file mode 100644 index 229aa23d5..000000000 --- a/old_nushell/crates/nu-command/tests/commands/cd.rs +++ /dev/null @@ -1,458 +0,0 @@ -use nu_test_support::fs::{Stub::EmptyFile, Stub::FileWithContent}; -use nu_test_support::nu; -use nu_test_support::playground::Playground; -use std::path::PathBuf; - -#[test] -fn filesystem_change_from_current_directory_using_relative_path() { - Playground::setup("cd_test_1", |dirs, _| { - let actual = nu!( - cwd: dirs.root(), - r#" - cd cd_test_1 - echo (pwd) - "# - ); - - assert_eq!(PathBuf::from(actual.out), *dirs.test()); - }) -} - -#[test] -fn filesystem_change_from_current_directory_using_absolute_path() { - Playground::setup("cd_test_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - r#" - cd "{}" - echo (pwd) - "#, - dirs.formats() - ); - - assert_eq!(PathBuf::from(actual.out), dirs.formats()); - }) -} - -#[test] -fn filesystem_switch_back_to_previous_working_directory() { - Playground::setup("cd_test_3", |dirs, sandbox| { - sandbox.mkdir("odin"); - - let actual = nu!( - cwd: dirs.test().join("odin"), - r#" - cd {} - cd - - echo (pwd) - "#, - dirs.test() - ); - - assert_eq!(PathBuf::from(actual.out), dirs.test().join("odin")); - }) -} - -#[test] -fn filesytem_change_from_current_directory_using_relative_path_and_dash() { - Playground::setup("cd_test_4", |dirs, sandbox| { - sandbox.within("odin").mkdir("-"); - - let actual = nu!( - cwd: dirs.test(), - r#" - cd odin/- - echo (pwd) - "# - ); - - assert_eq!( - PathBuf::from(actual.out), - dirs.test().join("odin").join("-") - ); - }) -} - -#[test] -fn filesystem_change_current_directory_to_parent_directory() { - Playground::setup("cd_test_5", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - r#" - cd .. - echo (pwd) - "# - ); - - assert_eq!(PathBuf::from(actual.out), *dirs.root()); - }) -} - -#[test] -fn filesystem_change_current_directory_to_two_parents_up_using_multiple_dots() { - Playground::setup("cd_test_6", |dirs, sandbox| { - sandbox.within("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test().join("foo/bar"), - r#" - cd ... - echo (pwd) - "# - ); - - assert_eq!(PathBuf::from(actual.out), *dirs.test()); - }) -} - -#[test] -fn filesystem_change_current_directory_to_parent_directory_after_delete_cwd() { - Playground::setup("cd_test_7", |dirs, sandbox| { - sandbox.within("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test().join("foo/bar"), - r#" - rm {}/foo/bar - echo "," - cd .. - echo (pwd) - "#, - dirs.test() - ); - - let actual = actual.out.split(',').nth(1).unwrap(); - - assert_eq!(PathBuf::from(actual), *dirs.test().join("foo")); - }) -} - -#[test] -fn filesystem_change_to_home_directory() { - Playground::setup("cd_test_8", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - r#" - cd ~ - echo (pwd) - "# - ); - - assert_eq!(Some(PathBuf::from(actual.out)), dirs_next::home_dir()); - }) -} - -#[test] -fn filesystem_change_to_a_directory_containing_spaces() { - Playground::setup("cd_test_9", |dirs, sandbox| { - sandbox.mkdir("robalino turner katz"); - - let actual = nu!( - cwd: dirs.test(), - r#" - cd "robalino turner katz" - echo (pwd) - "# - ); - - assert_eq!( - PathBuf::from(actual.out), - dirs.test().join("robalino turner katz") - ); - }) -} - -#[test] -fn filesystem_not_a_directory() { - Playground::setup("cd_test_10", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("ferris_did_it.txt")]); - - let actual = nu!( - cwd: dirs.test(), - "cd ferris_did_it.txt" - ); - - assert!( - actual.err.contains("ferris_did_it.txt"), - "actual={:?}", - actual.err - ); - assert!( - actual.err.contains("is not a directory"), - "actual={:?}", - actual.err - ); - }) -} - -#[test] -fn filesystem_directory_not_found() { - Playground::setup("cd_test_11", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - "cd dir_that_does_not_exist" - - ); - - assert!( - actual.err.contains("dir_that_does_not_exist"), - "actual={:?}", - actual.err - ); - assert!( - actual.err.contains("directory not found"), - "actual={:?}", - actual.err - ); - }) -} - -#[test] -fn filesystem_change_directory_to_symlink_relative() { - Playground::setup("cd_test_12", |dirs, sandbox| { - sandbox.mkdir("foo"); - sandbox.mkdir("boo"); - sandbox.symlink("foo", "foo_link"); - - let actual = nu!( - cwd: dirs.test().join("boo"), - r#" - cd ../foo_link - echo (pwd) - "# - ); - - assert_eq!(PathBuf::from(actual.out), dirs.test().join("foo")); - }) -} - -#[test] -fn valuesystem_change_from_current_path_using_relative_path() { - Playground::setup("cd_test_13", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [[bin]] - path = "src/plugins/turner.rs" - - [[bin]] - path = "src/plugins/robalino.rs" - - [[bin]] - path = "src/plugins/katz.rs" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - r#" - enter sample.toml - cd bin - pwd - exit - "# - ); - - assert_eq!(PathBuf::from(actual.out), PathBuf::from("/bin")); - }) -} - -#[test] -fn valuesystem_change_from_current_path_using_absolute_path() { - Playground::setup("cd_test_14", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [dependencies] - turner-ts = "0.1.1" - robalino-tkd = "0.0.1" - katz-ember = "0.2.3" - - [[bin]] - path = "src/plugins/arepa.rs" - - [[bin]] - path = "src/plugins/bbq.rs" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - r#" - enter sample.toml - cd bin - cd /dependencies - pwd - exit - "# - ); - - assert_eq!(PathBuf::from(actual.out), PathBuf::from("/dependencies")); - }) -} - -#[test] -fn valuesystem_switch_back_to_previous_working_path() { - Playground::setup("cd_test_15", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [dependencies] - turner-ts = "0.1.1" - robalino-tkd = "0.0.1" - katz-ember = "0.2.3" - odin-gf = "0.2.1" - - [[bin]] - path = "src/plugins/arepa.rs" - - [[bin]] - path = "src/plugins/bbq.rs" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - r#" - enter sample.toml - cd dependencies - cd /bin - cd - - pwd - exit - "# - ); - - assert_eq!(PathBuf::from(actual.out), PathBuf::from("/dependencies")); - }) -} - -#[test] -fn valuesystem_change_from_current_path_using_relative_path_and_dash() { - Playground::setup("cd_test_16", |dirs, sandbox| { - sandbox - .with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - - = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] - - [[bin]] - path = "src/plugins/arepa.rs" - - [[bin]] - path = "src/plugins/bbq.rs" - "# - )]); - - let actual = nu!( - cwd: dirs.test(), - r#" - enter sample.toml - cd package/- - cd /bin - cd - - pwd - exit - "# - ); - - assert_eq!(PathBuf::from(actual.out), PathBuf::from("/package/-")); - }) -} - -#[test] -fn valuesystem_change_current_path_to_parent_path() { - Playground::setup("cd_test_17", |dirs, sandbox| { - sandbox - .with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - emberenios = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] - "# - )]); - - let actual = nu!( - cwd: dirs.test(), - r#" - enter sample.toml - cd package/emberenios - cd .. - pwd - exit - "# - ); - - assert_eq!(PathBuf::from(actual.out), PathBuf::from("/package")); - }) -} - -#[test] -fn valuesystem_change_to_a_path_containing_spaces() { - Playground::setup("cd_test_18", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - ["pa que te"] - el = "pollo loco" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - r#" - enter sample.toml - cd "pa que te" - pwd - exit - "# - ); - - assert_eq!( - PathBuf::from(actual.out), - PathBuf::from("/").join("pa que te") - ); - }) -} - -#[test] -fn valuesystem_path_not_found() { - Playground::setup("cd_test_19", |dirs, _| { - let actual = nu!( - cwd: dirs.formats(), - r#" - enter cargo_sample.toml - cd im_a_path_that_does_not_exist - exit - "# - ); - - assert!(actual.err.contains("Can not change to path inside")); - assert!(actual.err.contains("No such path exists")); - }) -} - -#[cfg(target_os = "windows")] -#[test] -fn test_change_windows_drive() { - Playground::setup("cd_test_20", |dirs, sandbox| { - sandbox.mkdir("test_folder"); - - let _actual = nu!( - cwd: dirs.test(), - r#" - subst Z: test_folder - Z: - echo "some text" | save test_file.txt - cd ~ - subst Z: /d - "# - ); - assert!(dirs - .test() - .join("test_folder") - .join("test_file.txt") - .exists()); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/compact.rs b/old_nushell/crates/nu-command/tests/commands/compact.rs deleted file mode 100644 index 21b4db674..000000000 --- a/old_nushell/crates/nu-command/tests/commands/compact.rs +++ /dev/null @@ -1,50 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn discards_rows_where_given_column_is_empty() { - Playground::setup("compact_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.json", - r#" - { - "amigos": [ - {"name": "Yehuda", "rusty_luck": 1}, - {"name": "Jonathan", "rusty_luck": 1}, - {"name": "Andres", "rusty_luck": 1}, - {"name":"GorbyPuff"} - ] - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_amigos.json - | get amigos - | compact rusty_luck - | length - "# - )); - - assert_eq!(actual.out, "3"); - }); -} -#[test] -fn discards_empty_rows_by_default() { - Playground::setup("compact_test_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "[1,2,3,14,null]" - | from json - | compact - | length - "# - )); - - assert_eq!(actual.out, "4"); - }); -} diff --git a/old_nushell/crates/nu-command/tests/commands/config.rs b/old_nushell/crates/nu-command/tests/commands/config.rs deleted file mode 100644 index abce38a7a..000000000 --- a/old_nushell/crates/nu-command/tests/commands/config.rs +++ /dev/null @@ -1,138 +0,0 @@ -use nu_test_support::fs::AbsolutePath; -use nu_test_support::fs::Stub::FileWithContent; -use nu_test_support::playground::{says, Playground}; - -use hamcrest2::assert_that; -use hamcrest2::prelude::*; - -#[test] -fn clearing_config_clears_config() { - Playground::setup("environment_syncing_test_1", |dirs, nu| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - nu.with_config(&file); - nu.with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - "#, - )]); - - assert_that!( - nu.pipeline("config clear | ignore; config get skip_welcome_message"), - says().stdout("") - ); - let config_contents = std::fs::read_to_string(file).expect("Could not read file"); - assert!(config_contents.is_empty()); - }); -} - -#[test] -fn config_get_returns_value() { - Playground::setup("environment_syncing_test_1", |dirs, nu| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - nu.with_config(&file); - nu.with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - "#, - )]); - - assert_that!( - //Clears config - nu.pipeline("config get skip_welcome_message"), - says().stdout("true") - ); - }); -} - -#[test] -fn config_set_sets_value() { - Playground::setup("environment_syncing_test_1", |dirs, nu| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - nu.with_config(&file); - nu.with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - "#, - )]); - - assert_that!( - //Clears config - nu.pipeline("config set key value | ignore; config get key"), - says().stdout("value") - ); - let config_contents = std::fs::read_to_string(file).expect("Could not read file"); - assert!(config_contents.contains("key = \"value\"")); - }); -} - -#[test] -fn config_set_into_sets_value() { - Playground::setup("environment_syncing_test_1", |dirs, nu| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - nu.with_config(&file); - nu.with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - "#, - )]); - - assert_that!( - //Clears config - nu.pipeline("echo value | config set_into key | ignore; config get key"), - says().stdout("value") - ); - let config_contents = std::fs::read_to_string(file).expect("Could not read file"); - assert!(config_contents.contains("key = \"value\"")); - }); -} - -#[test] -fn config_rm_removes_value() { - Playground::setup("environment_syncing_test_1", |dirs, nu| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - nu.with_config(&file); - nu.with_files(vec![FileWithContent( - "config.toml", - r#" - key = "value" - skip_welcome_message = true - "#, - )]); - - assert_that!( - nu.pipeline("config remove key | ignore; config get key"), - says().stdout("") - ); - let config_contents = std::fs::read_to_string(file).expect("Could not read file"); - assert!(!config_contents.contains("key = \"value\"")); - }); -} - -#[test] -fn config_path_returns_correct_path() { - Playground::setup("environment_syncing_test_1", |dirs, nu| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - nu.with_config(&file); - nu.with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - "#, - )]); - - assert_that!( - nu.pipeline("config path"), - says().stdout(&file.inner.to_string_lossy().to_string()) - ); - }); -} diff --git a/old_nushell/crates/nu-command/tests/commands/cp.rs b/old_nushell/crates/nu-command/tests/commands/cp.rs deleted file mode 100644 index 9fe1272b7..000000000 --- a/old_nushell/crates/nu-command/tests/commands/cp.rs +++ /dev/null @@ -1,237 +0,0 @@ -use nu_test_support::fs::{files_exist_at, AbsoluteFile, Stub::EmptyFile}; -use nu_test_support::nu; -use nu_test_support::playground::Playground; -use std::path::Path; - -#[test] -fn copies_a_file() { - Playground::setup("cp_test_1", |dirs, _| { - nu!( - cwd: dirs.root(), - "cp \"{}\" cp_test_1/sample.ini", - dirs.formats().join("sample.ini") - ); - - assert!(dirs.test().join("sample.ini").exists()); - }); -} - -#[test] -fn copies_the_file_inside_directory_if_path_to_copy_is_directory() { - Playground::setup("cp_test_2", |dirs, _| { - let expected_file = AbsoluteFile::new(dirs.test().join("sample.ini")); - - nu!( - cwd: dirs.formats(), - "cp ../formats/sample.ini {}", - expected_file.dir() - ); - - assert!(dirs.test().join("sample.ini").exists()); - }) -} - -#[test] -fn error_if_attempting_to_copy_a_directory_to_another_directory() { - Playground::setup("cp_test_3", |dirs, _| { - let actual = nu!( - cwd: dirs.formats(), - "cp ../formats {}", dirs.test() - ); - - assert!(actual.err.contains("../formats")); - assert!(actual.err.contains("resolves to a directory (not copied)")); - }); -} - -#[test] -fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_recursive_flag() { - Playground::setup("cp_test_4", |dirs, sandbox| { - sandbox - .within("originals") - .with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - ]) - .mkdir("expected"); - - let expected_dir = dirs.test().join("expected").join("originals"); - - nu!( - cwd: dirs.test(), - "cp originals expected -r" - ); - - assert!(expected_dir.exists()); - assert!(files_exist_at( - vec![ - Path::new("yehuda.txt"), - Path::new("jonathan.txt"), - Path::new("andres.txt") - ], - expected_dir - )); - }) -} - -#[test] -fn deep_copies_with_recursive_flag() { - Playground::setup("cp_test_5", |dirs, sandbox| { - sandbox - .within("originals") - .with_files(vec![EmptyFile("manifest.txt")]) - .within("originals/contributors") - .with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - ]) - .within("originals/contributors/jonathan") - .with_files(vec![EmptyFile("errors.txt"), EmptyFile("multishells.txt")]) - .within("originals/contributors/andres") - .with_files(vec![EmptyFile("coverage.txt"), EmptyFile("commands.txt")]) - .within("originals/contributors/yehuda") - .with_files(vec![EmptyFile("defer-evaluation.txt")]) - .mkdir("expected"); - - let expected_dir = dirs.test().join("expected").join("originals"); - - let jonathans_expected_copied_dir = expected_dir.join("contributors").join("jonathan"); - let andres_expected_copied_dir = expected_dir.join("contributors").join("andres"); - let yehudas_expected_copied_dir = expected_dir.join("contributors").join("yehuda"); - - nu!( - cwd: dirs.test(), - "cp originals expected --recursive" - ); - - assert!(expected_dir.exists()); - assert!(files_exist_at( - vec![Path::new("errors.txt"), Path::new("multishells.txt")], - jonathans_expected_copied_dir - )); - assert!(files_exist_at( - vec![Path::new("coverage.txt"), Path::new("commands.txt")], - andres_expected_copied_dir - )); - assert!(files_exist_at( - vec![Path::new("defer-evaluation.txt")], - yehudas_expected_copied_dir - )); - }) -} - -#[test] -fn copies_using_path_with_wildcard() { - Playground::setup("cp_test_6", |dirs, _| { - nu!( - cwd: dirs.formats(), - "cp ../formats/* {}", dirs.test() - ); - - assert!(files_exist_at( - vec![ - Path::new("caco3_plastics.csv"), - Path::new("cargo_sample.toml"), - Path::new("jonathan.xml"), - Path::new("sample.ini"), - Path::new("sgml_description.json"), - Path::new("utf16.ini"), - ], - dirs.test() - )); - }) -} - -#[test] -fn copies_using_a_glob() { - Playground::setup("cp_test_7", |dirs, _| { - nu!( - cwd: dirs.formats(), - "cp * {}", dirs.test() - ); - - assert!(files_exist_at( - vec![ - Path::new("caco3_plastics.csv"), - Path::new("cargo_sample.toml"), - Path::new("jonathan.xml"), - Path::new("sample.ini"), - Path::new("sgml_description.json"), - Path::new("utf16.ini"), - ], - dirs.test() - )); - }); -} - -#[test] -fn copies_same_file_twice() { - Playground::setup("cp_test_8", |dirs, _| { - nu!( - cwd: dirs.root(), - "cp \"{}\" cp_test_8/sample.ini", - dirs.formats().join("sample.ini") - ); - - nu!( - cwd: dirs.root(), - "cp \"{}\" cp_test_8/sample.ini", - dirs.formats().join("sample.ini") - ); - - assert!(dirs.test().join("sample.ini").exists()); - }); -} - -#[test] -fn copy_files_using_glob_two_parents_up_using_multiple_dots() { - Playground::setup("cp_test_9", |dirs, sandbox| { - sandbox.within("foo").within("bar").with_files(vec![ - EmptyFile("jonathan.json"), - EmptyFile("andres.xml"), - EmptyFile("yehuda.yaml"), - EmptyFile("kevin.txt"), - EmptyFile("many_more.ppl"), - ]); - - nu!( - cwd: dirs.test().join("foo/bar"), - r#" - cp * ... - "# - ); - - assert!(files_exist_at( - vec![ - "yehuda.yaml", - "jonathan.json", - "andres.xml", - "kevin.txt", - "many_more.ppl", - ], - dirs.test() - )); - }) -} - -#[test] -fn copy_file_and_dir_from_two_parents_up_using_multiple_dots_to_current_dir_recursive() { - Playground::setup("cp_test_10", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("hello_there")]); - sandbox.mkdir("hello_again"); - sandbox.within("foo").mkdir("bar"); - - nu!( - cwd: dirs.test().join("foo/bar"), - r#" - cp -r .../hello* . - "# - ); - - let expected = dirs.test().join("foo/bar"); - - assert!(files_exist_at(vec!["hello_there", "hello_again"], expected)); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/def.rs b/old_nushell/crates/nu-command/tests/commands/def.rs deleted file mode 100644 index e0f218b1e..000000000 --- a/old_nushell/crates/nu-command/tests/commands/def.rs +++ /dev/null @@ -1,19 +0,0 @@ -use nu_test_support::nu; -use nu_test_support::playground::Playground; -use std::fs; -#[test] -fn def_with_comment() { - Playground::setup("def_with_comment", |dirs, _| { - let data = r#" -#My echo -def e [arg] {echo $arg} - "#; - fs::write(dirs.root().join("def_test"), data).expect("Unable to write file"); - let actual = nu!( - cwd: dirs.root(), - "source def_test; help e | to json" - ); - - assert!(actual.out.contains("My echo\\n\\n")); - }); -} diff --git a/old_nushell/crates/nu-command/tests/commands/default.rs b/old_nushell/crates/nu-command/tests/commands/default.rs deleted file mode 100644 index 334b45ee6..000000000 --- a/old_nushell/crates/nu-command/tests/commands/default.rs +++ /dev/null @@ -1,35 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn adds_row_data_if_column_missing() { - Playground::setup("default_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.json", - r#" - { - "amigos": [ - {"name": "Yehuda"}, - {"name": "Jonathan", "rusty_luck": 0}, - {"name": "Andres", "rusty_luck": 0}, - {"name":"GorbyPuff"} - ] - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_amigos.json - | get amigos - | default rusty_luck 1 - | where rusty_luck == 1 - | length - "# - )); - - assert_eq!(actual.out, "2"); - }); -} diff --git a/old_nushell/crates/nu-command/tests/commands/drop.rs b/old_nushell/crates/nu-command/tests/commands/drop.rs deleted file mode 100644 index e723ba769..000000000 --- a/old_nushell/crates/nu-command/tests/commands/drop.rs +++ /dev/null @@ -1,90 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn columns() { - let actual = nu!( - cwd: ".", pipeline(r#" - echo [ - [arepas, color]; - - [3, white] - [8, yellow] - [4, white] - ] - | drop column - | get - | length - "#) - ); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn more_columns_than_table_has() { - let actual = nu!( - cwd: ".", pipeline(r#" - echo [ - [arepas, color]; - - [3, white] - [8, yellow] - [4, white] - ] - | drop column 3 - | get - | empty? - "#) - ); - - assert_eq!(actual.out, "true"); -} - -#[test] -fn rows() { - let actual = nu!( - cwd: ".", pipeline(r#" - echo [ - [arepas]; - - [3] - [8] - [4] - ] - | drop 2 - | get arepas - | math sum - "#) - ); - - assert_eq!(actual.out, "3"); -} - -#[test] -fn more_rows_than_table_has() { - let actual = nu!(cwd: ".", "date | drop 50 | length"); - - assert_eq!(actual.out, "0"); -} - -#[test] -fn nth_range_inclusive() { - let actual = nu!(cwd: ".", "echo 10..15 | drop nth (2..3) | to json"); - - assert_eq!(actual.out, "[10,11,14,15]"); -} - -#[test] -fn nth_range_exclusive() { - let actual = nu!(cwd: ".", "echo 10..15 | drop nth (1..<3) | to json"); - - assert_eq!(actual.out, "[10,13,14,15]"); -} - -#[test] -fn nth_missing_first_argument() { - let actual = nu!(cwd: ".", "echo 10..15 | drop nth \"\""); - - assert!(actual.err.contains("Expected int or range")); - assert!(actual.err.contains("found string")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/each.rs b/old_nushell/crates/nu-command/tests/commands/each.rs deleted file mode 100644 index c4d7edb02..000000000 --- a/old_nushell/crates/nu-command/tests/commands/each.rs +++ /dev/null @@ -1,73 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn each_works_separately() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [1 2 3] | each { echo $it 10 | math sum } | to json - "# - )); - - assert_eq!(actual.out, "[11,12,13]"); -} - -#[test] -fn each_group_works() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [1 2 3 4 5 6] | each group 3 { $it } | to json - "# - )); - - assert_eq!(actual.out, "[[1,2,3],[4,5,6]]"); -} - -#[test] -fn each_window() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [1 2 3 4] | each window 3 { $it } | to json - "# - )); - - assert_eq!(actual.out, "[[1,2,3],[2,3,4]]"); -} - -#[test] -fn each_window_stride() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [1 2 3 4 5 6] | each window 3 -s 2 { echo $it } | to json - "# - )); - - assert_eq!(actual.out, "[[1,2,3],[3,4,5]]"); -} - -#[test] -fn each_no_args_in_block() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [[foo bar]; [a b] [c d] [e f]] | each { to json } | nth 1 | str collect - "# - )); - - assert_eq!(actual.out, r#"{"foo":"c","bar":"d"}"#); -} - -#[test] -fn each_implicit_it_in_block() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [[foo bar]; [a b] [c d] [e f]] | each { nu --testbin cococo $it.foo } - "# - )); - - assert_eq!(actual.out, "ace"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/echo.rs b/old_nushell/crates/nu-command/tests/commands/echo.rs deleted file mode 100644 index e23609f9a..000000000 --- a/old_nushell/crates/nu-command/tests/commands/echo.rs +++ /dev/null @@ -1,61 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn echo_range_is_lazy() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo 1..10000000000 | first 3 | to json - "# - )); - - assert_eq!(actual.out, "[1,2,3]"); -} - -#[test] -fn echo_range_handles_inclusive() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo 1..3 | to json - "# - )); - - assert_eq!(actual.out, "[1,2,3]"); -} - -#[test] -fn echo_range_handles_exclusive() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo 1..<3 | to json - "# - )); - - assert_eq!(actual.out, "[1,2]"); -} - -#[test] -fn echo_range_handles_inclusive_down() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo 3..1 | to json - "# - )); - - assert_eq!(actual.out, "[3,2,1]"); -} - -#[test] -fn echo_range_handles_exclusive_down() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo 3..<1 | to json - "# - )); - - assert_eq!(actual.out, "[3,2]"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/empty.rs b/old_nushell/crates/nu-command/tests/commands/empty.rs deleted file mode 100644 index f5ec14cf8..000000000 --- a/old_nushell/crates/nu-command/tests/commands/empty.rs +++ /dev/null @@ -1,86 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn reports_emptiness() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[are_empty]; - [([[check]; [[]] ])] - [([[check]; [""] ])] - [([[check]; [(wrap)] ])] - ] - | get are_empty - | empty? check - | where check - | length - "# - )); - - assert_eq!(actual.out, "3"); -} - -#[test] -fn sets_block_run_value_for_an_empty_column() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [ - [ first_name, last_name, rusty_at, likes ]; - [ Andrés, Robalino, 10/11/2013, 1 ] - [ Jonathan, Turner, 10/12/2013, 1 ] - [ Jason, Gedge, 10/11/2013, 1 ] - [ Yehuda, Katz, 10/11/2013, '' ] - ] - | empty? likes -b { 1 } - | get likes - | math sum - "# - )); - - assert_eq!(actual.out, "4"); -} - -#[test] -fn sets_block_run_value_for_many_empty_columns() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [ - [ boost check ]; - [ 1, [] ] - [ 1, "" ] - [ 1, (wrap) ] - ] - | empty? boost check -b { 1 } - | get boost check - | math sum - "# - )); - - assert_eq!(actual.out, "6"); -} - -#[test] -fn passing_a_block_will_set_contents_on_empty_cells_and_leave_non_empty_ones_untouched() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [ - [ NAME, LVL, HP ]; - [ Andrés, 30, 3000 ] - [ Alistair, 29, 2900 ] - [ Arepas, "", "" ] - [ Jorge, 30, 3000 ] - ] - | empty? LVL -b { 9 } - | empty? HP -b { - $it.LVL * 1000 - } - | math sum - | get HP - "# - )); - - assert_eq!(actual.out, "17900"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/enter.rs b/old_nushell/crates/nu-command/tests/commands/enter.rs deleted file mode 100644 index d7377eade..000000000 --- a/old_nushell/crates/nu-command/tests/commands/enter.rs +++ /dev/null @@ -1,85 +0,0 @@ -use nu_test_support::fs::{files_exist_at, Stub::EmptyFile}; -use nu_test_support::nu; -use nu_test_support::playground::Playground; -use std::path::Path; - -#[test] -fn knows_the_filesystems_entered() { - Playground::setup("enter_test_1", |dirs, sandbox| { - sandbox - .within("red_pill") - .with_files(vec![ - EmptyFile("andres.nu"), - EmptyFile("jonathan.nu"), - EmptyFile("yehuda.nu"), - ]) - .within("blue_pill") - .with_files(vec![ - EmptyFile("bash.nxt"), - EmptyFile("korn.nxt"), - EmptyFile("powedsh.nxt"), - ]) - .mkdir("expected"); - - let red_pill_dir = dirs.test().join("red_pill"); - let blue_pill_dir = dirs.test().join("blue_pill"); - let expected = dirs.test().join("expected"); - let expected_recycled = expected.join("recycled"); - - nu!( - cwd: dirs.test(), - r#" - enter expected - mkdir recycled - enter ../red_pill - mv jonathan.nu ../expected - enter ../blue_pill - cp *.nxt ../expected/recycled - p - p - mv ../red_pill/yehuda.nu . - n - mv andres.nu ../expected/andres.nu - exit - cd .. - rm red_pill --recursive - exit - n - rm blue_pill --recursive - exit - "# - ); - - assert!(!red_pill_dir.exists()); - assert!(files_exist_at( - vec![ - Path::new("andres.nu"), - Path::new("jonathan.nu"), - Path::new("yehuda.nu"), - ], - expected - )); - - assert!(!blue_pill_dir.exists()); - assert!(files_exist_at( - vec![ - Path::new("bash.nxt"), - Path::new("korn.nxt"), - Path::new("powedsh.nxt"), - ], - expected_recycled - )); - }) -} - -#[test] -fn errors_if_file_not_found() { - Playground::setup("enter_test_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - "enter i_dont_exist.csv" - ); - - assert!(actual.err.contains("Cannot find file")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/every.rs b/old_nushell/crates/nu-command/tests/commands/every.rs deleted file mode 100644 index f48b2bf2a..000000000 --- a/old_nushell/crates/nu-command/tests/commands/every.rs +++ /dev/null @@ -1,209 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn gets_all_rows_by_every_zero() { - Playground::setup("every_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 0 - | to json - "# - )); - - assert_eq!( - actual.out, - r#"["amigos.txt","arepas.clu","los.txt","tres.txt"]"# - ); - }) -} - -#[test] -fn gets_no_rows_by_every_skip_zero() { - Playground::setup("every_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 0 --skip - | to json - "# - )); - - assert_eq!(actual.out, ""); - }) -} - -#[test] -fn gets_all_rows_by_every_one() { - Playground::setup("every_test_3", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 1 - | to json - "# - )); - - assert_eq!( - actual.out, - r#"["amigos.txt","arepas.clu","los.txt","tres.txt"]"# - ); - }) -} - -#[test] -fn gets_no_rows_by_every_skip_one() { - Playground::setup("every_test_4", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 1 --skip - | to json - "# - )); - - assert_eq!(actual.out, ""); - }) -} - -#[test] -fn gets_first_row_by_every_too_much() { - Playground::setup("every_test_5", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 999 - "# - )); - - let expected = nu!( - cwd: dirs.test(), pipeline( - r#" - echo [ amigos.txt ] - "# - )); - - assert_eq!(actual.out, expected.out); - }) -} - -#[test] -fn gets_all_rows_except_first_by_every_skip_too_much() { - Playground::setup("every_test_6", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 999 --skip - | to json - "# - )); - - assert_eq!(actual.out, r#"["arepas.clu","los.txt","tres.txt"]"#); - }) -} - -#[test] -fn gets_every_third_row() { - Playground::setup("every_test_7", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("quatro.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 3 - | to json - "# - )); - - assert_eq!(actual.out, r#"["amigos.txt","quatro.txt"]"#); - }) -} - -#[test] -fn skips_every_third_row() { - Playground::setup("every_test_8", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("quatro.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | every 3 --skip - | to json - "# - )); - - assert_eq!(actual.out, r#"["arepas.clu","los.txt","tres.txt"]"#); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/find.rs b/old_nushell/crates/nu-command/tests/commands/find.rs deleted file mode 100644 index 0c8b04fe4..000000000 --- a/old_nushell/crates/nu-command/tests/commands/find.rs +++ /dev/null @@ -1,111 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn find_with_list_search_with_string() { - let actual = nu!( - cwd: ".", pipeline( - r#" - [moe larry curly] | find moe - "# - )); - - assert_eq!(actual.out, "moe"); -} - -#[test] -fn find_with_list_search_with_char() { - let actual = nu!( - cwd: ".", pipeline( - r#" - [moe larry curly] | find l | to json - "# - )); - - assert_eq!(actual.out, r#"["larry","curly"]"#); -} - -#[test] -fn find_with_list_search_with_number() { - let actual = nu!( - cwd: ".", pipeline( - r#" - [1 2 3 4 5] | find 3 - "# - )); - - assert_eq!(actual.out, "3"); -} - -#[test] -fn find_with_string_search_with_string() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo Cargo.toml | find toml - "# - )); - - assert_eq!(actual.out, "Cargo.toml"); -} - -#[test] -fn find_with_string_search_with_string_not_found() { - let actual = nu!( - cwd: ".", pipeline( - r#" - [moe larry curly] | find shemp - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn find_with_filepath_search_with_string() { - Playground::setup("filepath_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | find arep - | to json - "# - )); - - assert_eq!(actual.out, r#""arepas.clu""#); - }) -} - -#[test] -fn find_with_filepath_search_with_multiple_patterns() { - Playground::setup("filepath_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | find arep ami - | to json - "# - )); - - assert_eq!(actual.out, r#"["amigos.txt","arepas.clu"]"#); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/first.rs b/old_nushell/crates/nu-command/tests/commands/first.rs deleted file mode 100644 index 686fc6565..000000000 --- a/old_nushell/crates/nu-command/tests/commands/first.rs +++ /dev/null @@ -1,67 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn gets_first_rows_by_amount() { - Playground::setup("first_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | first 3 - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn gets_all_rows_if_amount_higher_than_all_rows() { - Playground::setup("first_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | first 99 - | length - "# - )); - - assert_eq!(actual.out, "4"); - }) -} - -#[test] -fn gets_first_row_when_no_amount_given() { - Playground::setup("first_test_3", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | first - | length - "# - )); - - assert_eq!(actual.out, "1"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/flatten.rs b/old_nushell/crates/nu-command/tests/commands/flatten.rs deleted file mode 100644 index 2e36a4e70..000000000 --- a/old_nushell/crates/nu-command/tests/commands/flatten.rs +++ /dev/null @@ -1,184 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn flatten_nested_tables_with_columns() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[origin, people]; [Ecuador, ('Andres' | wrap name)]] - [[origin, people]; [Nu, ('nuno' | wrap name)]] - | flatten - | get name - | str collect ',' - "# - )); - - assert_eq!(actual.out, "Andres,nuno"); -} - -#[test] -fn flatten_nested_tables_that_have_many_columns() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[origin, people]; [Ecuador, (echo [[name, meal]; ['Andres', 'arepa']])]] - [[origin, people]; [USA, (echo [[name, meal]; ['Katz', 'nurepa']])]] - | flatten - | get meal - | str collect ',' - "# - )); - - assert_eq!(actual.out, "arepa,nurepa"); -} - -#[test] -fn flatten_nested_tables() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[Andrés, Nicolás, Robalino]] | flatten | nth 1 - "# - )); - - assert_eq!(actual.out, "Nicolás"); -} - -#[test] -fn flatten_row_column_explicitly() { - Playground::setup("flatten_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.json", - r#" - [ - { - "people": { - "name": "Andres", - "meal": "arepa" - } - }, - { - "people": { - "name": "Katz", - "meal": "nurepa" - } - } - ] - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open katz.json | flatten people | where name == Andres | length" - ); - - assert_eq!(actual.out, "1"); - }) -} - -#[test] -fn flatten_row_columns_having_same_column_names_flats_separately() { - Playground::setup("flatten_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.json", - r#" - [ - { - "people": { - "name": "Andres", - "meal": "arepa" - }, - "city": [{"name": "Guayaquil"}, {"name": "Samborondón"}] - }, - { - "people": { - "name": "Katz", - "meal": "nurepa" - }, - "city": [{"name": "Oregon"}, {"name": "Brooklin"}] - } - ] - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open katz.json | flatten | flatten people city | get city_name | length" - ); - - assert_eq!(actual.out, "4"); - }) -} - -#[test] -fn flatten_table_columns_explicitly() { - Playground::setup("flatten_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.json", - r#" - [ - { - "people": { - "name": "Andres", - "meal": "arepa" - }, - "city": ["Guayaquil", "Samborondón"] - }, - { - "people": { - "name": "Katz", - "meal": "nurepa" - }, - "city": ["Oregon", "Brooklin"] - } - ] - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open katz.json | flatten city | where people.name == Katz | length" - ); - - assert_eq!(actual.out, "2"); - }) -} - -#[test] -fn flatten_more_than_one_column_that_are_subtables_not_supported() { - Playground::setup("flatten_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.json", - r#" - [ - { - "people": { - "name": "Andres", - "meal": "arepa" - } - "tags": ["carbohydrate", "corn", "maiz"], - "city": ["Guayaquil", "Samborondón"] - }, - { - "people": { - "name": "Katz", - "meal": "nurepa" - }, - "tags": ["carbohydrate", "shell food", "amigos flavor"], - "city": ["Oregon", "Brooklin"] - } - ] - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open katz.json | flatten tags city" - ); - - assert!(actual.err.contains("tried flattening")); - assert!(actual.err.contains("but is flattened already")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/format.rs b/old_nushell/crates/nu-command/tests/commands/format.rs deleted file mode 100644 index d3b585ecf..000000000 --- a/old_nushell/crates/nu-command/tests/commands/format.rs +++ /dev/null @@ -1,93 +0,0 @@ -use nu_test_support::fs::Stub::{EmptyFile, FileWithContentToBeTrimmed}; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn creates_the_resulting_string_from_the_given_fields() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml - | get package - | format "{name} has license {license}" - "# - )); - - assert_eq!(actual.out, "nu has license ISC"); -} - -#[test] -fn given_fields_can_be_column_paths() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml - | format "{package.name} is {package.description}" - "# - )); - - assert_eq!(actual.out, "nu is a new type of shell"); -} - -#[test] -fn can_use_variables() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml - | format "{$it.package.name} is {$it.package.description}" - "# - )); - - assert_eq!(actual.out, "nu is a new type of shell"); -} - -#[test] -fn format_filesize_works() { - Playground::setup("format_filesize_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | format filesize size KB - | get size - | first - "# - )); - - assert_eq!(actual.out, "0.0 KB"); - }) -} - -#[test] -fn format_filesize_works_with_nonempty_files() { - Playground::setup( - "format_filesize_works_with_nonempty_files", - |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.toml", - r#" - [dependency] - name = "nu" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "ls sample.toml | format filesize size B | get size | first" - ); - - #[cfg(not(windows))] - assert_eq!(actual.out, "25"); - - #[cfg(windows)] - assert_eq!(actual.out, "27"); - }, - ) -} diff --git a/old_nushell/crates/nu-command/tests/commands/get.rs b/old_nushell/crates/nu-command/tests/commands/get.rs deleted file mode 100644 index 667acf94d..000000000 --- a/old_nushell/crates/nu-command/tests/commands/get.rs +++ /dev/null @@ -1,222 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContent; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn fetches_a_row() { - Playground::setup("get_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - nu_party_venue = "zion" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get nu_party_venue - "# - )); - - assert_eq!(actual.out, "zion"); - }) -} - -#[test] -fn fetches_by_index() { - Playground::setup("get_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - name = "nu" - version = "0.4.1" - authors = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] - description = "When arepas shells are tasty and fun." - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get package.authors.2 - "# - )); - - assert_eq!(actual.out, "Andrés N. Robalino "); - }) -} -#[test] -fn fetches_by_column_path() { - Playground::setup("get_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - name = "nu" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get package.name - "# - )); - - assert_eq!(actual.out, "nu"); - }) -} - -#[test] -fn column_paths_are_either_double_quoted_or_regular_unquoted_words_separated_by_dot() { - Playground::setup("get_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - 9999 = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] - description = "When arepas shells are tasty and fun." - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get package."9999" - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn fetches_more_than_one_column_path() { - Playground::setup("get_test_5", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [[fortune_tellers]] - name = "Andrés N. Robalino" - arepas = 1 - - [[fortune_tellers]] - name = "Jonathan Turner" - arepas = 1 - - [[fortune_tellers]] - name = "Yehuda Katz" - arepas = 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get fortune_tellers.2.name fortune_tellers.0.name fortune_tellers.1.name - | nth 2 - "# - )); - - assert_eq!(actual.out, "Jonathan Turner"); - }) -} - -#[test] -fn errors_fetching_by_column_not_present() { - Playground::setup("get_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [taconushell] - sentence_words = ["Yo", "quiero", "taconushell"] - [pizzanushell] - sentence-words = ["I", "want", "pizza"] - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get taco - "# - )); - - assert!(actual.err.contains("Unknown column"),); - assert!(actual.err.contains("There isn't a column named 'taco'"),); - assert!(actual.err.contains("Perhaps you meant 'taconushell'?"),); - assert!(actual - .err - .contains("Columns available: pizzanushell, taconushell"),); - }) -} - -#[test] -fn errors_fetching_by_column_using_a_number() { - Playground::setup("get_test_7", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [spanish_lesson] - 0 = "can only be fetched with 0 double quoted." - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get spanish_lesson.0 - "# - )); - - assert!(actual.err.contains("No rows available"),); - assert!(actual.err.contains("A row at '0' can't be indexed."),); - assert!(actual - .err - .contains("Appears to contain columns. Columns available: 0"),) - }) -} -#[test] -fn errors_fetching_by_index_out_of_bounds() { - Playground::setup("get_test_8", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [spanish_lesson] - sentence_words = ["Yo", "quiero", "taconushell"] - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get spanish_lesson.sentence_words.3 - "# - )); - - assert!(actual.err.contains("Row not found"),); - assert!(actual.err.contains("There isn't a row indexed at 3"),); - assert!(actual.err.contains("The table only has 3 rows (0 to 2)"),) - }) -} - -#[test] -fn quoted_column_access() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r#"echo '[{"foo bar": {"baz": 4}}]' | from json | get "foo bar".baz "# - ); - - assert_eq!(actual.out, "4"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/group_by.rs b/old_nushell/crates/nu-command/tests/commands/group_by.rs deleted file mode 100644 index 690a5ddd2..000000000 --- a/old_nushell/crates/nu-command/tests/commands/group_by.rs +++ /dev/null @@ -1,97 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn groups() { - Playground::setup("group_by_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.csv - | group-by rusty_at - | get "10/11/2013" - | length - "# - )); - - assert_eq!(actual.out, "2"); - }) -} - -#[test] -fn errors_if_given_unknown_column_name() { - Playground::setup("group_by_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.json", - r#" - { - "nu": { - "committers": [ - {"name": "Andrés N. Robalino"}, - {"name": "Jonathan Turner"}, - {"name": "Yehuda Katz"} - ], - "releases": [ - {"version": "0.2"} - {"version": "0.8"}, - {"version": "0.9999999"} - ], - "0xATYKARNU": [ - ["Th", "e", " "], - ["BIG", " ", "UnO"], - ["punto", "cero"] - ] - } - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.json - | group-by { get nu.releases.version } - "# - )); - - assert!(actual - .err - .contains("requires a table with one value for grouping")); - }) -} - -#[test] -fn errors_if_block_given_evaluates_more_than_one_row() { - Playground::setup("group_by_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.csv - | group-by ttype - "# - )); - - assert!(actual.err.contains("Unknown column")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/hash_/mod.rs b/old_nushell/crates/nu-command/tests/commands/hash_/mod.rs deleted file mode 100644 index 61ad8f155..000000000 --- a/old_nushell/crates/nu-command/tests/commands/hash_/mod.rs +++ /dev/null @@ -1,114 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn base64_defaults_to_encoding_with_standard_character_type() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 'username:password' | hash base64 - "# - ) - ); - - assert_eq!(actual.out, "dXNlcm5hbWU6cGFzc3dvcmQ="); -} - -#[test] -fn base64_encode_characterset_binhex() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 'username:password' | hash base64 --character_set binhex --encode - "# - ) - ); - - assert_eq!(actual.out, "F@0NEPjJD97kE\'&bEhFZEP3"); -} - -#[test] -fn error_when_invalid_character_set_given() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 'username:password' | hash base64 --character_set 'this is invalid' --encode - "# - ) - ); - - assert!(actual - .err - .contains("this is invalid is not a valid character-set")); -} - -#[test] -fn base64_decode_characterset_binhex() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "F@0NEPjJD97kE'&bEhFZEP3" | hash base64 --character_set binhex --decode - "# - ) - ); - - assert_eq!(actual.out, "username:password"); -} - -#[test] -fn error_invalid_decode_value() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "this should not be a valid encoded value" | hash base64 --character_set url-safe --decode - "# - ) - ); - - assert!(actual - .err - .contains("invalid base64 input for character set url-safe")); -} - -#[test] -fn error_use_both_flags() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 'username:password' | hash base64 --encode --decode - "# - ) - ); - - assert!(actual - .err - .contains("only one of --decode and --encode flags can be used")); -} - -#[test] -fn md5_works_with_file() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db | hash md5 - "# - ) - ); - - assert_eq!(actual.out, "4de97601d232c427977ef11db396c951"); -} - -#[test] -fn sha256_works_with_file() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db | hash sha256 - "# - ) - ); - - assert_eq!( - actual.out, - "2f5050e7eea415c1f3d80b5d93355efd15043ec9157a2bb167a9e73f2ae651f2" - ); -} diff --git a/old_nushell/crates/nu-command/tests/commands/headers.rs b/old_nushell/crates/nu-command/tests/commands/headers.rs deleted file mode 100644 index 1eadf754a..000000000 --- a/old_nushell/crates/nu-command/tests/commands/headers.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn headers_uses_first_row_as_header() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample_headers.xlsx - | get Sheet1 - | headers - | get header0 - | from json"# - )); - - assert_eq!(actual.out, "r1c0r2c0") -} - -#[test] -fn headers_adds_missing_column_name() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample_headers.xlsx - | get Sheet1 - | headers - | get Column1 - | from json"# - )); - - assert_eq!(actual.out, "r1c1r2c1") -} diff --git a/old_nushell/crates/nu-command/tests/commands/help.rs b/old_nushell/crates/nu-command/tests/commands/help.rs deleted file mode 100644 index bab3102f0..000000000 --- a/old_nushell/crates/nu-command/tests/commands/help.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn help_commands_length() { - let actual = nu!( - cwd: ".", pipeline( - r#" - help commands | length - "# - )); - - let output = actual.out; - let output_int: i32 = output.parse().unwrap(); - let is_positive = output_int.is_positive(); - assert!(is_positive); -} - -#[test] -fn help_generate_docs_length() { - let actual = nu!( - cwd: ".", pipeline( - r#" - help generate_docs | flatten | length - "# - )); - - let output = actual.out; - let output_int: i32 = output.parse().unwrap(); - let is_positive = output_int.is_positive(); - assert!(is_positive); -} diff --git a/old_nushell/crates/nu-command/tests/commands/histogram.rs b/old_nushell/crates/nu-command/tests/commands/histogram.rs deleted file mode 100644 index 1ff4fef31..000000000 --- a/old_nushell/crates/nu-command/tests/commands/histogram.rs +++ /dev/null @@ -1,109 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn summarizes_by_column_given() { - Playground::setup("histogram_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at - Andrés,Robalino,Ecuador - Jonathan,Turner,Estados Unidos - Yehuda,Katz,Estados Unidos - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.csv - | histogram rusty_at countries - | where rusty_at == "Ecuador" - | get countries - "# - )); - - assert_eq!( - actual.out, - "**************************************************" - ); - // 50% - }) -} - -#[test] -fn summarizes_by_values() { - Playground::setup("histogram_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at - Andrés,Robalino,Ecuador - Jonathan,Turner,Estados Unidos - Yehuda,Katz,Estados Unidos - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.csv - | get rusty_at - | histogram - | where value == "Estados Unidos" - | get count - "# - )); - - assert_eq!(actual.out, "2"); - }) -} - -#[test] -fn help() { - Playground::setup("histogram_test_3", |dirs, _sandbox| { - let help_command = nu!( - cwd: dirs.test(), pipeline( - r#" - help histogram - "# - )); - - let help_short = nu!( - cwd: dirs.test(), pipeline( - r#" - histogram -h - "# - )); - - let help_long = nu!( - cwd: dirs.test(), pipeline( - r#" - histogram --help - "# - )); - - assert_eq!(help_short.out, help_command.out); - assert_eq!(help_long.out, help_command.out); - }) -} - -#[test] -fn count() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[bit]; [1] [0] [0] [0] [0] [0] [0] [1]] - | histogram bit - | sort-by count - | reject frequency - | to json - "# - )); - - let bit_json = r#"[{"bit":"1","count":2,"percentage":"33.33%"},{"bit":"0","count":6,"percentage":"100.00%"}]"#; - - assert_eq!(actual.out, bit_json); -} diff --git a/old_nushell/crates/nu-command/tests/commands/insert.rs b/old_nushell/crates/nu-command/tests/commands/insert.rs deleted file mode 100644 index 4d162de95..000000000 --- a/old_nushell/crates/nu-command/tests/commands/insert.rs +++ /dev/null @@ -1,45 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn sets_the_column_from_a_block_run_output() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml - | insert dev-dependencies.newdep "1" - | get dev-dependencies.newdep - "# - )); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn sets_the_column_from_a_block_full_stream_output() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - wrap _ - | insert content { open --raw cargo_sample.toml | lines | first 5 } - | get content.1 - | str contains "nu" - "# - )); - - assert_eq!(actual.out, "true"); -} - -#[test] -fn sets_the_column_from_a_subexpression() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - wrap content - | insert content (open --raw cargo_sample.toml | lines | first 5) - | get content.1 - | str contains "nu" - "# - )); - - assert_eq!(actual.out, "true"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/into_filesize.rs b/old_nushell/crates/nu-command/tests/commands/into_filesize.rs deleted file mode 100644 index b6919e4bd..000000000 --- a/old_nushell/crates/nu-command/tests/commands/into_filesize.rs +++ /dev/null @@ -1,76 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn into_filesize_int() { - let actual = nu!( - cwd: ".", pipeline( - r#" - 1 | into filesize - "# - )); - - assert!(actual.out.contains("1 B")); -} - -#[test] -fn into_filesize_decimal() { - let actual = nu!( - cwd: ".", pipeline( - r#" - 1.2 | into filesize - "# - )); - - assert!(actual.out.contains("1 B")); -} - -#[test] -fn into_filesize_str() { - let actual = nu!( - cwd: ".", pipeline( - r#" - '2000' | into filesize - "# - )); - - assert!(actual.out.contains("2.0 KB")); -} - -#[test] -fn into_filesize_str_newline() { - let actual = nu!( - cwd: ".", pipeline( - r#" - '2000 -' | into filesize - "# - )); - - assert!(actual.out.contains("2.0 KB")); -} - -#[test] -fn into_filesize_str_many_newlines() { - let actual = nu!( - cwd: ".", pipeline( - r#" - '2000 - -' | into filesize - "# - )); - - assert!(actual.out.contains("2.0 KB")); -} - -#[test] -fn into_filesize_filesize() { - let actual = nu!( - cwd: ".", pipeline( - r#" - 3kb | into filesize - "# - )); - - assert!(actual.out.contains("3.0 KB")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/into_int.rs b/old_nushell/crates/nu-command/tests/commands/into_int.rs deleted file mode 100644 index dbb20a1c7..000000000 --- a/old_nushell/crates/nu-command/tests/commands/into_int.rs +++ /dev/null @@ -1,37 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn into_int_filesize() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 1kb | into int | each { $it / 1000 } - "# - )); - - assert!(actual.out.contains('1')); -} - -#[test] -fn into_int_filesize2() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 1kib | into int | each { $it / 1024 } - "# - )); - - assert!(actual.out.contains('1')); -} - -#[test] -fn into_int_int() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 1024 | into int | each { $it / 1024 } - "# - )); - - assert!(actual.out.contains('1')); -} diff --git a/old_nushell/crates/nu-command/tests/commands/keep/mod.rs b/old_nushell/crates/nu-command/tests/commands/keep/mod.rs deleted file mode 100644 index a267c2352..000000000 --- a/old_nushell/crates/nu-command/tests/commands/keep/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod rows; -mod until; -mod while_; diff --git a/old_nushell/crates/nu-command/tests/commands/keep/rows.rs b/old_nushell/crates/nu-command/tests/commands/keep/rows.rs deleted file mode 100644 index 84df11377..000000000 --- a/old_nushell/crates/nu-command/tests/commands/keep/rows.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn rows() { - Playground::setup("keep_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "caballeros.csv", - r#" - name,lucky_code - Andrés,1 - Jonathan,1 - Jason,2 - Yehuda,1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open caballeros.csv - | keep 3 - | get lucky_code - | math sum - "# - )); - - assert_eq!(actual.out, "4"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/keep/until.rs b/old_nushell/crates/nu-command/tests/commands/keep/until.rs deleted file mode 100644 index 36e2783ee..000000000 --- a/old_nushell/crates/nu-command/tests/commands/keep/until.rs +++ /dev/null @@ -1,51 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn condition_is_met() { - Playground::setup("keep_until_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "caballeros.txt", - r#" - CHICKEN SUMMARY report date: April 29th, 2020 - -------------------------------------------------------------------- - Chicken Collection,29/04/2020,30/04/2020,31/04/2020, - Yellow Chickens,,, - Andrés,1,1,1 - Jonathan,1,1,1 - Jason,1,1,1 - Yehuda,1,1,1 - Blue Chickens,,, - Andrés,1,1,2 - Jonathan,1,1,2 - Jason,1,1,2 - Yehuda,1,1,2 - Red Chickens,,, - Andrés,1,1,3 - Jonathan,1,1,3 - Jason,1,1,3 - Yehuda,1,1,3 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open --raw caballeros.txt - | lines - | skip 2 - | split column ',' - | headers - | skip while "Chicken Collection" != "Blue Chickens" - | keep until "Chicken Collection" == "Red Chickens" - | skip 1 - | str to-int "31/04/2020" - | get "31/04/2020" - | math sum - "# - )); - - assert_eq!(actual.out, "8"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/keep/while_.rs b/old_nushell/crates/nu-command/tests/commands/keep/while_.rs deleted file mode 100644 index 713fc41c8..000000000 --- a/old_nushell/crates/nu-command/tests/commands/keep/while_.rs +++ /dev/null @@ -1,50 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn condition_is_met() { - Playground::setup("keep_while_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "caballeros.txt", - r#" - CHICKEN SUMMARY report date: April 29th, 2020 - -------------------------------------------------------------------- - Chicken Collection,29/04/2020,30/04/2020,31/04/2020, - Yellow Chickens,,, - Andrés,1,1,1 - Jonathan,1,1,1 - Jason,1,1,1 - Yehuda,1,1,1 - Blue Chickens,,, - Andrés,1,1,2 - Jonathan,1,1,2 - Jason,1,1,2 - Yehuda,1,1,2 - Red Chickens,,, - Andrés,1,1,3 - Jonathan,1,1,3 - Jason,1,1,3 - Yehuda,1,1,3 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open --raw caballeros.txt - | lines - | skip 2 - | split column ',' - | headers - | skip 1 - | keep while "Chicken Collection" != "Blue Chickens" - | str to-int "31/04/2020" - | get "31/04/2020" - | math sum - "# - )); - - assert_eq!(actual.out, "4"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/last.rs b/old_nushell/crates/nu-command/tests/commands/last.rs deleted file mode 100644 index b5acbb99e..000000000 --- a/old_nushell/crates/nu-command/tests/commands/last.rs +++ /dev/null @@ -1,66 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn gets_the_last_row() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "ls | sort-by name | last 1 | get name | str trim" - ); - - assert_eq!(actual.out, "utf16.ini"); -} - -#[test] -fn gets_last_rows_by_amount() { - Playground::setup("last_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | last 3 - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn gets_last_row_when_no_amount_given() { - Playground::setup("last_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | last - | length - "# - )); - - assert_eq!(actual.out, "1"); - }) -} - -#[test] -fn requests_more_rows_than_table_has() { - let actual = nu!( - cwd: ".", pipeline( - r#" - date | last 50 | length - "# - )); - - assert_eq!(actual.out, "1"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/length.rs b/old_nushell/crates/nu-command/tests/commands/length.rs deleted file mode 100644 index 9c5f51e9d..000000000 --- a/old_nushell/crates/nu-command/tests/commands/length.rs +++ /dev/null @@ -1,25 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn length_columns_in_cal_table() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cal | length -c - "# - )); - - assert_eq!(actual.out, "7"); -} - -#[test] -fn length_columns_no_rows() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [] | length -c - "# - )); - - assert_eq!(actual.out, "0"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/lines.rs b/old_nushell/crates/nu-command/tests/commands/lines.rs deleted file mode 100644 index e03b5ad4b..000000000 --- a/old_nushell/crates/nu-command/tests/commands/lines.rs +++ /dev/null @@ -1,50 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn lines() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml -r - | lines - | skip while $it != "[dependencies]" - | skip 1 - | first 1 - | split column "=" - | get Column1 - | str trim - "# - )); - - assert_eq!(actual.out, "rustyline"); -} - -#[test] -fn lines_proper_buffering() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open lines_test.txt -r - | lines - | str length - | to json - "# - )); - - assert_eq!(actual.out, "[8193,3]"); -} - -#[test] -fn lines_multi_value_split() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample-simple.json - | get first second - | lines - | length - "# - )); - - assert_eq!(actual.out, "5"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/ls.rs b/old_nushell/crates/nu-command/tests/commands/ls.rs deleted file mode 100644 index a6f52a037..000000000 --- a/old_nushell/crates/nu-command/tests/commands/ls.rs +++ /dev/null @@ -1,346 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn lists_regular_files() { - Playground::setup("ls_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn lists_regular_files_using_asterisk_wildcard() { - Playground::setup("ls_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls *.txt - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn lists_regular_files_using_question_mark_wildcard() { - Playground::setup("ls_test_3", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.10.txt"), - EmptyFile("jonathan.10.txt"), - EmptyFile("andres.10.txt"), - EmptyFile("chicken_not_to_be_picked_up.100.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls *.??.txt - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn lists_all_files_in_directories_from_stream() { - Playground::setup("ls_test_4", |dirs, sandbox| { - sandbox - .with_files(vec![EmptyFile("root1.txt"), EmptyFile("root2.txt")]) - .within("dir_a") - .with_files(vec![ - EmptyFile("yehuda.10.txt"), - EmptyFile("jonathan.10.txt"), - ]) - .within("dir_b") - .with_files(vec![ - EmptyFile("andres.10.txt"), - EmptyFile("chicken_not_to_be_picked_up.100.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo dir_a dir_b - | each { ls $it } - | length - "# - )); - - assert_eq!(actual.out, "4"); - }) -} - -#[test] -fn does_not_fail_if_glob_matches_empty_directory() { - Playground::setup("ls_test_5", |dirs, sandbox| { - sandbox.within("dir_a"); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls dir_a - | length - "# - )); - - assert_eq!(actual.out, "0"); - }) -} - -#[test] -fn fails_when_glob_doesnt_match() { - Playground::setup("ls_test_5", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("root1.txt"), EmptyFile("root2.txt")]); - - let actual = nu!( - cwd: dirs.test(), - "ls root3*" - ); - - assert!(actual.err.contains("no matches found")); - }) -} - -#[test] -fn list_files_from_two_parents_up_using_multiple_dots() { - Playground::setup("ls_test_6", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yahuda.yaml"), - EmptyFile("jonathan.json"), - EmptyFile("andres.xml"), - EmptyFile("kevin.txt"), - ]); - - sandbox.within("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test().join("foo/bar"), - r#" - ls ... | length - "# - ); - - assert_eq!(actual.out, "5"); - }) -} - -#[test] -fn lists_hidden_file_when_explicitly_specified() { - Playground::setup("ls_test_7", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - EmptyFile(".testdotfile"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls .testdotfile - | length - "# - )); - - assert_eq!(actual.out, "1"); - }) -} - -#[test] -fn lists_all_hidden_files_when_glob_contains_dot() { - Playground::setup("ls_test_8", |dirs, sandbox| { - sandbox - .with_files(vec![ - EmptyFile("root1.txt"), - EmptyFile("root2.txt"), - EmptyFile(".dotfile1"), - ]) - .within("dir_a") - .with_files(vec![ - EmptyFile("yehuda.10.txt"), - EmptyFile("jonathan.10.txt"), - EmptyFile(".dotfile2"), - ]) - .within("dir_b") - .with_files(vec![ - EmptyFile("andres.10.txt"), - EmptyFile("chicken_not_to_be_picked_up.100.txt"), - EmptyFile(".dotfile3"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls **/.* - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -// TODO Remove this cfg value when we have an OS-agnostic way -// of creating hidden files using the playground. -#[cfg(unix)] -fn lists_all_hidden_files_when_glob_does_not_contain_dot() { - Playground::setup("ls_test_8", |dirs, sandbox| { - sandbox - .with_files(vec![ - EmptyFile("root1.txt"), - EmptyFile("root2.txt"), - EmptyFile(".dotfile1"), - ]) - .within("dir_a") - .with_files(vec![ - EmptyFile("yehuda.10.txt"), - EmptyFile("jonathan.10.txt"), - EmptyFile(".dotfile2"), - ]) - .within(".dir_b") - .with_files(vec![ - EmptyFile("andres.10.txt"), - EmptyFile("chicken_not_to_be_picked_up.100.txt"), - EmptyFile(".dotfile3"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls **/* - | length - "# - )); - - assert_eq!(actual.out, "5"); - }) -} - -#[test] -#[cfg(unix)] -fn fails_with_ls_to_dir_without_permission() { - Playground::setup("ls_test_1", |dirs, sandbox| { - sandbox.within("dir_a").with_files(vec![ - EmptyFile("yehuda.11.txt"), - EmptyFile("jonathan.10.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - chmod 000 dir_a; ls dir_a - "# - )); - assert!(actual - .err - .contains("The permissions of 0 do not allow access for this user")); - }) -} - -#[test] -fn lists_files_including_starting_with_dot() { - Playground::setup("ls_test_9", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - EmptyFile(".hidden1.txt"), - EmptyFile(".hidden2.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls -a - | length - "# - )); - - assert_eq!(actual.out, "5"); - }) -} - -#[test] -fn list_all_columns() { - Playground::setup("ls_test_all_columns", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("Leonardo.yaml"), - EmptyFile("Raphael.json"), - EmptyFile("Donatello.xml"), - EmptyFile("Michelangelo.txt"), - ]); - // Normal Operation - let actual = nu!( - cwd: dirs.test(), - "ls | get | to md" - ); - let expected = ["name", "type", "size", "modified"].join(""); - assert_eq!(actual.out, expected, "column names are incorrect for ls"); - // Long - let actual = nu!( - cwd: dirs.test(), - "ls -l | get | to md" - ); - let expected = { - #[cfg(unix)] - { - [ - "name", - "type", - "target", - "num_links", - "inode", - "readonly", - "mode", - "uid", - "group", - "size", - "created", - "accessed", - "modified", - ] - .join("") - } - - #[cfg(windows)] - { - [ - "name", "type", "target", "readonly", "size", "created", "accessed", "modified", - ] - .join("") - } - }; - assert_eq!( - actual.out, expected, - "column names are incorrect for ls long" - ); - }); -} diff --git a/old_nushell/crates/nu-command/tests/commands/math/avg.rs b/old_nushell/crates/nu-command/tests/commands/math/avg.rs deleted file mode 100644 index e749192c4..000000000 --- a/old_nushell/crates/nu-command/tests/commands/math/avg.rs +++ /dev/null @@ -1,25 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn can_average_numbers() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sgml_description.json - | get glossary.GlossDiv.GlossList.GlossEntry.Sections - | math avg - "# - )); - - assert_eq!(actual.out, "101.5") -} - -#[test] -fn can_average_bytes() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "ls | sort-by name | skip 1 | first 2 | get size | math avg | format \"{$it}\" " - ); - - assert_eq!(actual.out, "1.6 KB"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/math/eval.rs b/old_nushell/crates/nu-command/tests/commands/math/eval.rs deleted file mode 100644 index 736d1f641..000000000 --- a/old_nushell/crates/nu-command/tests/commands/math/eval.rs +++ /dev/null @@ -1,85 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn evaluates_two_plus_two() { - let actual = nu!( - cwd: ".", pipeline( - r#" - math eval "2 + 2" - "# - )); - - assert!(actual.out.contains("4.0")); -} - -#[test] -fn evaluates_two_to_the_power_four() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "2 ^ 4" | math eval - "# - )); - - assert!(actual.out.contains("16.0")); -} - -#[test] -fn evaluates_three_multiplied_by_five() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "3 * 5" | math eval - "# - )); - - assert!(actual.out.contains("15.0")); -} - -#[test] -fn evaluates_twenty_four_divided_by_two() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "24 / 2" | math eval - "# - )); - - assert!(actual.out.contains("12.0")); -} - -#[test] -fn evaluates_twenty_eight_minus_seven() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "28 - 7" | math eval - "# - )); - - assert!(actual.out.contains("21")); -} - -#[test] -fn evaluates_pi() { - let actual = nu!( - cwd: ".", pipeline( - r#" - math eval pi - "# - )); - - assert!(actual.out.contains("3.14")); -} - -#[test] -fn evaluates_tau() { - let actual = nu!( - cwd: ".", pipeline( - r#" - math eval tau - "# - )); - - assert!(actual.out.contains("6.28")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/math/median.rs b/old_nushell/crates/nu-command/tests/commands/math/median.rs deleted file mode 100644 index 7509fe8f4..000000000 --- a/old_nushell/crates/nu-command/tests/commands/math/median.rs +++ /dev/null @@ -1,40 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn median_numbers_with_even_rows() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [10 6 19 21 4] - | math median - "# - )); - - assert_eq!(actual.out, "10") -} - -#[test] -fn median_numbers_with_odd_rows() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [3 8 9 12 12 15] - | math median - "# - )); - - assert_eq!(actual.out, "10.5") -} - -#[test] -fn median_mixed_numbers() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [-11.5 -13.5 10] - | math median - "# - )); - - assert_eq!(actual.out, "-11.5") -} diff --git a/old_nushell/crates/nu-command/tests/commands/math/mod.rs b/old_nushell/crates/nu-command/tests/commands/math/mod.rs deleted file mode 100644 index 21c4cab65..000000000 --- a/old_nushell/crates/nu-command/tests/commands/math/mod.rs +++ /dev/null @@ -1,296 +0,0 @@ -mod avg; -mod eval; -mod median; -mod round; -mod sqrt; -mod sum; - -use nu_test_support::{nu, pipeline}; - -#[test] -fn one_arg() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 - "# - )); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn add() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 + 1 - "# - )); - - assert_eq!(actual.out, "2"); -} - -#[test] -fn add_compound() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 + 2 + 2 - "# - )); - - assert_eq!(actual.out, "5"); -} - -#[test] -fn precedence_of_operators() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 + 2 * 2 - "# - )); - - assert_eq!(actual.out, "5"); -} - -#[test] -fn precedence_of_operators2() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 + 2 * 2 + 1 - "# - )); - - assert_eq!(actual.out, "6"); -} - -#[test] -fn division_of_ints() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 4 / 2 - "# - )); - - assert_eq!(actual.out, "2"); -} - -#[test] -fn division_of_ints2() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 / 4 - "# - )); - - assert_eq!(actual.out, "0.25"); -} - -#[test] -fn error_zero_division_int_int() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 / 0 - "# - )); - - assert!(actual.err.contains("division by zero")); -} - -#[test] -fn error_zero_division_decimal_int() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1.0 / 0 - "# - )); - - assert!(actual.err.contains("division by zero")); -} - -#[test] -fn error_zero_division_int_decimal() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1 / 0.0 - "# - )); - - assert!(actual.err.contains("division by zero")); -} - -#[test] -fn error_zero_division_decimal_decimal() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1.0 / 0.0 - "# - )); - - assert!(actual.err.contains("division by zero")); -} - -#[test] -fn proper_precedence_history() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 2 / 2 / 2 + 1 - "# - )); - - assert_eq!(actual.out, "1.5"); -} - -#[test] -fn parens_precedence() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 4 * (6 - 3) - "# - )); - - assert_eq!(actual.out, "12"); -} - -#[test] -fn modulo() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 9 mod 2 - "# - )); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn duration_math() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1wk + 1day - "# - )); - - assert_eq!(actual.out, "8day"); -} - -#[test] -fn duration_decimal_math() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 5.5day + 0.5day - "# - )); - - assert_eq!(actual.out, "6day"); -} - -#[test] -fn duration_math_with_nanoseconds() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1wk + 10ns - "# - )); - - assert_eq!(actual.out, "7day 10ns"); -} - -#[test] -fn duration_decimal_math_with_nanoseconds() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1.5wk + 10ns - "# - )); - - assert_eq!(actual.out, "10day 10ns"); -} - -#[test] -fn duration_math_with_negative() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 1day - 1wk - "# - )); - - assert_eq!(actual.out, "-6day"); -} - -#[test] -fn duration_math_shell_error_on_big_numbers() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - (date now) + 100000000000000day - "# - )); - - assert!(actual.err.contains("Duration overflow")); -} - -#[test] -fn compound_comparison() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 4 > 3 && 2 > 1 - "# - )); - - assert_eq!(actual.out, "true"); -} - -#[test] -fn compound_comparison2() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - 4 < 3 || 2 > 1 - "# - )); - - assert_eq!(actual.out, "true"); -} - -#[test] -fn compound_where() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where a == 2 && b == 1 | to json - "# - )); - - assert_eq!(actual.out, r#"{"a":2,"b":1}"#); -} - -#[test] -fn compound_where_paren() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo '[{"a": 1, "b": 1}, {"a": 2, "b": 1}, {"a": 2, "b": 2}]' | from json | where ($it.a == 2 && $it.b == 1) || $it.b == 2 | to json - "# - )); - - assert_eq!(actual.out, r#"[{"a":2,"b":1},{"a":2,"b":2}]"#); -} diff --git a/old_nushell/crates/nu-command/tests/commands/math/round.rs b/old_nushell/crates/nu-command/tests/commands/math/round.rs deleted file mode 100644 index 2bec436a6..000000000 --- a/old_nushell/crates/nu-command/tests/commands/math/round.rs +++ /dev/null @@ -1,21 +0,0 @@ -use nu_test_support::nu; - -#[test] -fn can_round_very_large_numbers() { - let actual = nu!( - cwd: ".", - "echo 18.1372544780074142289927665486772012345 | math round" - ); - - assert_eq!(actual.out, "18") -} - -#[test] -fn can_round_very_large_numbers_with_precision() { - let actual = nu!( - cwd: ".", - "echo 18.13725447800741422899276654867720121457878988 | math round -p 10" - ); - - assert_eq!(actual.out, "18.137254478") -} diff --git a/old_nushell/crates/nu-command/tests/commands/math/sqrt.rs b/old_nushell/crates/nu-command/tests/commands/math/sqrt.rs deleted file mode 100644 index c8e7eb24a..000000000 --- a/old_nushell/crates/nu-command/tests/commands/math/sqrt.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::nu; - -#[test] -fn can_sqrt_numbers() { - let actual = nu!( - cwd: ".", - "echo [0.25 2 4] | math sqrt | math sum" - ); - - assert_eq!(actual.out, "3.914213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573"); -} - -#[test] -fn can_sqrt_irrational() { - let actual = nu!( - cwd: ".", - "echo 2 | math sqrt" - ); - - assert_eq!(actual.out, "1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573"); -} - -#[test] -fn can_sqrt_perfect_square() { - let actual = nu!( - cwd: ".", - "echo 4 | math sqrt" - ); - - assert_eq!(actual.out, "2"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/math/sum.rs b/old_nushell/crates/nu-command/tests/commands/math/sum.rs deleted file mode 100644 index 4e3623d81..000000000 --- a/old_nushell/crates/nu-command/tests/commands/math/sum.rs +++ /dev/null @@ -1,87 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; -use std::str::FromStr; - -#[test] -fn all() { - Playground::setup("sum_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "meals.json", - r#" - { - meals: [ - {description: "1 large egg", calories: 90}, - {description: "1 cup white rice", calories: 250}, - {description: "1 tablespoon fish oil", calories: 108} - ] - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open meals.json - | get meals - | get calories - | math sum - "# - )); - - assert_eq!(actual.out, "448"); - }) -} - -#[test] -#[allow(clippy::unreadable_literal)] -#[allow(clippy::float_cmp)] -fn compute_sum_of_individual_row() -> Result<(), String> { - let answers_for_columns = [ - ("cpu", 88.257434), - ("mem", 3032375296.), - ("virtual", 102579965952.), - ]; - for (column_name, expected_value) in answers_for_columns { - let actual = nu!( - cwd: "tests/fixtures/formats/", - format!("open sample-ps-output.json | select {} | math sum | get {}", column_name, column_name) - ); - let result = - f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?; - assert_eq!(result, expected_value); - } - Ok(()) -} - -#[test] -#[allow(clippy::unreadable_literal)] -#[allow(clippy::float_cmp)] -fn compute_sum_of_table() -> Result<(), String> { - let answers_for_columns = [ - ("cpu", 88.257434), - ("mem", 3032375296.), - ("virtual", 102579965952.), - ]; - for (column_name, expected_value) in answers_for_columns { - let actual = nu!( - cwd: "tests/fixtures/formats/", - format!("open sample-ps-output.json | select cpu mem virtual | math sum | get {}", column_name) - ); - let result = - f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?; - assert_eq!(result, expected_value); - } - Ok(()) -} - -#[test] -fn sum_of_a_row_containing_a_table_is_an_error() { - let actual = nu!( - cwd: "tests/fixtures/formats/", - "open sample-sys-output.json | math sum" - ); - assert!(actual - .err - .contains("Attempted to compute values that can't be operated on")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/merge.rs b/old_nushell/crates/nu-command/tests/commands/merge.rs deleted file mode 100644 index 92ec3fe5d..000000000 --- a/old_nushell/crates/nu-command/tests/commands/merge.rs +++ /dev/null @@ -1,42 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn row() { - Playground::setup("merge_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - FileWithContentToBeTrimmed( - "caballeros.csv", - r#" - name,country,luck - Andrés,Ecuador,0 - Jonathan,USA,0 - Jason,Canada,0 - Yehuda,USA,0 - "#, - ), - FileWithContentToBeTrimmed( - "new_caballeros.csv", - r#" - name,country,luck - Andrés Robalino,Guayaquil Ecuador,1 - Jonathan Turner,New Zealand,1 - "#, - ), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open caballeros.csv - | merge { open new_caballeros.csv } - | where country in ["Guayaquil Ecuador" "New Zealand"] - | get luck - | math sum - "# - )); - - assert_eq!(actual.out, "2"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/mkdir.rs b/old_nushell/crates/nu-command/tests/commands/mkdir.rs deleted file mode 100644 index ddb3b0856..000000000 --- a/old_nushell/crates/nu-command/tests/commands/mkdir.rs +++ /dev/null @@ -1,84 +0,0 @@ -use nu_test_support::fs::files_exist_at; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; -use std::path::Path; - -#[test] -fn creates_directory() { - Playground::setup("mkdir_test_1", |dirs, _| { - nu!( - cwd: dirs.test(), - "mkdir my_new_directory" - ); - - let expected = dirs.test().join("my_new_directory"); - - assert!(expected.exists()); - }) -} - -#[test] -fn accepts_and_creates_directories() { - Playground::setup("mkdir_test_2", |dirs, _| { - nu!( - cwd: dirs.test(), - "mkdir dir_1 dir_2 dir_3" - ); - - assert!(files_exist_at( - vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")], - dirs.test() - )); - }) -} - -#[test] -fn creates_intermediary_directories() { - Playground::setup("mkdir_test_3", |dirs, _| { - nu!( - cwd: dirs.test(), - "mkdir some_folder/another/deeper_one" - ); - - let expected = dirs.test().join("some_folder/another/deeper_one"); - - assert!(expected.exists()); - }) -} - -#[test] -fn create_directory_two_parents_up_using_multiple_dots() { - Playground::setup("mkdir_test_4", |dirs, sandbox| { - sandbox.within("foo").mkdir("bar"); - - nu!( - cwd: dirs.test().join("foo/bar"), - "mkdir .../boo" - ); - - let expected = dirs.test().join("boo"); - - assert!(expected.exists()); - }) -} - -#[test] -fn show_created_paths() { - Playground::setup("mkdir_test_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#" - mkdir -s dir_1 dir_2 dir_3 - | length - "# - )); - - assert!(files_exist_at( - vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")], - dirs.test() - )); - - assert_eq!(actual.out, "3"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/mod.rs b/old_nushell/crates/nu-command/tests/commands/mod.rs deleted file mode 100644 index eaf8f6bbe..000000000 --- a/old_nushell/crates/nu-command/tests/commands/mod.rs +++ /dev/null @@ -1,69 +0,0 @@ -mod all; -mod any; -mod append; -mod cal; -mod cd; -mod compact; -mod config; -mod cp; -mod def; -mod default; -mod drop; -mod each; -mod echo; -mod empty; -mod enter; -mod every; -mod find; -mod first; -mod flatten; -mod format; -mod get; -mod group_by; -mod hash_; -mod headers; -mod help; -mod histogram; -mod insert; -mod into_filesize; -mod into_int; -mod keep; -mod last; -mod length; -mod lines; -mod ls; -mod math; -mod merge; -mod mkdir; -mod move_; -mod open; -mod parse; -mod path; -mod pathvar; -mod prepend; -mod random; -mod range; -mod reduce; -mod rename; -mod reverse; -mod rm; -mod roll; -mod rotate; -mod save; -mod select; -mod semicolon; -mod skip; -mod sort_by; -mod source; -mod split_by; -mod split_column; -mod split_row; -mod str_; -mod touch; -mod uniq; -mod update; -mod where_; -mod which; -mod with_env; -mod wrap; -mod zip; diff --git a/old_nushell/crates/nu-command/tests/commands/move_/column.rs b/old_nushell/crates/nu-command/tests/commands/move_/column.rs deleted file mode 100644 index caf1b2fd4..000000000 --- a/old_nushell/crates/nu-command/tests/commands/move_/column.rs +++ /dev/null @@ -1,137 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn moves_a_column_before() { - Playground::setup("move_column_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.csv", - r#" - column1,column2,column3,...,column98,column99,column100 - -------,-------,-------,---,--------, A ,--------- - -------,-------,-------,---,--------, N ,--------- - -------,-------,-------,---,--------, D ,--------- - -------,-------,-------,---,--------, R ,--------- - -------,-------,-------,---,--------, E ,--------- - -------,-------,-------,---,--------, S ,--------- - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.csv - | move column99 --before column1 - | rename chars - | get chars - | str trim - | str collect - "# - )); - - assert!(actual.out.contains("ANDRES")); - }) -} - -#[test] -fn moves_columns_before() { - Playground::setup("move_column_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.csv", - r#" - column1,column2,column3,...,column98,column99,column100 - -------,-------, A ,---,--------, N ,--------- - -------,-------, D ,---,--------, R ,--------- - -------,-------, E ,---,--------, S ,--------- - -------,-------, : ,---,--------, : ,--------- - -------,-------, J ,---,--------, O ,--------- - -------,-------, N ,---,--------, A ,--------- - -------,-------, T ,---,--------, H ,--------- - -------,-------, A ,---,--------, N ,--------- - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.csv - | move column99 column3 --before column2 - | rename _ chars_1 chars_2 - | get chars_2 chars_1 - | str trim - | str collect - "# - )); - - assert!(actual.out.contains("ANDRES::JONATHAN")); - }) -} - -#[test] -fn moves_a_column_after() { - Playground::setup("move_column_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.csv", - r#" - column1,column2,letters,...,column98,and_more,column100 - -------,-------, A ,---,--------, N ,--------- - -------,-------, D ,---,--------, R ,--------- - -------,-------, E ,---,--------, S ,--------- - -------,-------, : ,---,--------, : ,--------- - -------,-------, J ,---,--------, O ,--------- - -------,-------, N ,---,--------, A ,--------- - -------,-------, T ,---,--------, H ,--------- - -------,-------, A ,---,--------, N ,--------- - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.csv - | move letters --after and_more - | move letters and_more --before column2 - | rename _ chars_1 chars_2 - | get chars_1 chars_2 - | str trim - | str collect - "# - )); - - assert!(actual.out.contains("ANDRES::JONATHAN")); - }) -} - -#[test] -fn moves_columns_after() { - Playground::setup("move_column_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.csv", - r#" - column1,column2,letters,...,column98,and_more,column100 - -------,-------, A ,---,--------, N ,--------- - -------,-------, D ,---,--------, R ,--------- - -------,-------, E ,---,--------, S ,--------- - -------,-------, : ,---,--------, : ,--------- - -------,-------, J ,---,--------, O ,--------- - -------,-------, N ,---,--------, A ,--------- - -------,-------, T ,---,--------, H ,--------- - -------,-------, A ,---,--------, N ,--------- - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.csv - | move letters and_more --after column1 - | get - | nth 1 2 - | str collect - "# - )); - - assert!(actual.out.contains("lettersand_more")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/move_/mod.rs b/old_nushell/crates/nu-command/tests/commands/move_/mod.rs deleted file mode 100644 index 58d0a7f6c..000000000 --- a/old_nushell/crates/nu-command/tests/commands/move_/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod column; -mod mv; diff --git a/old_nushell/crates/nu-command/tests/commands/move_/mv.rs b/old_nushell/crates/nu-command/tests/commands/move_/mv.rs deleted file mode 100644 index 5debb64b3..000000000 --- a/old_nushell/crates/nu-command/tests/commands/move_/mv.rs +++ /dev/null @@ -1,361 +0,0 @@ -use nu_test_support::fs::{files_exist_at, Stub::EmptyFile}; -use nu_test_support::nu; -use nu_test_support::playground::Playground; - -#[test] -fn moves_a_file() { - Playground::setup("mv_test_1", |dirs, sandbox| { - sandbox - .with_files(vec![EmptyFile("andres.txt")]) - .mkdir("expected"); - - let original = dirs.test().join("andres.txt"); - let expected = dirs.test().join("expected/yehuda.txt"); - - nu!( - cwd: dirs.test(), - "mv andres.txt expected/yehuda.txt" - ); - - assert!(!original.exists()); - assert!(expected.exists()); - }) -} - -#[test] -fn overwrites_if_moving_to_existing_file() { - Playground::setup("mv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("andres.txt"), EmptyFile("jonathan.txt")]); - - let original = dirs.test().join("andres.txt"); - let expected = dirs.test().join("jonathan.txt"); - - nu!( - cwd: dirs.test(), - "mv andres.txt jonathan.txt" - ); - - assert!(!original.exists()); - assert!(expected.exists()); - }) -} - -#[test] -fn moves_a_directory() { - Playground::setup("mv_test_3", |dirs, sandbox| { - sandbox.mkdir("empty_dir"); - - let original_dir = dirs.test().join("empty_dir"); - let expected = dirs.test().join("renamed_dir"); - - nu!( - cwd: dirs.test(), - "mv empty_dir renamed_dir" - ); - - assert!(!original_dir.exists()); - assert!(expected.exists()); - }) -} - -#[test] -fn moves_the_file_inside_directory_if_path_to_move_is_existing_directory() { - Playground::setup("mv_test_4", |dirs, sandbox| { - sandbox - .with_files(vec![EmptyFile("jonathan.txt")]) - .mkdir("expected"); - - let original_dir = dirs.test().join("jonathan.txt"); - let expected = dirs.test().join("expected/jonathan.txt"); - - nu!( - cwd: dirs.test(), - "mv jonathan.txt expected" - ); - - assert!(!original_dir.exists()); - assert!(expected.exists()); - }) -} - -#[test] -fn moves_the_directory_inside_directory_if_path_to_move_is_existing_directory() { - Playground::setup("mv_test_5", |dirs, sandbox| { - sandbox - .within("contributors") - .with_files(vec![EmptyFile("jonathan.txt")]) - .mkdir("expected"); - - let original_dir = dirs.test().join("contributors"); - let expected = dirs.test().join("expected/contributors"); - - nu!( - cwd: dirs.test(), - "mv contributors expected" - ); - - assert!(!original_dir.exists()); - assert!(expected.exists()); - assert!(files_exist_at(vec!["jonathan.txt"], expected)) - }) -} - -#[test] -fn moves_using_path_with_wildcard() { - Playground::setup("mv_test_7", |dirs, sandbox| { - sandbox - .within("originals") - .with_files(vec![ - EmptyFile("andres.ini"), - EmptyFile("caco3_plastics.csv"), - EmptyFile("cargo_sample.toml"), - EmptyFile("jonathan.ini"), - EmptyFile("jonathan.xml"), - EmptyFile("sgml_description.json"), - EmptyFile("sample.ini"), - EmptyFile("utf16.ini"), - EmptyFile("yehuda.ini"), - ]) - .mkdir("work_dir") - .mkdir("expected"); - - let work_dir = dirs.test().join("work_dir"); - let expected = dirs.test().join("expected"); - - nu!(cwd: work_dir, "mv ../originals/*.ini ../expected"); - - assert!(files_exist_at( - vec!["yehuda.ini", "jonathan.ini", "sample.ini", "andres.ini",], - expected - )); - }) -} - -#[test] -fn moves_using_a_glob() { - Playground::setup("mv_test_8", |dirs, sandbox| { - sandbox - .within("meals") - .with_files(vec![ - EmptyFile("arepa.txt"), - EmptyFile("empanada.txt"), - EmptyFile("taquiza.txt"), - ]) - .mkdir("work_dir") - .mkdir("expected"); - - let meal_dir = dirs.test().join("meals"); - let work_dir = dirs.test().join("work_dir"); - let expected = dirs.test().join("expected"); - - nu!(cwd: work_dir, "mv ../meals/* ../expected"); - - assert!(meal_dir.exists()); - assert!(files_exist_at( - vec!["arepa.txt", "empanada.txt", "taquiza.txt",], - expected - )); - }) -} - -#[test] -fn moves_a_directory_with_files() { - Playground::setup("mv_test_9", |dirs, sandbox| { - sandbox - .mkdir("vehicles/car") - .mkdir("vehicles/bicycle") - .with_files(vec![ - EmptyFile("vehicles/car/car1.txt"), - EmptyFile("vehicles/car/car2.txt"), - ]) - .with_files(vec![ - EmptyFile("vehicles/bicycle/bicycle1.txt"), - EmptyFile("vehicles/bicycle/bicycle2.txt"), - ]); - - let original_dir = dirs.test().join("vehicles"); - let expected_dir = dirs.test().join("expected"); - - nu!( - cwd: dirs.test(), - "mv vehicles expected" - ); - - assert!(!original_dir.exists()); - assert!(expected_dir.exists()); - assert!(files_exist_at( - vec![ - "car/car1.txt", - "car/car2.txt", - "bicycle/bicycle1.txt", - "bicycle/bicycle2.txt" - ], - expected_dir - )); - }) -} - -#[test] -fn errors_if_source_doesnt_exist() { - Playground::setup("mv_test_10", |dirs, sandbox| { - sandbox.mkdir("test_folder"); - let actual = nu!( - cwd: dirs.test(), - "mv non-existing-file test_folder/" - ); - assert!(actual.err.contains("Invalid file or pattern")); - }) -} - -#[test] -fn errors_if_destination_doesnt_exist() { - Playground::setup("mv_test_10_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("empty.txt")]); - - let actual = nu!( - cwd: dirs.test(), - "mv empty.txt does/not/exist" - ); - - assert!(actual.err.contains("Destination directory does not exist")); - }) -} - -#[test] -fn errors_if_multiple_sources_but_destination_not_a_directory() { - Playground::setup("mv_test_10_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("file1.txt"), - EmptyFile("file2.txt"), - EmptyFile("file3.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), - "mv file?.txt not_a_dir" - ); - - assert!(actual - .err - .contains("Can only move multiple sources if destination is a directory")); - }) -} - -#[test] -fn errors_if_renaming_directory_to_an_existing_file() { - Playground::setup("mv_test_10_3", |dirs, sandbox| { - sandbox - .mkdir("mydir") - .with_files(vec![EmptyFile("empty.txt")]); - - let actual = nu!( - cwd: dirs.test(), - "mv mydir empty.txt" - ); - - assert!(actual.err.contains("Cannot rename a directory to a file")); - }) -} - -#[test] -fn errors_if_moving_to_itself() { - Playground::setup("mv_test_10_4", |dirs, sandbox| { - sandbox.mkdir("mydir").mkdir("mydir/mydir_2"); - - let actual = nu!( - cwd: dirs.test(), - "mv mydir mydir/mydir_2/" - ); - - assert!(actual.err.contains("cannot move to itself")); - }) -} - -#[test] -fn does_not_error_on_relative_parent_path() { - Playground::setup("mv_test_11", |dirs, sandbox| { - sandbox - .mkdir("first") - .with_files(vec![EmptyFile("first/william_hartnell.txt")]); - - let original = dirs.test().join("first/william_hartnell.txt"); - let expected = dirs.test().join("william_hartnell.txt"); - - nu!( - cwd: dirs.test().join("first"), - "mv william_hartnell.txt ./.." - ); - - assert!(!original.exists()); - assert!(expected.exists()); - }) -} - -#[test] -fn move_files_using_glob_two_parents_up_using_multiple_dots() { - Playground::setup("mv_test_12", |dirs, sandbox| { - sandbox.within("foo").within("bar").with_files(vec![ - EmptyFile("jonathan.json"), - EmptyFile("andres.xml"), - EmptyFile("yehuda.yaml"), - EmptyFile("kevin.txt"), - EmptyFile("many_more.ppl"), - ]); - - nu!( - cwd: dirs.test().join("foo/bar"), - r#" - mv * ... - "# - ); - - let files = vec![ - "yehuda.yaml", - "jonathan.json", - "andres.xml", - "kevin.txt", - "many_more.ppl", - ]; - - let original_dir = dirs.test().join("foo/bar"); - let destination_dir = dirs.test(); - - assert!(files_exist_at(files.clone(), destination_dir)); - assert!(!files_exist_at(files, original_dir)) - }) -} - -#[test] -fn move_file_from_two_parents_up_using_multiple_dots_to_current_dir() { - Playground::setup("cp_test_10", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("hello_there")]); - sandbox.within("foo").mkdir("bar"); - - nu!( - cwd: dirs.test().join("foo/bar"), - r#" - mv .../hello_there . - "# - ); - - let expected = dirs.test().join("foo/bar/hello_there"); - let original = dirs.test().join("hello_there"); - - assert!(expected.exists()); - assert!(!original.exists()); - }) -} - -#[test] -fn does_not_error_when_some_file_is_moving_into_itself() { - Playground::setup("mv_test_13", |dirs, sandbox| { - sandbox.mkdir("11").mkdir("12"); - - let original_dir = dirs.test().join("11"); - let expected = dirs.test().join("12/11"); - nu!(cwd: dirs.test(), "mv 1* 12"); - - assert!(!original_dir.exists()); - assert!(expected.exists()); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/nth.rs b/old_nushell/crates/nu-command/tests/commands/nth.rs deleted file mode 100644 index a65dcd7ed..000000000 --- a/old_nushell/crates/nu-command/tests/commands/nth.rs +++ /dev/null @@ -1,37 +0,0 @@ -#[test] -fn selects_a_row() { - Playground::setup("nth_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | sort-by name - | nth 0 - | get name - "# - )); - - assert_eq!(actual.out, "arepas.txt"); - }); -} - -#[test] -fn selects_many_rows() { - Playground::setup("nth_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | nth 1 0 - | length - "# - )); - - assert_eq!(actual.out, "2"); - }); -} diff --git a/old_nushell/crates/nu-command/tests/commands/open.rs b/old_nushell/crates/nu-command/tests/commands/open.rs deleted file mode 100644 index 994d2699d..000000000 --- a/old_nushell/crates/nu-command/tests/commands/open.rs +++ /dev/null @@ -1,254 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn parses_csv() { - Playground::setup("open_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "nu.zion.csv", - r#" - author,lang,source - Jonathan Turner,Rust,New Zealand - Andres N. Robalino,Rust,Ecuador - Yehuda Katz,Rust,Estados Unidos - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open nu.zion.csv - | where author == "Andres N. Robalino" - | get source - "# - )); - - assert_eq!(actual.out, "Ecuador"); - }) -} - -// sample.bson has the following format: -// ━━━━━━━━━━┯━━━━━━━━━━━ -// _id │ root -// ──────────┼─────────── -// [object] │ [9 items] -// ━━━━━━━━━━┷━━━━━━━━━━━ -// -// the root value is: -// ━━━┯━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━ -// # │ _id │ a │ b │ c -// ───┼───────────────────┼─────────────────────────┼──────────┼────────── -// 0 │ [object] │ 1.000000000000000 │ hello │ [2 items] -// 1 │ [object] │ 42.00000000000000 │ whel │ hello -// 2 │ [object] │ [object] │ │ -// 3 │ [object] │ │ [object] │ -// 4 │ [object] │ │ │ [object] -// 5 │ [object] │ │ │ [object] -// 6 │ [object] │ [object] │ [object] │ -// 7 │ [object] │ │ [object] │ -// 8 │ 1.000000 │ │ [object] │ -// -// The decimal value is supposed to be π, but is currently wrong due to -// what appears to be an issue in the bson library that is under investigation. -// - -#[cfg(feature = "bson")] -#[test] -fn parses_bson() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open sample.bson | get root | nth 0 | get b" - ); - - assert_eq!(actual.out, "hello"); -} - -#[cfg(feature = "bson")] -#[test] -fn parses_more_bson_complexity() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.bson - | get root - | nth 6 - | get b - | get '$binary_subtype' - "# - )); - - assert_eq!(actual.out, "function"); -} - -// sample.db has the following format: -// -// ━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━ -// # │ table_name │ table_values -// ───┼────────────┼────────────── -// 0 │ strings │ [6 items] -// 1 │ ints │ [5 items] -// 2 │ floats │ [4 items] -// ━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━ -// -// In this case, this represents a sqlite database -// with three tables named `strings`, `ints`, and `floats`. -// The table_values represent the values for the tables: -// -// ━━━━┯━━━━━━━┯━━━━━━━━━━┯━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -// # │ x │ y │ z │ f -// ────┼───────┼──────────┼──────┼────────────────────────────────────────────────────────────────────── -// 0 │ hello │ │ │ -// 1 │ hello │ │ │ -// 2 │ hello │ │ │ -// 3 │ hello │ │ │ -// 4 │ world │ │ │ -// 5 │ world │ │ │ -// 6 │ │ │ 1 │ -// 7 │ │ │ 42 │ -// 8 │ │ │ 425 │ -// 9 │ │ │ 4253 │ -// 10 │ │ │ │ -// 11 │ │ │ │ 3.400000000000000 -// 12 │ │ │ │ 3.141592650000000 -// 13 │ │ │ │ 23.00000000000000 -// 14 │ │ │ │ this string that doesn't really belong here but sqlite is what it is -// ━━━━┷━━━━━━━┷━━━━━━━━━━┷━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -// -// We can see here that each table has different columns. `strings` has `x` and `y`, while -// `ints` has just `z`, and `floats` has only the column `f`. This means, in general, when working -// with sqlite, one will want to select a single table, e.g.: -// -// open sample.db | nth 1 | get table_values -// ━━━┯━━━━━━ -// # │ z -// ───┼────── -// 0 │ 1 -// 1 │ 42 -// 2 │ 425 -// 3 │ 4253 -// 4 │ -// ━━━┷━━━━━━ - -#[cfg(feature = "sqlite")] -#[test] -fn parses_sqlite() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | get table_values - | nth 2 - | get x - "# - )); - - assert_eq!(actual.out, "hello"); -} - -#[test] -fn parses_toml() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open cargo_sample.toml | get package.edition" - ); - - assert_eq!(actual.out, "2018"); -} - -#[test] -fn parses_tsv() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open caco3_plastics.tsv - | first 1 - | get origin - "# - )); - - assert_eq!(actual.out, "SPAIN") -} - -#[test] -fn parses_json() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sgml_description.json - | get glossary.GlossDiv.GlossList.GlossEntry.GlossSee - "# - )); - - assert_eq!(actual.out, "markup") -} - -#[test] -fn parses_xml() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open jonathan.xml | get rss.children.channel.children | get item.children | get link.children.0" - ); - - assert_eq!( - actual.out, - "http://www.jonathanturner.org/2015/10/off-to-new-adventures.html" - ) -} - -#[test] -fn parses_ini() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open sample.ini | get SectionOne.integer" - ); - - assert_eq!(actual.out, "1234") -} - -#[test] -fn parses_utf16_ini() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open utf16.ini | rename info | get info | get IconIndex" - ); - - assert_eq!(actual.out, "-236") -} - -#[test] -fn errors_if_file_not_found() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open i_dont_exist.txt" - ); - let expected = "Cannot find file"; - assert!( - actual.err.contains(expected), - "Error:\n{}\ndoes not contain{}", - actual.err, - expected - ); -} - -#[test] -fn open_dir_is_ls() { - Playground::setup("open_dir", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open . - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/parse.rs b/old_nushell/crates/nu-command/tests/commands/parse.rs deleted file mode 100644 index 3b9c9c527..000000000 --- a/old_nushell/crates/nu-command/tests/commands/parse.rs +++ /dev/null @@ -1,187 +0,0 @@ -use nu_test_support::fs::Stub; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -mod simple { - use super::*; - - #[test] - fn extracts_fields_from_the_given_the_pattern() { - Playground::setup("parse_test_1", |dirs, sandbox| { - sandbox.with_files(vec![Stub::FileWithContentToBeTrimmed( - "key_value_separated_arepa_ingredients.txt", - r#" - VAR1=Cheese - VAR2=JonathanParsed - VAR3=NushellSecretIngredient - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open key_value_separated_arepa_ingredients.txt - | lines - | each { echo $it | parse "{Name}={Value}" } - | nth 1 - | get Value - "# - )); - - assert_eq!(actual.out, "JonathanParsed"); - }) - } - - #[test] - fn double_open_curly_evalutes_to_a_single_curly() { - Playground::setup("parse_test_regex_2", |dirs, _sandbox| { - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "{abc}123" - | parse "{{abc}{name}" - | get name - "# - )); - - assert_eq!(actual.out, "123"); - }) - } - - #[test] - fn properly_escapes_text() { - Playground::setup("parse_test_regex_3", |dirs, _sandbox| { - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "(abc)123" - | parse "(abc){name}" - | get name - "# - )); - - assert_eq!(actual.out, "123"); - }) - } - - #[test] - fn properly_captures_empty_column() { - Playground::setup("parse_test_regex_4", |dirs, _sandbox| { - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo ["1:INFO:component:all is well" "2:ERROR::something bad happened"] - | parse "{timestamp}:{level}:{tag}:{entry}" - | get entry - | nth 1 - "# - )); - - assert_eq!(actual.out, "something bad happened"); - }) - } - - #[test] - fn errors_when_missing_closing_brace() { - Playground::setup("parse_test_regex_5", |dirs, _sandbox| { - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "(abc)123" - | parse "(abc){name" - | get name - "# - )); - - assert!(actual.err.contains("invalid parse pattern")); - }) - } -} - -mod regex { - use super::*; - - fn nushell_git_log_oneline<'a>() -> Vec> { - vec![Stub::FileWithContentToBeTrimmed( - "nushell_git_log_oneline.txt", - r#" - ae87582c Fix missing invocation errors (#1846) - b89976da let format access variables also (#1842) - "#, - )] - } - - #[test] - fn extracts_fields_with_all_named_groups() { - Playground::setup("parse_test_regex_1", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open nushell_git_log_oneline.txt - | parse --regex "(?P\w+) (?P.+) \(#(?P\d+)\)" - | nth 1 - | get PR - "# - )); - - assert_eq!(actual.out, "1842"); - }) - } - - #[test] - fn extracts_fields_with_all_unnamed_groups() { - Playground::setup("parse_test_regex_2", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open nushell_git_log_oneline.txt - | parse --regex "(\w+) (.+) \(#(\d+)\)" - | nth 1 - | get Capture1 - "# - )); - - assert_eq!(actual.out, "b89976da"); - }) - } - - #[test] - fn extracts_fields_with_named_and_unnamed_groups() { - Playground::setup("parse_test_regex_3", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open nushell_git_log_oneline.txt - | parse --regex "(?P\w+) (.+) \(#(?P\d+)\)" - | nth 1 - | get Capture2 - "# - )); - - assert_eq!(actual.out, "let format access variables also"); - }) - } - - #[test] - fn errors_with_invalid_regex() { - Playground::setup("parse_test_regex_1", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open nushell_git_log_oneline.txt - | parse --regex "(?P\w+ unfinished capture group" - "# - )); - - assert!(actual.err.contains("unclosed group")); - }) - } -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/basename.rs b/old_nushell/crates/nu-command/tests/commands/path/basename.rs deleted file mode 100644 index a16c8202c..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/basename.rs +++ /dev/null @@ -1,83 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -use super::join_path_sep; - -#[test] -fn returns_basename_of_empty_input() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "" - | path basename - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn replaces_basename_of_empty_input() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "" - | path basename -r newname.txt - "# - )); - - assert_eq!(actual.out, "newname.txt"); -} - -#[test] -fn returns_basename_of_path_ending_with_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/file.txt/." - | path basename - "# - )); - - assert_eq!(actual.out, "file.txt"); -} - -#[test] -fn replaces_basename_of_path_ending_with_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/file.txt/." - | path basename -r viking.txt - "# - )); - - let expected = join_path_sep(&["some", "viking.txt"]); - assert_eq!(actual.out, expected); -} - -#[test] -fn returns_basename_of_path_ending_with_double_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/file.txt/.." - | path basename - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn replaces_basename_of_path_ending_with_double_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/file.txt/.." - | path basename -r eggs - "# - )); - - let expected = join_path_sep(&["some/file.txt/..", "eggs"]); - assert_eq!(actual.out, expected); -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/dirname.rs b/old_nushell/crates/nu-command/tests/commands/path/dirname.rs deleted file mode 100644 index a935c1fb3..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/dirname.rs +++ /dev/null @@ -1,137 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -use super::join_path_sep; - -#[test] -fn returns_dirname_of_empty_input() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "" - | path dirname - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn replaces_dirname_of_empty_input() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "" - | path dirname -r newdir - "# - )); - - assert_eq!(actual.out, "newdir"); -} - -#[test] -fn returns_dirname_of_path_ending_with_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/." - | path dirname - "# - )); - - assert_eq!(actual.out, "some"); -} - -#[test] -fn replaces_dirname_of_path_ending_with_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/." - | path dirname -r eggs - "# - )); - - let expected = join_path_sep(&["eggs", "dir"]); - assert_eq!(actual.out, expected); -} - -#[test] -fn returns_dirname_of_path_ending_with_double_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/.." - | path dirname - "# - )); - - assert_eq!(actual.out, "some/dir"); -} - -#[test] -fn replaces_dirname_of_path_with_double_dot() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/.." - | path dirname -r eggs - "# - )); - - let expected = join_path_sep(&["eggs", ".."]); - assert_eq!(actual.out, expected); -} - -#[test] -fn returns_dirname_of_zero_levels() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/with/spam.txt" - | path dirname -n 0 - "# - )); - - assert_eq!(actual.out, "some/dir/with/spam.txt"); -} - -#[test] -fn replaces_dirname_of_zero_levels_with_empty_string() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/with/spam.txt" - | path dirname -n 0 -r "" - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn replaces_dirname_of_more_levels() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/with/spam.txt" - | path dirname -r eggs -n 2 - "# - )); - - let expected = join_path_sep(&["eggs", "with/spam.txt"]); - assert_eq!(actual.out, expected); -} - -#[test] -fn replaces_dirname_of_way_too_many_levels() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "some/dir/with/spam.txt" - | path dirname -r eggs -n 999 - "# - )); - - let expected = join_path_sep(&["eggs", "some/dir/with/spam.txt"]); - assert_eq!(actual.out, expected); -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/exists.rs b/old_nushell/crates/nu-command/tests/commands/path/exists.rs deleted file mode 100644 index 9a1b496e0..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/exists.rs +++ /dev/null @@ -1,53 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::nu; -use nu_test_support::playground::Playground; - -#[test] -fn checks_if_existing_file_exists() { - Playground::setup("path_exists_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); - - let actual = nu!( - cwd: dirs.test(), - "echo spam.txt | path exists" - ); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn checks_if_missing_file_exists() { - Playground::setup("path_exists_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - "echo spam.txt | path exists" - ); - - assert_eq!(actual.out, "false"); - }) -} - -#[test] -fn checks_if_dot_exists() { - Playground::setup("path_exists_3", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - "echo '.' | path exists" - ); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn checks_if_double_dot_exists() { - Playground::setup("path_exists_4", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - "echo '..' | path exists" - ); - - assert_eq!(actual.out, "true"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/expand.rs b/old_nushell/crates/nu-command/tests/commands/path/expand.rs deleted file mode 100644 index 08ca9dc58..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/expand.rs +++ /dev/null @@ -1,78 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -use std::path::PathBuf; - -#[test] -fn expands_path_with_dot() { - Playground::setup("path_expand_1", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "menu/./spam.txt" - | path expand - "# - )); - - let expected = dirs.test.join("menu").join("spam.txt"); - assert_eq!(PathBuf::from(actual.out), expected); - }) -} - -#[test] -fn expands_path_with_double_dot() { - Playground::setup("path_expand_2", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "menu/../menu/spam.txt" - | path expand - "# - )); - - let expected = dirs.test.join("menu").join("spam.txt"); - assert_eq!(PathBuf::from(actual.out), expected); - }) -} - -#[cfg(windows)] -mod windows { - use super::*; - - #[test] - fn expands_path_with_tilde_backward_slash() { - Playground::setup("path_expand_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "~\tmp.txt" | path expand - "# - )); - - assert!(!PathBuf::from(actual.out).starts_with("~")); - }) - } - - #[test] - fn win_expands_path_with_tilde_forward_slash() { - Playground::setup("path_expand_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "~/tmp.txt" | path expand - "# - )); - - assert!(!PathBuf::from(actual.out).starts_with("~")); - }) - } -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/join.rs b/old_nushell/crates/nu-command/tests/commands/path/join.rs deleted file mode 100644 index b7ffa7353..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/join.rs +++ /dev/null @@ -1,59 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -use super::join_path_sep; - -#[test] -fn returns_path_joined_with_column_path() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo [ [name]; [eggs] ] - | path join spam.txt -c [ name ] - | get name - "# - )); - - let expected = join_path_sep(&["eggs", "spam.txt"]); - assert_eq!(actual.out, expected); -} - -#[test] -fn returns_path_joined_from_list() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo [ home viking spam.txt ] - | path join - "# - )); - - let expected = join_path_sep(&["home", "viking", "spam.txt"]); - assert_eq!(actual.out, expected); -} - -#[test] -fn appends_slash_when_joined_with_empty_path() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "/some/dir" - | path join '' - "# - )); - - let expected = join_path_sep(&["/some/dir", ""]); - assert_eq!(actual.out, expected); -} - -#[test] -fn returns_joined_path_when_joining_empty_path() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "" - | path join foo.txt - "# - )); - - assert_eq!(actual.out, "foo.txt"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/mod.rs b/old_nushell/crates/nu-command/tests/commands/path/mod.rs deleted file mode 100644 index c836c5691..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -mod basename; -mod dirname; -mod exists; -mod expand; -mod join; -mod parse; -mod split; -mod type_; - -use std::path::MAIN_SEPARATOR; - -/// Helper function that joins string literals with '/' or '\', based on host OS -fn join_path_sep(pieces: &[&str]) -> String { - let sep_string = String::from(MAIN_SEPARATOR); - pieces.join(&sep_string) -} - -#[cfg(windows)] -#[test] -fn joins_path_on_windows() { - let pieces = ["sausage", "bacon", "spam"]; - let actual = join_path_sep(&pieces); - - assert_eq!(&actual, "sausage\\bacon\\spam"); -} - -#[cfg(not(windows))] -#[test] -fn joins_path_on_other_than_windows() { - let pieces = ["sausage", "bacon", "spam"]; - let actual = join_path_sep(&pieces); - - assert_eq!(&actual, "sausage/bacon/spam"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/parse.rs b/old_nushell/crates/nu-command/tests/commands/path/parse.rs deleted file mode 100644 index b4ffb3b65..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/parse.rs +++ /dev/null @@ -1,136 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[cfg(windows)] -#[test] -fn parses_single_path_prefix() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'C:\users\viking\spam.txt' - | path parse - | get prefix - "# - )); - - assert_eq!(actual.out, "C:"); -} - -#[test] -fn parses_single_path_parent() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'home/viking/spam.txt' - | path parse - | get parent - "# - )); - - assert_eq!(actual.out, "home/viking"); -} - -#[test] -fn parses_single_path_stem() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'home/viking/spam.txt' - | path parse - | get stem - "# - )); - - assert_eq!(actual.out, "spam"); -} - -#[test] -fn parses_custom_extension_gets_extension() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'home/viking/spam.tar.gz' - | path parse -e tar.gz - | get extension - "# - )); - - assert_eq!(actual.out, "tar.gz"); -} - -#[test] -fn parses_custom_extension_gets_stem() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'home/viking/spam.tar.gz' - | path parse -e tar.gz - | get stem - "# - )); - - assert_eq!(actual.out, "spam"); -} - -#[test] -fn parses_ignoring_extension_gets_extension() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'home/viking/spam.tar.gz' - | path parse -e '' - | get extension - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn parses_ignoring_extension_gets_stem() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'home/viking/spam.tar.gz' - | path parse -e "" - | get stem - "# - )); - - assert_eq!(actual.out, "spam.tar.gz"); -} - -#[test] -fn parses_column_path_extension() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo [[home, barn]; ['home/viking/spam.txt', 'barn/cow/moo.png']] - | path parse -c [ home barn ] - | get barn - | get extension - "# - )); - - assert_eq!(actual.out, "png"); -} - -#[test] -fn parses_into_correct_number_of_columns() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo 'home/viking/spam.txt' - | path parse - | pivot - | get Column0 - | length - "# - )); - - #[cfg(windows)] - let expected = "4"; - #[cfg(not(windows))] - let expected = "3"; - - assert_eq!(actual.out, expected); -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/split.rs b/old_nushell/crates/nu-command/tests/commands/path/split.rs deleted file mode 100644 index 97f1cbd37..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/split.rs +++ /dev/null @@ -1,47 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn splits_empty_path() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo '' | path split - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn splits_correctly_single_path() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo ['home/viking/spam.txt'] - | path split - | last - "# - )); - - assert_eq!(actual.out, "spam.txt"); -} - -#[test] -fn splits_correctly_with_column_path() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo [ - [home, barn]; - - ['home/viking/spam.txt', 'barn/cow/moo.png'] - ['home/viking/eggs.txt', 'barn/goat/cheese.png'] - ] - | path split -c [ home barn ] - | get barn - | length - "# - )); - - assert_eq!(actual.out, "6"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/path/type_.rs b/old_nushell/crates/nu-command/tests/commands/path/type_.rs deleted file mode 100644 index 0699767f8..000000000 --- a/old_nushell/crates/nu-command/tests/commands/path/type_.rs +++ /dev/null @@ -1,54 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn returns_type_of_missing_file() { - let actual = nu!( - cwd: "tests", pipeline( - r#" - echo "spam.txt" - | path type - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn returns_type_of_existing_file() { - Playground::setup("path_expand_1", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "menu" - | path type - "# - )); - - assert_eq!(actual.out, "Dir"); - }) -} - -#[test] -fn returns_type_of_existing_directory() { - Playground::setup("path_expand_1", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - echo "menu/spam.txt" - | path type - "# - )); - - assert_eq!(actual.out, "File"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/pathvar/mod.rs b/old_nushell/crates/nu-command/tests/commands/pathvar/mod.rs deleted file mode 100644 index 2ac3fd138..000000000 --- a/old_nushell/crates/nu-command/tests/commands/pathvar/mod.rs +++ /dev/null @@ -1,380 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContent; -use nu_test_support::fs::{AbsolutePath, DisplayPath}; -use nu_test_support::playground::{says, Playground}; -use nu_test_support::{nu, NATIVE_PATH_ENV_SEPARATOR}; - -use std::path::PathBuf; - -use hamcrest2::assert_that; -use hamcrest2::prelude::*; - -/// Helper function that joins string literals with ':' or ';', based on host OS -fn join_env_sep(pieces: &[&str]) -> String { - let sep_string = String::from(NATIVE_PATH_ENV_SEPARATOR); - pieces.join(&sep_string) -} - -// Helpers - -#[cfg(windows)] -#[test] -fn joins_env_on_windows() { - let pieces = ["sausage", "bacon", "spam"]; - let actual = join_env_sep(&pieces); - - assert_eq!(&actual, "sausage;bacon;spam"); -} - -#[cfg(not(windows))] -#[test] -fn joins_env_on_non_windows() { - let pieces = ["sausage", "bacon", "spam"]; - let actual = join_env_sep(&pieces); - - assert_eq!(&actual, "sausage:bacon:spam"); -} - -// The following tests don't work on Windows likely because of this issue: -// https://github.com/nushell/nushell/issues/3831 -// -// fn pathvar_correctly_reads_path_from_config_and_env() -// fn pathvar_correctly_reads_path_from_env() -// fn pathvar_saves_new_path_to_config() -// -// Requires also auto-reading other-than-path env vars from config: -// fn pathvar_correctly_reads_env_var_from_config_and_env() -// fn pathvar_correctly_reads_env_var_from_config() - -// pathvar - -#[test] -fn pathvar_correctly_reads_path_from_config() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - path = ["/Users/andresrobalino/.volta/bin", "/Users/mosqueteros/bin"] - "#, - )]) - .with_config(&file); - - let expected = "/Users/andresrobalino/.volta/bin-/Users/mosqueteros/bin"; - let actual = sandbox.pipeline(r#" pathvar | first 2 | str collect '-' "#); - - assert_that!(actual, says().stdout(expected)); - }) -} - -#[test] -fn pathvar_correctly_reads_env_var_from_env() { - Playground::setup("hi_there", |_, sandbox| { - sandbox.with_env("BREAKFAST", &join_env_sep(&["bacon", "spam"])); - - let expected = "bacon-spam"; - let actual = sandbox.pipeline(r#" pathvar -v BREAKFAST | str collect '-' "#); - - assert_that!(actual, says().stdout(expected)); - }) -} - -// pathvar add - -#[test] -fn pathvar_adds_to_path() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - path = ["/Users/mosquito/proboscis"] - "#, - )]) - .with_config(&file); - - let expected = "spam"; - let actual = sandbox.pipeline(r#" pathvar add spam; pathvar | first "#); - - assert_that!(actual, says().stdout(expected)); - }) -} - -#[test] -fn pathvar_adds_to_env_var() { - Playground::setup("hi_there", |_, sandbox| { - sandbox.with_env("BREAKFAST", &join_env_sep(&["egg", "sausage", "bacon"])); - - let expected = join_env_sep(&["spam", "egg", "sausage", "bacon"]); - let actual = sandbox.pipeline( - r#" - pathvar add -v BREAKFAST spam - $nu.env.BREAKFAST - "#, - ); - - assert_that!(actual, says().stdout(&expected)); - }) -} - -// pathvar append - -#[test] -fn pathvar_appends_to_path() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - path = ["/Users/mosquito/proboscis"] - "#, - )]) - .with_config(&file); - - let expected = "spam"; - let actual = sandbox.pipeline(r#" pathvar append spam; pathvar | last "#); - - assert_that!(actual, says().stdout(expected)); - }) -} - -#[test] -fn pathvar_appends_to_env_var() { - Playground::setup("hi_there", |_, sandbox| { - sandbox.with_env("BREAKFAST", &join_env_sep(&["egg", "sausage", "bacon"])); - - let expected = join_env_sep(&["egg", "sausage", "bacon", "spam"]); - let actual = sandbox.pipeline( - r#" - pathvar append -v BREAKFAST spam - $nu.env.BREAKFAST - "#, - ); - - assert_that!(actual, says().stdout(&expected)); - }) -} - -// pathvar remove - -#[test] -fn pathvar_removes_from_path() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - path = ["/Users/mosquito/proboscis", "spam"] - "#, - )]) - .with_config(&file); - - let expected = "/Users/mosquito/proboscis"; - let actual = sandbox.pipeline(r#" pathvar remove 1; pathvar | first "#); - - assert_that!(actual, says().stdout(expected)); - }) -} - -#[test] -fn pathvar_removes_from_env_var() { - Playground::setup("hi_there", |_, sandbox| { - sandbox.with_env( - "BREAKFAST", - &join_env_sep(&["egg", "sausage", "bacon", "spam"]), - ); - - let expected = join_env_sep(&["egg", "sausage", "bacon"]); - let actual = sandbox.pipeline( - r#" - pathvar remove -v BREAKFAST 3 - $nu.env.BREAKFAST - "#, - ); - - assert_that!(actual, says().stdout(&expected)); - }) -} - -// pathvar reset - -#[test] -fn pathvar_resets_path_from_config() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - path = ["/Users/andresrobalino/.volta/bin", "/Users/mosqueteros/bin"] - "#, - )]) - .with_config(&file) - .with_env( - nu_test_support::NATIVE_PATH_ENV_VAR, - &PathBuf::from("/Users/mosquito/proboscis").display_path(), - ); - - let expected = "/Users/andresrobalino/.volta/bin-/Users/mosqueteros/bin"; - let actual = sandbox.pipeline( - r#" - pathvar reset - pathvar | str collect '-' - "#, - ); - - assert_that!(actual, says().stdout(expected)); - }) -} - -#[test] -fn pathvar_resets_env_var_from_config() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - breakfast = ["egg", "sausage", "bacon"] - "#, - )]) - .with_config(&file) - .with_env( - "BREAKFAST", - &join_env_sep(&["egg", "sausage", "bacon", "spam"]), - ); - - let expected = "egg-sausage-bacon"; - let actual = sandbox.pipeline( - r#" - pathvar reset -v BREAKFAST - pathvar -v BREAKFAST | str collect '-' - "#, - ); - - assert_that!(actual, says().stdout(expected)); - }) -} - -// pathvar save - -#[test] -fn pathvar_saves_path_to_config() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - path = ["/Users/andresrobalino/.volta/bin", "/Users/mosqueteros/bin"] - "#, - )]) - .with_config(&file); - - let expected = "/Users/mosquito/proboscis"; - let actual = sandbox.pipeline( - r#" - pathvar append "/Users/mosquito/proboscis" - pathvar save - (config).path | last - "#, - ); - - assert_that!(actual, says().stdout(expected)); - }) -} - -#[test] -fn pathvar_saves_env_var_to_config() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - - breakfast = ["egg", "sausage", "bacon"] - "#, - )]) - .with_config(&file) - .with_env("BREAKFAST", "spam"); - - let expected = "spam"; - let actual = sandbox.pipeline( - r#" - pathvar save -v BREAKFAST - (config).breakfast | str collect '-' - "#, - ); - - assert_that!(actual, says().stdout(expected)); - }) -} - -#[test] -fn pathvar_saves_new_env_var_to_config() { - Playground::setup("hi_there", |dirs, sandbox| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - - sandbox - .with_files(vec![FileWithContent( - "config.toml", - r#" - skip_welcome_message = true - "#, - )]) - .with_config(&file) - .with_env("BREAKFAST", "spam"); - - let expected = "spam"; - let actual = sandbox.pipeline( - r#" - pathvar save -v BREAKFAST - (config).breakfast | str collect '-' - "#, - ); - - assert_that!(actual, says().stdout(expected)); - }) -} - -// test some errors - -#[test] -fn pathvar_error_non_existent_env_var() { - Playground::setup("hi_there", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - "pathvar -v EGGS_BACON_SPAM_SAUSAGE_SPAM_AND_SPAM_WITH_EXTRA_SPAM" - ); - - assert!(actual.err.contains("Error")); - assert!(actual.err.contains("not set")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/prepend.rs b/old_nushell/crates/nu-command/tests/commands/prepend.rs deleted file mode 100644 index 1c872becb..000000000 --- a/old_nushell/crates/nu-command/tests/commands/prepend.rs +++ /dev/null @@ -1,29 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn adds_a_row_to_the_beginning() { - Playground::setup("prepend_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - Andrés N. Robalino - Jonathan Turner - Yehuda Katz - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.txt - | lines - | prepend "pollo loco" - | nth 0 - "# - )); - - assert_eq!(actual.out, "pollo loco"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/random/bool.rs b/old_nushell/crates/nu-command/tests/commands/random/bool.rs deleted file mode 100644 index 862ba2840..000000000 --- a/old_nushell/crates/nu-command/tests/commands/random/bool.rs +++ /dev/null @@ -1,16 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn generates_a_bool() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random bool - "# - )); - - let output = actual.out; - let is_boolean_output = output == "true" || output == "false"; - - assert!(is_boolean_output); -} diff --git a/old_nushell/crates/nu-command/tests/commands/random/chars.rs b/old_nushell/crates/nu-command/tests/commands/random/chars.rs deleted file mode 100644 index c77f34736..000000000 --- a/old_nushell/crates/nu-command/tests/commands/random/chars.rs +++ /dev/null @@ -1,14 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn generates_chars_of_specified_length() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random chars -l 15 | size | get chars - "# - )); - - let result = actual.out; - assert_eq!(result, "15"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/random/decimal.rs b/old_nushell/crates/nu-command/tests/commands/random/decimal.rs deleted file mode 100644 index 0e78509a7..000000000 --- a/old_nushell/crates/nu-command/tests/commands/random/decimal.rs +++ /dev/null @@ -1,37 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn generates_an_decimal() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random decimal 42..43 - "# - )); - - assert!(actual.out.contains("42") || actual.out.contains("43")); -} - -#[test] -fn generates_55() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random decimal 55..55 - "# - )); - - assert!(actual.out.contains("55")); -} - -#[test] -fn generates_0() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random decimal ..<1 - "# - )); - - assert!(actual.out.contains('0')); -} diff --git a/old_nushell/crates/nu-command/tests/commands/random/dice.rs b/old_nushell/crates/nu-command/tests/commands/random/dice.rs deleted file mode 100644 index a056f07c9..000000000 --- a/old_nushell/crates/nu-command/tests/commands/random/dice.rs +++ /dev/null @@ -1,13 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn rolls_4_roll() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random dice -d 4 -s 10 | length - "# - )); - - assert_eq!(actual.out, "4"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/random/integer.rs b/old_nushell/crates/nu-command/tests/commands/random/integer.rs deleted file mode 100644 index 80cc8f5a2..000000000 --- a/old_nushell/crates/nu-command/tests/commands/random/integer.rs +++ /dev/null @@ -1,37 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn generates_an_integer() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random integer 42..43 - "# - )); - - assert!(actual.out.contains("42") || actual.out.contains("43")); -} - -#[test] -fn generates_55() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random integer 55..55 - "# - )); - - assert!(actual.out.contains("55")); -} - -#[test] -fn generates_0() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random integer ..<1 - "# - )); - - assert!(actual.out.contains('0')); -} diff --git a/old_nushell/crates/nu-command/tests/commands/random/mod.rs b/old_nushell/crates/nu-command/tests/commands/random/mod.rs deleted file mode 100644 index 9b3bf6eb8..000000000 --- a/old_nushell/crates/nu-command/tests/commands/random/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod bool; -mod chars; -mod decimal; -mod dice; -mod integer; -#[cfg(feature = "uuid_crate")] -mod uuid; diff --git a/old_nushell/crates/nu-command/tests/commands/random/uuid.rs b/old_nushell/crates/nu-command/tests/commands/random/uuid.rs deleted file mode 100644 index 725081383..000000000 --- a/old_nushell/crates/nu-command/tests/commands/random/uuid.rs +++ /dev/null @@ -1,16 +0,0 @@ -use nu_test_support::{nu, pipeline}; -use uuid_crate::Uuid; - -#[test] -fn generates_valid_uuid4() { - let actual = nu!( - cwd: ".", pipeline( - r#" - random uuid - "# - )); - - let result = Uuid::parse_str(actual.out.as_str()); - - assert!(result.is_ok()); -} diff --git a/old_nushell/crates/nu-command/tests/commands/range.rs b/old_nushell/crates/nu-command/tests/commands/range.rs deleted file mode 100644 index 7aa3e4e66..000000000 --- a/old_nushell/crates/nu-command/tests/commands/range.rs +++ /dev/null @@ -1,68 +0,0 @@ -use nu_test_support::fs::Stub::EmptyFile; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn selects_a_row() { - Playground::setup("range_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("tests.txt")]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | sort-by name - | range 0..0 - | get name - "# - )); - - assert_eq!(actual.out, "notes.txt"); - }); -} - -#[test] -fn selects_some_rows() { - Playground::setup("range_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("notes.txt"), - EmptyFile("tests.txt"), - EmptyFile("persons.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | range 1..2 - | length - "# - )); - - assert_eq!(actual.out, "2"); - }); -} - -#[test] -fn negative_indices() { - Playground::setup("range_test_negative_indices", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("notes.txt"), - EmptyFile("tests.txt"), - EmptyFile("persons.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | range (-1..) - | length - "# - )); - - assert_eq!(actual.out, "1"); - }); -} diff --git a/old_nushell/crates/nu-command/tests/commands/reduce.rs b/old_nushell/crates/nu-command/tests/commands/reduce.rs deleted file mode 100644 index dee4cd224..000000000 --- a/old_nushell/crates/nu-command/tests/commands/reduce.rs +++ /dev/null @@ -1,125 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn reduce_table_column() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "[{month:2,total:30}, {month:3,total:10}, {month:4,total:3}, {month:5,total:60}]" - | from json - | get total - | reduce -f 20 { $it + (math eval $"($acc)^1.05")} - | into string -d 1 - "# - ) - ); - - assert_eq!(actual.out, "180.6"); -} - -#[test] -fn reduce_table_column_with_path() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "[{month:2,total:30}, {month:3,total:10}, {month:4,total:3}, {month:5,total:60}]" - | from json - | reduce -f 20 { $it.total + (math eval $"($acc)^1.05")} - | into string -d 1 - "# - ) - ); - - assert_eq!(actual.out, "180.6"); -} - -#[test] -fn reduce_rows_example() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo a,b 1,2 3,4 - | split column , - | headers - | reduce -f 1.6 { $acc * ($it.a | str to-int) + ($it.b | str to-int) } - "# - ) - ); - - assert_eq!(actual.out, "14.8"); -} - -#[test] -fn reduce_numbered_example() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo one longest three bar - | reduce -n { if ($it.item | str length) > ($acc.item | str length) {echo $it} {echo $acc}} - | get index - "# - ) - ); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn reduce_numbered_integer_addition_example() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [1 2 3 4] - | reduce -n { $acc.item + $it.item } - | get item - "# - ) - ); - - assert_eq!(actual.out, "10"); -} - -#[test] -fn folding_with_tables() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [10 20 30 40] - | reduce -f [] { - with-env [value $it] { - echo $acc | append (10 * ($nu.env.value | str to-int)) - } - } - | math sum - "# - ) - ); - - assert_eq!(actual.out, "1000"); -} - -#[test] -fn error_reduce_fold_type_mismatch() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo a b c | reduce -f 0 { $acc + $it } - "# - ) - ); - - assert!(actual.err.contains("Coercion")); -} - -#[test] -fn error_reduce_empty() { - let actual = nu!( - cwd: ".", pipeline( - r#" - reduce { $acc + $it } - "# - ) - ); - - assert!(actual.err.contains("needs input")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/rename.rs b/old_nushell/crates/nu-command/tests/commands/rename.rs deleted file mode 100644 index f4ea04b66..000000000 --- a/old_nushell/crates/nu-command/tests/commands/rename.rs +++ /dev/null @@ -1,89 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn changes_the_column_name() { - Playground::setup("rename_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_cuatro_mosqueteros.txt", - r#" - Andrés N. Robalino - Jonathan Turner - Yehuda Katz - Jason Gedge - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_cuatro_mosqueteros.txt - | lines - | wrap name - | rename mosqueteros - | get mosqueteros - | length - "# - )); - - assert_eq!(actual.out, "4"); - }) -} - -#[test] -fn keeps_remaining_original_names_given_less_new_names_than_total_original_names() { - Playground::setup("rename_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_cuatro_mosqueteros.txt", - r#" - Andrés N. Robalino - Jonathan Turner - Yehuda Katz - Jason Gedge - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_cuatro_mosqueteros.txt - | lines - | wrap name - | default hit "arepa!" - | rename mosqueteros - | get hit - | length - "# - )); - - assert_eq!(actual.out, "4"); - }) -} - -#[test] -fn errors_if_no_columns_present() { - Playground::setup("rename_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_cuatro_mosqueteros.txt", - r#" - Andrés N. Robalino - Jonathan Turner - Yehuda Katz - Jason Gedge - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_cuatro_mosqueteros.txt - | lines - | rename mosqueteros - "# - )); - - assert!(actual.err.contains("no column names available")); - assert!(actual.err.contains("can't rename")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/reverse.rs b/old_nushell/crates/nu-command/tests/commands/reverse.rs deleted file mode 100644 index e994aa492..000000000 --- a/old_nushell/crates/nu-command/tests/commands/reverse.rs +++ /dev/null @@ -1,11 +0,0 @@ -use nu_test_support::nu; - -#[test] -fn can_get_reverse_first() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "ls | sort-by name | reverse | first 1 | get name | str trim " - ); - - assert_eq!(actual.out, "utf16.ini"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/rm.rs b/old_nushell/crates/nu-command/tests/commands/rm.rs deleted file mode 100644 index ae7e35828..000000000 --- a/old_nushell/crates/nu-command/tests/commands/rm.rs +++ /dev/null @@ -1,326 +0,0 @@ -use nu_test_support::fs::{files_exist_at, Stub::EmptyFile}; -use nu_test_support::nu; -use nu_test_support::playground::Playground; - -#[test] -fn removes_a_file() { - Playground::setup("rm_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("i_will_be_deleted.txt")]); - - nu!( - cwd: dirs.root(), - "rm rm_test_1/i_will_be_deleted.txt" - ); - - let path = dirs.test().join("i_will_be_deleted.txt"); - - assert!(!path.exists()); - }) -} - -#[test] -fn removes_files_with_wildcard() { - Playground::setup("rm_test_2", |dirs, sandbox| { - sandbox - .within("src") - .with_files(vec![ - EmptyFile("cli.rs"), - EmptyFile("lib.rs"), - EmptyFile("prelude.rs"), - ]) - .within("src/parser") - .with_files(vec![EmptyFile("parse.rs"), EmptyFile("parser.rs")]) - .within("src/parser/parse") - .with_files(vec![EmptyFile("token_tree.rs")]) - .within("src/parser/hir") - .with_files(vec![ - EmptyFile("baseline_parse.rs"), - EmptyFile("baseline_parse_tokens.rs"), - ]); - - nu!( - cwd: dirs.test(), - r#"rm "src/*/*/*.rs""# - ); - - assert!(!files_exist_at( - vec![ - "src/parser/parse/token_tree.rs", - "src/parser/hir/baseline_parse.rs", - "src/parser/hir/baseline_parse_tokens.rs" - ], - dirs.test() - )); - - assert_eq!( - Playground::glob_vec(&format!("{}/src/*/*/*.rs", dirs.test().display())), - Vec::::new() - ); - }) -} - -#[test] -fn removes_deeply_nested_directories_with_wildcard_and_recursive_flag() { - Playground::setup("rm_test_3", |dirs, sandbox| { - sandbox - .within("src") - .with_files(vec![ - EmptyFile("cli.rs"), - EmptyFile("lib.rs"), - EmptyFile("prelude.rs"), - ]) - .within("src/parser") - .with_files(vec![EmptyFile("parse.rs"), EmptyFile("parser.rs")]) - .within("src/parser/parse") - .with_files(vec![EmptyFile("token_tree.rs")]) - .within("src/parser/hir") - .with_files(vec![ - EmptyFile("baseline_parse.rs"), - EmptyFile("baseline_parse_tokens.rs"), - ]); - - nu!( - cwd: dirs.test(), - "rm -r src/*" - ); - - assert!(!files_exist_at( - vec!["src/parser/parse", "src/parser/hir"], - dirs.test() - )); - }) -} - -#[test] -fn removes_directory_contents_without_recursive_flag_if_empty() { - Playground::setup("rm_test_4", |dirs, _| { - nu!( - cwd: dirs.root(), - "rm rm_test_4" - ); - - assert!(!dirs.test().exists()); - }) -} - -#[test] -fn removes_directory_contents_with_recursive_flag() { - Playground::setup("rm_test_5", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - ]); - - nu!( - cwd: dirs.root(), - "rm rm_test_5 --recursive" - ); - - assert!(!dirs.test().exists()); - }) -} - -#[test] -fn errors_if_attempting_to_delete_a_directory_with_content_without_recursive_flag() { - Playground::setup("rm_test_6", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("some_empty_file.txt")]); - let actual = nu!( - cwd: dirs.root(), - "rm rm_test_6" - ); - - assert!(dirs.test().exists()); - assert!(actual.err.contains("cannot remove non-empty directory")); - }) -} - -#[test] -fn errors_if_attempting_to_delete_single_dot_as_argument() { - Playground::setup("rm_test_7", |dirs, _| { - let actual = nu!( - cwd: dirs.root(), - "rm ." - ); - - assert!(actual.err.contains("cannot remove any parent directory")); - }) -} - -#[test] -fn errors_if_attempting_to_delete_two_dot_as_argument() { - Playground::setup("rm_test_8", |dirs, _| { - let actual = nu!( - cwd: dirs.root(), - "rm .." - ); - - assert!(actual.err.contains("cannot remove any parent directory")); - }) -} - -#[test] -fn removes_multiple_directories() { - Playground::setup("rm_test_9", |dirs, sandbox| { - sandbox - .within("src") - .with_files(vec![EmptyFile("a.rs"), EmptyFile("b.rs")]) - .within("src/cli") - .with_files(vec![EmptyFile("c.rs"), EmptyFile("d.rs")]) - .within("test") - .with_files(vec![EmptyFile("a_test.rs"), EmptyFile("b_test.rs")]); - - nu!( - cwd: dirs.test(), - "rm src test --recursive" - ); - - assert_eq!( - Playground::glob_vec(&format!("{}/*", dirs.test().display())), - Vec::::new() - ); - }) -} - -#[test] -fn removes_multiple_files() { - Playground::setup("rm_test_10", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.txt"), - ]); - - nu!( - cwd: dirs.test(), - "rm yehuda.txt jonathan.txt andres.txt" - ); - - assert_eq!( - Playground::glob_vec(&format!("{}/*", dirs.test().display())), - Vec::::new() - ); - }) -} - -#[test] -fn removes_multiple_files_with_asterisks() { - Playground::setup("rm_test_11", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("andres.toml"), - ]); - - nu!( - cwd: dirs.test(), - "rm *.txt *.toml" - ); - - assert_eq!( - Playground::glob_vec(&format!("{}/*", dirs.test().display())), - Vec::::new() - ); - }) -} - -#[test] -fn allows_doubly_specified_file() { - Playground::setup("rm_test_12", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("yehuda.txt"), EmptyFile("jonathan.toml")]); - - let actual = nu!( - cwd: dirs.test(), - "rm *.txt yehuda* *.toml" - ); - - assert_eq!( - Playground::glob_vec(&format!("{}/*", dirs.test().display())), - Vec::::new() - ); - assert!(!actual.out.contains("error")) - }) -} - -#[test] -fn remove_files_from_two_parents_up_using_multiple_dots_and_glob() { - Playground::setup("rm_test_13", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("yehuda.txt"), - EmptyFile("jonathan.txt"), - EmptyFile("kevin.txt"), - ]); - - sandbox.within("foo").mkdir("bar"); - - nu!( - cwd: dirs.test().join("foo/bar"), - "rm .../*.txt" - ); - - assert!(!files_exist_at( - vec!["yehuda.txt", "jonathan.txt", "kevin.txt"], - dirs.test() - )); - }) -} - -#[test] -fn no_errors_if_attempting_to_delete_non_existent_file_with_f_flag() { - Playground::setup("rm_test_14", |dirs, _| { - let actual = nu!( - cwd: dirs.root(), - "rm -f non_existent_file.txt" - ); - - assert!(!actual.err.contains("no valid path")); - }) -} - -#[test] -fn rm_wildcard_keeps_dotfiles() { - Playground::setup("rm_test_15", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("foo"), EmptyFile(".bar")]); - - nu!( - cwd: dirs.test(), - r#"rm *"# - ); - - assert!(!files_exist_at(vec!["foo"], dirs.test())); - assert!(files_exist_at(vec![".bar"], dirs.test())); - }) -} - -#[test] -fn rm_wildcard_leading_dot_deletes_dotfiles() { - Playground::setup("rm_test_16", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("foo"), EmptyFile(".bar")]); - - nu!( - cwd: dirs.test(), - r#"rm .*"# - ); - - assert!(files_exist_at(vec!["foo"], dirs.test())); - assert!(!files_exist_at(vec![".bar"], dirs.test())); - }) -} - -#[test] -fn removes_files_with_case_sensitive_glob_matches_by_default() { - Playground::setup("glob_test", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("A0"), EmptyFile("a1")]); - - nu!( - cwd: dirs.root(), - "rm glob_test/A*" - ); - - let deleted_path = dirs.test().join("A0"); - let skipped_path = dirs.test().join("a1"); - - assert!(!deleted_path.exists()); - assert!(skipped_path.exists()); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/roll.rs b/old_nushell/crates/nu-command/tests/commands/roll.rs deleted file mode 100644 index d99a0c5dd..000000000 --- a/old_nushell/crates/nu-command/tests/commands/roll.rs +++ /dev/null @@ -1,166 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -mod rows { - use super::*; - - fn table() -> String { - pipeline( - r#" - echo [ - [service, status]; - - [ruby, DOWN] - [db, DOWN] - [nud, DOWN] - [expected, HERE] - ]"#, - ) - } - - #[test] - fn roll_down_by_default() { - let actual = nu!( - cwd: ".", - format!("{} | {}", table(), pipeline(r#" - roll - | first - | get status - "#))); - - assert_eq!(actual.out, "HERE"); - } - - #[test] - fn can_roll_up() { - let actual = nu!( - cwd: ".", - format!("{} | {}", table(), pipeline(r#" - roll up 3 - | first - | get status - "#))); - - assert_eq!(actual.out, "HERE"); - } -} - -mod columns { - use super::*; - - fn table() -> String { - pipeline( - r#" - echo [ - [commit_author, origin, stars]; - - [ "Andres", EC, amarillito] - [ "Darren", US, black] - [ "Jonathan", US, black] - [ "Yehuda", US, black] - [ "Jason", CA, gold] - ]"#, - ) - } - - #[test] - fn roll_left_by_default() { - let actual = nu!( - cwd: ".", - format!("{} | {}", table(), pipeline(r#" - roll column - | get - | str collect "-" - "#))); - - assert_eq!(actual.out, "origin-stars-commit_author"); - } - - #[test] - fn can_roll_in_the_opposite_direction() { - let actual = nu!( - cwd: ".", - format!("{} | {}", table(), pipeline(r#" - roll column 2 --opposite - | get - | str collect "-" - "#))); - - assert_eq!(actual.out, "origin-stars-commit_author"); - } - - struct ThirtieTwo<'a>(usize, &'a str); - - #[test] - fn can_roll_the_cells_only_keeping_the_header_names() { - let four_bitstring = bitstring_to_nu_row_pipeline("00000100"); - let expected_value = ThirtieTwo(32, "bit1-bit2-bit3-bit4-bit5-bit6-bit7-bit8"); - - let actual = nu!( - cwd: ".", - format!("{} | roll column 3 --opposite --cells-only | get | str collect '-' ", four_bitstring) - ); - - assert_eq!(actual.out, expected_value.1); - } - - #[test] - fn four_in_bitstring_left_shifted_with_three_bits_should_be_32_in_decimal() { - let four_bitstring = "00000100"; - let expected_value = ThirtieTwo(32, "00100000"); - - assert_eq!( - shift_three_bits_to_the_left_to_bitstring(four_bitstring), - expected_value.0.to_string() - ); - } - - fn shift_three_bits_to_the_left_to_bitstring(bits: &str) -> String { - // this pipeline takes the bitstring and outputs a nu row literal - // for example the number 4 in bitstring: - // - // input: 00000100 - // - // output: - // [ - // [Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8]; - // [ 0, 0, 0, 0, 0, 1, 0, 0] - // ] - // - let bitstring_as_nu_row_pipeline = bitstring_to_nu_row_pipeline(bits); - - // this pipeline takes the nu bitstring row literal, computes it's - // decimal value. - let nu_row_literal_bitstring_to_decimal_value_pipeline = pipeline( - r#" - pivot bit --ignore-titles - | get bit - | reverse - | each --numbered { - $it.item * (2 ** $it.index) - } - | math sum - "#, - ); - - nu!( - cwd: ".", - format!("{} | roll column 3 | {}", bitstring_as_nu_row_pipeline, nu_row_literal_bitstring_to_decimal_value_pipeline) - ).out - } - - fn bitstring_to_nu_row_pipeline(bits: &str) -> String { - format!( - "echo '{}' | {}", - bits, - pipeline( - r#" - split chars - | each { str to-int } - | rotate counter-clockwise _ - | reject _ - | rename bit1 bit2 bit3 bit4 bit5 bit6 bit7 bit8 - "# - ) - ) - } -} diff --git a/old_nushell/crates/nu-command/tests/commands/rotate.rs b/old_nushell/crates/nu-command/tests/commands/rotate.rs deleted file mode 100644 index 0432d89d5..000000000 --- a/old_nushell/crates/nu-command/tests/commands/rotate.rs +++ /dev/null @@ -1,83 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn counter_clockwise() { - let table = pipeline( - r#" - echo [ - [col1, col2, EXPECTED]; - - [---, "|||", XX1] - [---, "|||", XX2] - [---, "|||", XX3] - ] - "#, - ); - - let expected = nu!(cwd: ".", pipeline( - r#" - echo [ - [ Column0, Column1, Column2, Column3]; - - [ EXPECTED, XX1, XX2, XX3] - [ col2, "|||", "|||", "|||"] - [ col1, ---, ---, ---] - ] - | where Column0 == EXPECTED - | get Column1 Column2 Column3 - | str collect "-" - "#, - )); - - let actual = nu!( - cwd: ".", - format!("{} | {}", table, pipeline(r#" - rotate counter-clockwise - | where Column0 == EXPECTED - | get Column1 Column2 Column3 - | str collect "-" - "#))); - - assert_eq!(actual.out, expected.out); -} - -#[test] -fn clockwise() { - let table = pipeline( - r#" - echo [ - [col1, col2, EXPECTED]; - - [ ---, "|||", XX1] - [ ---, "|||", XX2] - [ ---, "|||", XX3] - ] - "#, - ); - - let expected = nu!(cwd: ".", pipeline( - r#" - echo [ - [ Column0, Column1, Column2, Column3]; - - [ ---, ---, ---, col1] - [ "|||", "|||", "|||", col2] - [ XX3, XX2, XX1, EXPECTED] - ] - | where Column3 == EXPECTED - | get Column0 Column1 Column2 - | str collect "-" - "#, - )); - - let actual = nu!( - cwd: ".", - format!("{} | {}", table, pipeline(r#" - rotate - | where Column3 == EXPECTED - | get Column0 Column1 Column2 - | str collect "-" - "#))); - - assert_eq!(actual.out, expected.out); -} diff --git a/old_nushell/crates/nu-command/tests/commands/save.rs b/old_nushell/crates/nu-command/tests/commands/save.rs deleted file mode 100644 index ff953bcfb..000000000 --- a/old_nushell/crates/nu-command/tests/commands/save.rs +++ /dev/null @@ -1,67 +0,0 @@ -use nu_test_support::fs::{file_contents, Stub::FileWithContent}; -use nu_test_support::nu; -use nu_test_support::playground::Playground; - -#[test] -fn figures_out_intelligently_where_to_write_out_with_metadata() { - Playground::setup("save_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "cargo_sample.toml", - r#" - [package] - name = "nu" - version = "0.1.1" - authors = ["Yehuda Katz "] - description = "A shell for the GitHub era" - license = "ISC" - edition = "2018" - "#, - )]); - - let subject_file = dirs.test().join("cargo_sample.toml"); - - nu!( - cwd: dirs.root(), - "open save_test_1/cargo_sample.toml | save" - ); - - let actual = file_contents(&subject_file); - assert!(actual.contains("0.1.1")); - }) -} - -#[test] -fn writes_out_csv() { - Playground::setup("save_test_2", |dirs, sandbox| { - sandbox.with_files(vec![]); - - let expected_file = dirs.test().join("cargo_sample.csv"); - - nu!( - cwd: dirs.root(), - r#"echo [[name, version, description, license, edition]; [nu, "0.14", "A new type of shell", "MIT", "2018"]] | save save_test_2/cargo_sample.csv"#, - ); - - let actual = file_contents(expected_file); - println!("{}", actual); - assert!(actual.contains("nu,0.14,A new type of shell,MIT,2018")); - }) -} - -#[test] -fn save_append_will_create_file_if_not_exists() { - Playground::setup("save_test_3", |dirs, sandbox| { - sandbox.with_files(vec![]); - - let expected_file = dirs.test().join("new-file.txt"); - - nu!( - cwd: dirs.root(), - r#"echo hello | save --raw --append save_test_3/new-file.txt"#, - ); - - let actual = file_contents(expected_file); - println!("{}", actual); - assert!(actual == "hello"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/select.rs b/old_nushell/crates/nu-command/tests/commands/select.rs deleted file mode 100644 index cb79f8142..000000000 --- a/old_nushell/crates/nu-command/tests/commands/select.rs +++ /dev/null @@ -1,122 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn regular_columns() { - let actual = nu!(cwd: ".", pipeline( - r#" - echo [ - [first_name, last_name, rusty_at, type]; - - [Andrés Robalino 10/11/2013 A] - [Jonathan Turner 10/12/2013 B] - [Yehuda Katz 10/11/2013 A] - ] - | select rusty_at last_name - | nth 0 - | get last_name - "# - )); - - assert_eq!(actual.out, "Robalino"); -} - -#[test] -fn complex_nested_columns() { - Playground::setup("select_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.json", - r#" - { - "nu": { - "committers": [ - {"name": "Andrés N. Robalino"}, - {"name": "Jonathan Turner"}, - {"name": "Yehuda Katz"} - ], - "releases": [ - {"version": "0.2"} - {"version": "0.8"}, - {"version": "0.9999999"} - ], - "0xATYKARNU": [ - ["Th", "e", " "], - ["BIG", " ", "UnO"], - ["punto", "cero"] - ] - } - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.json - | select nu."0xATYKARNU" nu.committers.name nu.releases.version - | where nu_releases_version > "0.8" - | get nu_releases_version - "# - )); - - assert_eq!(actual.out, "0.9999999"); - }) -} - -#[test] -fn allows_if_given_unknown_column_name_is_missing() { - let actual = nu!(cwd: ".", pipeline( - r#" - echo [ - [first_name, last_name, rusty_at, type]; - - [Andrés Robalino 10/11/2013 A] - [Jonathan Turner 10/12/2013 B] - [Yehuda Katz 10/11/2013 A] - ] - | select rrusty_at first_name - | length - "# - )); - - assert_eq!(actual.out, "3"); -} - -#[test] -fn column_names_with_spaces() { - let actual = nu!(cwd: ".", pipeline( - r#" - echo [ - ["first name", "last name"]; - - [Andrés Robalino] - [Andrés Jnth] - ] - | select "last name" - | get "last name" - | str collect " " - "# - )); - - assert_eq!(actual.out, "Robalino Jnth"); -} - -#[test] -fn ignores_duplicate_columns_selected() { - let actual = nu!(cwd: ".", pipeline( - r#" - echo [ - ["first name", "last name"]; - - [Andrés Robalino] - [Andrés Jnth] - ] - | select "first name" "last name" "first name" - | get - | str collect " " - "# - )); - - assert_eq!(actual.out, "first name last name"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/semicolon.rs b/old_nushell/crates/nu-command/tests/commands/semicolon.rs deleted file mode 100644 index 19e4a9cfe..000000000 --- a/old_nushell/crates/nu-command/tests/commands/semicolon.rs +++ /dev/null @@ -1,29 +0,0 @@ -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn semicolon_allows_lhs_to_complete() { - Playground::setup("create_test_1", |dirs, _sandbox| { - let actual = nu!( - cwd: dirs.test(), - "touch i_will_be_created_semi.txt; echo done" - ); - - let path = dirs.test().join("i_will_be_created_semi.txt"); - - assert!(path.exists()); - assert_eq!(actual.out, "done"); - }) -} - -#[test] -fn semicolon_lhs_error_stops_processing() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - where 1 1; echo done - "# - )); - - assert!(!actual.out.contains("done")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/skip/mod.rs b/old_nushell/crates/nu-command/tests/commands/skip/mod.rs deleted file mode 100644 index aa35de070..000000000 --- a/old_nushell/crates/nu-command/tests/commands/skip/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod until; -mod while_; diff --git a/old_nushell/crates/nu-command/tests/commands/skip/until.rs b/old_nushell/crates/nu-command/tests/commands/skip/until.rs deleted file mode 100644 index cdc89e5f7..000000000 --- a/old_nushell/crates/nu-command/tests/commands/skip/until.rs +++ /dev/null @@ -1,50 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn condition_is_met() { - Playground::setup("skip_until_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "caballeros.txt", - r#" - CHICKEN SUMMARY report date: April 29th, 2020 - -------------------------------------------------------------------- - Chicken Collection,29/04/2020,30/04/2020,31/04/2020, - Yellow Chickens,,, - Andrés,0,0,1 - Jonathan,0,0,1 - Jason,0,0,1 - Yehuda,0,0,1 - Blue Chickens,,, - Andrés,0,0,1 - Jonathan,0,0,1 - Jason,0,0,1 - Yehuda,0,0,2 - Red Chickens,,, - Andrés,0,0,1 - Jonathan,0,0,1 - Jason,0,0,1 - Yehuda,0,0,3 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open --raw caballeros.txt - | lines - | skip 2 - | split column ',' - | headers - | skip until "Chicken Collection" == "Red Chickens" - | skip 1 - | str to-int "31/04/2020" - | get "31/04/2020" - | math sum - "# - )); - - assert_eq!(actual.out, "6"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/skip/while_.rs b/old_nushell/crates/nu-command/tests/commands/skip/while_.rs deleted file mode 100644 index c0a55a7d6..000000000 --- a/old_nushell/crates/nu-command/tests/commands/skip/while_.rs +++ /dev/null @@ -1,50 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn condition_is_met() { - Playground::setup("skip_while_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "caballeros.txt", - r#" - CHICKEN SUMMARY report date: April 29th, 2020 - -------------------------------------------------------------------- - Chicken Collection,29/04/2020,30/04/2020,31/04/2020, - Yellow Chickens,,, - Andrés,0,0,1 - Jonathan,0,0,1 - Jason,0,0,1 - Yehuda,0,0,1 - Blue Chickens,,, - Andrés,0,0,1 - Jonathan,0,0,1 - Jason,0,0,1 - Yehuda,0,0,2 - Red Chickens,,, - Andrés,0,0,1 - Jonathan,0,0,1 - Jason,0,0,1 - Yehuda,0,0,3 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open --raw caballeros.txt - | lines - | skip 2 - | split column ',' - | headers - | skip while "Chicken Collection" != "Red Chickens" - | skip 1 - | str to-int "31/04/2020" - | get "31/04/2020" - | math sum - "# - )); - - assert_eq!(actual.out, "6"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/sort_by.rs b/old_nushell/crates/nu-command/tests/commands/sort_by.rs deleted file mode 100644 index 4eb3c98fe..000000000 --- a/old_nushell/crates/nu-command/tests/commands/sort_by.rs +++ /dev/null @@ -1,146 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn by_column() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml --raw - | lines - | skip 1 - | first 4 - | split column "=" - | sort-by Column1 - | skip 1 - | first 1 - | get Column1 - | str trim - "# - )); - - assert_eq!(actual.out, "description"); -} - -#[test] -fn by_invalid_column() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml --raw - | lines - | skip 1 - | first 4 - | split column "=" - | sort-by ColumnThatDoesNotExist - | skip 1 - | first 1 - | get Column1 - | str trim - "# - )); - - assert!(actual.err.contains("Can not find column to sort by")); - assert!(actual.err.contains("invalid column")); -} - -#[test] -fn by_invalid_types() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml --raw - | echo [1 "foo"] - | sort-by - "# - )); - - assert!(actual.err.contains("Not all values can be compared")); - assert!(actual - .err - .contains("Unable to sort values, as \"integer\" cannot compare against \"string\"")); -} - -#[test] -fn sort_primitive_values() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml --raw - | lines - | skip 1 - | first 6 - | sort-by - | first 1 - "# - )); - - assert_eq!(actual.out, "authors = [\"The Nu Project Contributors\"]"); -} - -#[test] -fn ls_sort_by_name_sensitive() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample-ls-output.json - | sort-by name - | select name - | to json - "# - )); - - let json_output = r#"[{"name":"B.txt"},{"name":"C"},{"name":"a.txt"}]"#; - - assert_eq!(actual.out, json_output); -} - -#[test] -fn ls_sort_by_name_insensitive() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample-ls-output.json - | sort-by -i name - | select name - | to json - "# - )); - - let json_output = r#"[{"name":"a.txt"},{"name":"B.txt"},{"name":"C"}]"#; - - assert_eq!(actual.out, json_output); -} - -#[test] -fn ls_sort_by_type_name_sensitive() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample-ls-output.json - | sort-by type name - | select name type - | to json - "# - )); - - let json_output = r#"[{"name":"C","type":"Dir"},{"name":"B.txt","type":"File"},{"name":"a.txt","type":"File"}]"#; - - assert_eq!(actual.out, json_output); -} - -#[test] -fn ls_sort_by_type_name_insensitive() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample-ls-output.json - | sort-by -i type name - | select name type - | to json - "# - )); - - let json_output = r#"[{"name":"C","type":"Dir"},{"name":"a.txt","type":"File"},{"name":"B.txt","type":"File"}]"#; - - assert_eq!(actual.out, json_output); -} diff --git a/old_nushell/crates/nu-command/tests/commands/source.rs b/old_nushell/crates/nu-command/tests/commands/source.rs deleted file mode 100644 index 473c3e6a3..000000000 --- a/old_nushell/crates/nu-command/tests/commands/source.rs +++ /dev/null @@ -1,146 +0,0 @@ -use nu_test_support::fs::{AbsolutePath, DisplayPath, Stub::FileWithContent}; -use nu_test_support::nu; -use nu_test_support::pipeline as input; -use nu_test_support::playground::{says, Playground}; - -use hamcrest2::assert_that; -use hamcrest2::prelude::*; - -#[should_panic] -#[test] -fn sources_also_files_under_custom_lib_dirs_path() { - Playground::setup("source_test_1", |dirs, nu| { - let file = AbsolutePath::new(dirs.test().join("config.toml")); - let library_path = AbsolutePath::new(dirs.test().join("lib")); - - nu.with_config(&file); - nu.with_files(vec![FileWithContent( - "config.toml", - &format!( - r#" - lib_dirs = ["{}"] - skip_welcome_message = true - "#, - library_path.display_path() - ), - )]); - - nu.within("lib").with_files(vec![FileWithContent( - "my_library.nu", - r#" - source my_library/main.nu - "#, - )]); - nu.within("lib/my_library").with_files(vec![FileWithContent( - "main.nu", - r#" - def hello [] { - echo "hello nu" - } - "#, - )]); - - assert_that!( - nu.pipeline(&input( - r#" - source my_library.nu ; - - hello - "#, - )), - says().stdout("hello nu") - ); - }) -} - -fn try_source_foo_with_double_quotes_in(testdir: &str, playdir: &str) { - Playground::setup(playdir, |dirs, sandbox| { - let testdir = String::from(testdir); - let mut foo_file = testdir.clone(); - foo_file.push_str("/foo.nu"); - - sandbox.mkdir(&testdir); - sandbox.with_files(vec![FileWithContent(&foo_file, "echo foo")]); - - let cmd = String::from("source ") + r#"""# + &foo_file + r#"""#; - - let actual = nu!(cwd: dirs.test(), &cmd); - - assert_eq!(actual.out, "foo"); - }); -} - -fn try_source_foo_with_single_quotes_in(testdir: &str, playdir: &str) { - Playground::setup(playdir, |dirs, sandbox| { - let testdir = String::from(testdir); - let mut foo_file = testdir.clone(); - foo_file.push_str("/foo.nu"); - - sandbox.mkdir(&testdir); - sandbox.with_files(vec![FileWithContent(&foo_file, "echo foo")]); - - let cmd = String::from("source ") + r#"'"# + &foo_file + r#"'"#; - - let actual = nu!(cwd: dirs.test(), &cmd); - - assert_eq!(actual.out, "foo"); - }); -} - -fn try_source_foo_without_quotes_in(testdir: &str, playdir: &str) { - Playground::setup(playdir, |dirs, sandbox| { - let testdir = String::from(testdir); - let mut foo_file = testdir.clone(); - foo_file.push_str("/foo.nu"); - - sandbox.mkdir(&testdir); - sandbox.with_files(vec![FileWithContent(&foo_file, "echo foo")]); - - let cmd = String::from("source ") + &foo_file; - - let actual = nu!(cwd: dirs.test(), &cmd); - - assert_eq!(actual.out, "foo"); - }); -} - -#[test] -fn sources_unicode_file_in_normal_dir() { - try_source_foo_with_single_quotes_in("foo", "source_test_1"); - try_source_foo_with_double_quotes_in("foo", "source_test_2"); - try_source_foo_without_quotes_in("foo", "source_test_3"); -} - -#[test] -fn sources_unicode_file_in_unicode_dir_without_spaces_1() { - try_source_foo_with_single_quotes_in("🚒", "source_test_4"); - try_source_foo_with_double_quotes_in("🚒", "source_test_5"); - try_source_foo_without_quotes_in("🚒", "source_test_6"); -} - -#[cfg(not(windows))] // ':' is not allowed in Windows paths -#[test] -fn sources_unicode_file_in_unicode_dir_without_spaces_2() { - try_source_foo_with_single_quotes_in(":fire_engine:", "source_test_7"); - try_source_foo_with_double_quotes_in(":fire_engine:", "source_test_8"); - try_source_foo_without_quotes_in(":fire_engine:", "source_test_9"); -} - -#[test] -fn sources_unicode_file_in_unicode_dir_with_spaces_1() { - try_source_foo_with_single_quotes_in("e-$ èрт🚒♞中片-j", "source_test_8"); - try_source_foo_with_double_quotes_in("e-$ èрт🚒♞中片-j", "source_test_9"); -} - -#[cfg(not(windows))] // ':' is not allowed in Windows paths -#[test] -fn sources_unicode_file_in_unicode_dir_with_spaces_2() { - try_source_foo_with_single_quotes_in("e-$ èрт:fire_engine:♞中片-j", "source_test_10"); - try_source_foo_with_double_quotes_in("e-$ èрт:fire_engine:♞中片-j", "source_test_11"); -} - -#[ignore] -#[test] -fn sources_unicode_file_in_non_utf8_dir() { - // How do I create non-UTF-8 path??? -} diff --git a/old_nushell/crates/nu-command/tests/commands/split_by.rs b/old_nushell/crates/nu-command/tests/commands/split_by.rs deleted file mode 100644 index bea39199e..000000000 --- a/old_nushell/crates/nu-command/tests/commands/split_by.rs +++ /dev/null @@ -1,54 +0,0 @@ -use nu_test_support::fs::Stub::{EmptyFile, FileWithContentToBeTrimmed}; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn splits() { - Playground::setup("split_by_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.csv - | group-by rusty_at - | split-by type - | get A."10/11/2013" - | length - "# - )); - - assert_eq!(actual.out, "2"); - }) -} - -#[test] -fn errors_if_no_table_given_as_input() { - Playground::setup("split_by_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - ls - | get name - | split-by type - "# - )); - - assert!(actual.err.contains("Expected table from pipeline")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/split_column.rs b/old_nushell/crates/nu-command/tests/commands/split_column.rs deleted file mode 100644 index cb591e500..000000000 --- a/old_nushell/crates/nu-command/tests/commands/split_column.rs +++ /dev/null @@ -1,28 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn to_column() { - Playground::setup("split_column_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.txt", - r#" - importer,shipper,tariff_item,name,origin - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.txt - | lines - | str trim - | split column "," - | get Column2 - "# - )); - - assert!(actual.out.contains("shipper")); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/split_row.rs b/old_nushell/crates/nu-command/tests/commands/split_row.rs deleted file mode 100644 index e7e7dd4f3..000000000 --- a/old_nushell/crates/nu-command/tests/commands/split_row.rs +++ /dev/null @@ -1,28 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn to_row() { - Playground::setup("split_row_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.txt", - r#" - importer,shipper,tariff_item,name,origin - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.txt - | lines - | str trim - | split row "," - | length - "# - )); - - assert!(actual.out.contains('5')); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/str_/collect.rs b/old_nushell/crates/nu-command/tests/commands/str_/collect.rs deleted file mode 100644 index 4ac56cc14..000000000 --- a/old_nushell/crates/nu-command/tests/commands/str_/collect.rs +++ /dev/null @@ -1,53 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn test_1() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 1..5 | into string | str collect - "# - ) - ); - - assert_eq!(actual.out, "12345"); -} - -#[test] -fn test_2() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [a b c d] | str collect "" - "# - ) - ); - - assert_eq!(actual.out, "abcd"); -} - -#[test] -fn construct_a_path() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [sample txt] | str collect "." - "# - ) - ); - - assert_eq!(actual.out, "sample.txt"); -} - -#[test] -fn sum_one_to_four() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 1..4 | into string | str collect "+" | math eval - "# - ) - ); - - assert!(actual.out.contains("10.0")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/str_/into_string.rs b/old_nushell/crates/nu-command/tests/commands/str_/into_string.rs deleted file mode 100644 index 9a50bcd6a..000000000 --- a/old_nushell/crates/nu-command/tests/commands/str_/into_string.rs +++ /dev/null @@ -1,158 +0,0 @@ -use nu_test_support::playground::{Dirs, Playground}; -use nu_test_support::{nu, pipeline}; - -#[test] -fn from_range() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 1..5 | into string | to json - "# - ) - ); - - assert_eq!(actual.out, "[\"1\",\"2\",\"3\",\"4\",\"5\"]"); -} - -#[test] -fn from_number() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 5 | into string - "# - ) - ); - - assert_eq!(actual.out, "5"); -} - -#[test] -fn from_decimal() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 1.5 | into string - "# - ) - ); - - assert_eq!(actual.out, "1.5"); -} - -#[test] -fn from_boolean() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo $true | into string - "# - ) - ); - - assert_eq!(actual.out, "true"); -} - -#[test] -fn from_string() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "one" | into string - "# - ) - ); - - assert_eq!(actual.out, "one"); -} - -#[test] -fn from_filename() { - Playground::setup("from_filename", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.toml", - r#" - [dependency] - name = "nu" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "ls sample.toml | get name | into string" - ); - - assert_eq!(actual.out, "sample.toml"); - }) -} - -#[test] -fn from_filesize() { - Playground::setup("from_filesize", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.toml", - r#" - [dependency] - name = "nu" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "ls sample.toml | get size | into string" - ); - - assert_eq!(actual.out, "25 B"); - }) -} - -#[test] -fn from_decimal_correct_trailing_zeros() { - let actual = nu!( - cwd: ".", pipeline( - r#" - = 1.23000 | into string -d 3 - "# - )); - - assert!(actual.out.contains("1.230")); -} - -#[test] -fn from_int_decimal_correct_trailing_zeros() { - let actual = nu!( - cwd: ".", pipeline( - r#" - = 1.00000 | into string -d 3 - "# - )); - - assert!(actual.out.contains("1.000")); -} - -#[test] -fn from_int_decimal_trim_trailing_zeros() { - let actual = nu!( - cwd: ".", pipeline( - r#" - = 1.00000 | into string | format "{$it} flat" - "# - )); - - assert!(actual.out.contains("1 flat")); // "1" would match "1.0" -} - -#[test] -fn from_table() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo '[{"name": "foo", "weight": 32.377}, {"name": "bar", "weight": 15.2}]' - | from json - | into string weight -d 2 - "# - )); - - assert!(actual.out.contains("32.38")); - assert!(actual.out.contains("15.20")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/str_/mod.rs b/old_nushell/crates/nu-command/tests/commands/str_/mod.rs deleted file mode 100644 index 6e159f943..000000000 --- a/old_nushell/crates/nu-command/tests/commands/str_/mod.rs +++ /dev/null @@ -1,356 +0,0 @@ -mod collect; - -use nu_test_support::fs::Stub::FileWithContent; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn trims() { - Playground::setup("str_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [dependency] - name = "nu " - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open sample.toml | str trim dependency.name | get dependency.name" - ); - - assert_eq!(actual.out, "nu"); - }) -} - -#[test] -fn error_trim_multiple_chars() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 'does it work now?!' | str trim -c '?!' - "# - ) - ); - - assert!(actual.err.contains("char")); -} - -#[test] -fn capitalizes() { - Playground::setup("str_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [dependency] - name = "nu" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open sample.toml | str capitalize dependency.name | get dependency.name" - ); - - assert_eq!(actual.out, "Nu"); - }) -} - -#[test] -fn downcases() { - Playground::setup("str_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [dependency] - name = "LIGHT" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open sample.toml | str downcase dependency.name | get dependency.name" - ); - - assert_eq!(actual.out, "light"); - }) -} - -#[test] -fn upcases() { - Playground::setup("str_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - name = "nushell" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open sample.toml | str upcase package.name | get package.name" - ); - - assert_eq!(actual.out, "NUSHELL"); - }) -} - -#[test] -fn camelcases() { - Playground::setup("str_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [dependency] - name = "THIS_IS_A_TEST" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open sample.toml | str camel-case dependency.name | get dependency.name" - ); - - assert_eq!(actual.out, "thisIsATest"); - }) -} - -#[test] -fn converts_to_int() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo '{number_as_string: "1"}' - | from json - | str to-int number_as_string - | rename number - | where number == 1 - | get number - - "# - )); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn converts_to_decimal() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo "3.1, 0.0415" - | split row "," - | str to-decimal - | math sum - "# - )); - - assert_eq!(actual.out, "3.1415"); -} - -#[test] -fn find_and_replaces() { - Playground::setup("str_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [fortune.teller] - phone = "1-800-KATZ" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | str find-replace KATZ "5289" fortune.teller.phone - | get fortune.teller.phone - "# - )); - - assert_eq!(actual.out, "1-800-5289"); - }) -} - -#[test] -fn find_and_replaces_without_passing_field() { - Playground::setup("str_test_7", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [fortune.teller] - phone = "1-800-KATZ" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | get fortune.teller.phone - | str find-replace KATZ "5289" - "# - )); - - assert_eq!(actual.out, "1-800-5289"); - }) -} - -#[test] -fn substrings_the_input() { - Playground::setup("str_test_8", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [fortune.teller] - phone = "1-800-ROBALINO" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | str substring 6,14 fortune.teller.phone - | get fortune.teller.phone - "# - )); - - assert_eq!(actual.out, "ROBALINO"); - }) -} - -#[test] -fn substring_errors_if_start_index_is_greater_than_end_index() { - Playground::setup("str_test_9", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [fortune.teller] - phone = "1-800-ROBALINO" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | str substring 6,5 fortune.teller.phone - "# - )); - - assert!(actual - .err - .contains("End must be greater than or equal to Start")) - }) -} - -#[test] -fn substrings_the_input_and_returns_the_string_if_end_index_exceeds_length() { - Playground::setup("str_test_10", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - name = "nu-arepas" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | str substring 0,999 package.name - | get package.name - "# - )); - - assert_eq!(actual.out, "nu-arepas"); - }) -} - -#[test] -fn substrings_the_input_and_returns_blank_if_start_index_exceeds_length() { - Playground::setup("str_test_11", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - name = "nu-arepas" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | str substring 50,999 package.name - | get package.name - "# - )); - - assert_eq!(actual.out, ""); - }) -} - -#[test] -fn substrings_the_input_and_treats_start_index_as_zero_if_blank_start_index_given() { - Playground::setup("str_test_12", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - name = "nu-arepas" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | str substring ,2 package.name - | get package.name - "# - )); - - assert_eq!(actual.out, "nu"); - }) -} - -#[test] -fn substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given() { - Playground::setup("str_test_13", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [package] - name = "nu-arepas" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.toml - | str substring 3, package.name - | get package.name - "# - )); - - assert_eq!(actual.out, "arepas"); - }) -} - -#[test] -fn str_reverse() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "nushell" | str reverse - "# - )); - - assert!(actual.out.contains("llehsun")); -} diff --git a/old_nushell/crates/nu-command/tests/commands/touch.rs b/old_nushell/crates/nu-command/tests/commands/touch.rs deleted file mode 100644 index affc1d14c..000000000 --- a/old_nushell/crates/nu-command/tests/commands/touch.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::nu; -use nu_test_support::playground::Playground; - -#[test] -fn creates_a_file_when_it_doesnt_exist() { - Playground::setup("create_test_1", |dirs, _sandbox| { - nu!( - cwd: dirs.test(), - "touch i_will_be_created.txt" - ); - - let path = dirs.test().join("i_will_be_created.txt"); - assert!(path.exists()); - }) -} - -#[test] -fn creates_two_files() { - Playground::setup("create_test_2", |dirs, _sandbox| { - nu!( - cwd: dirs.test(), - "touch a b" - ); - - let path = dirs.test().join("a"); - assert!(path.exists()); - - let path2 = dirs.test().join("b"); - assert!(path2.exists()); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/uniq.rs b/old_nushell/crates/nu-command/tests/commands/uniq.rs deleted file mode 100644 index 4f74a5af8..000000000 --- a/old_nushell/crates/nu-command/tests/commands/uniq.rs +++ /dev/null @@ -1,231 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn removes_duplicate_rows() { - Playground::setup("uniq_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.csv - | uniq - | length - - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn uniq_values() { - Playground::setup("uniq_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.csv - | select type - | uniq - | length - - "# - )); - - assert_eq!(actual.out, "2"); - }) -} - -#[test] -fn nested_json_structures() { - Playground::setup("uniq_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "nested_json_structures.json", - r#" - [ - { - "name": "this is duplicated", - "nesting": [ { "a": "a", "b": "b" }, - { "c": "c", "d": "d" } - ], - "can_be_ordered_differently": { - "array": [1, 2, 3, 4, 5], - "something": { "else": "works" } - } - }, - { - "can_be_ordered_differently": { - "something": { "else": "works" }, - "array": [1, 2, 3, 4, 5] - }, - "nesting": [ { "b": "b", "a": "a" }, - { "d": "d", "c": "c" } - ], - "name": "this is duplicated" - }, - { - "name": "this is unique", - "nesting": [ { "a": "b", "b": "a" }, - { "c": "d", "d": "c" } - ], - "can_be_ordered_differently": { - "array": [], - "something": { "else": "does not work" } - } - }, - { - "name": "this is unique", - "nesting": [ { "a": "a", "b": "b", "c": "c" }, - { "d": "d", "e": "e", "f": "f" } - ], - "can_be_ordered_differently": { - "array": [], - "something": { "else": "works" } - } - } - ] - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open nested_json_structures.json - | uniq - | length - - "# - )); - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn uniq_when_keys_out_of_order() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo '[{"a": "a", "b": [1,2,3]},{"b": [1,2,3], "a": "a"}]' - | from json - | uniq - | length - - "# - )); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn uniq_counting() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo '["A", "B", "A"]' - | from json - | wrap item - | uniq --count - | where item == A - | get count - "# - )); - assert_eq!(actual.out, "2"); - - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo '["A", "B", "A"]' - | from json - | wrap item - | uniq --count - | where item == B - | get count - "# - )); - assert_eq!(actual.out, "1"); -} - -#[test] -fn uniq_unique() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [1 2 3 4 1 5] - | uniq --unique - "# - )); - let expected = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [2 3 4 5] - "# - )); - print!("{}", actual.out); - print!("{}", expected.out); - assert_eq!(actual.out, expected.out); -} - -#[test] -fn uniq_simple_vals_ints() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [1 2 3 4 1 5] - | uniq - "# - )); - let expected = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [1 2 3 4 5] - "# - )); - print!("{}", actual.out); - print!("{}", expected.out); - assert_eq!(actual.out, expected.out); -} - -#[test] -fn uniq_simple_vals_strs() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [A B C A] - | uniq - "# - )); - let expected = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - echo [A B C] - "# - )); - print!("{}", actual.out); - print!("{}", expected.out); - assert_eq!(actual.out, expected.out); -} diff --git a/old_nushell/crates/nu-command/tests/commands/update.rs b/old_nushell/crates/nu-command/tests/commands/update.rs deleted file mode 100644 index 5506fb488..000000000 --- a/old_nushell/crates/nu-command/tests/commands/update.rs +++ /dev/null @@ -1,60 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn sets_the_column() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml - | update dev-dependencies.pretty_assertions "0.7.0" - | get dev-dependencies.pretty_assertions - "# - )); - - assert_eq!(actual.out, "0.7.0"); -} - -#[cfg(features = "inc")] -#[test] -fn sets_the_column_from_a_block_run_output() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml - | update dev-dependencies.pretty_assertions { open cargo_sample.toml | get dev-dependencies.pretty_assertions | inc --minor } - | get dev-dependencies.pretty_assertions - "# - )); - - assert_eq!(actual.out, "0.7.0"); -} - -#[test] -fn sets_the_column_from_a_block_full_stream_output() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - wrap content - | update content { open --raw cargo_sample.toml | lines | first 5 } - | get content.1 - | str contains "nu" - "# - )); - - assert_eq!(actual.out, "true"); -} - -#[test] -fn sets_the_column_from_a_subexpression() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - wrap content - | update content (open --raw cargo_sample.toml | lines | first 5) - | get content.1 - | str contains "nu" - "# - )); - - assert_eq!(actual.out, "true"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/where_.rs b/old_nushell/crates/nu-command/tests/commands/where_.rs deleted file mode 100644 index c4eb69c63..000000000 --- a/old_nushell/crates/nu-command/tests/commands/where_.rs +++ /dev/null @@ -1,166 +0,0 @@ -use nu_test_support::nu; - -#[cfg(feature = "sqlite")] -use nu_test_support::pipeline; - -#[test] -fn filters_by_unit_size_comparison() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "ls | where size > 1kib | sort-by size | get name | first 1 | str trim" - ); - - assert_eq!(actual.out, "cargo_sample.toml"); -} - -#[test] -fn filters_with_nothing_comparison() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r#"echo '[{"foo": 3}, {"foo": null}, {"foo": 4}]' | from json | get foo | compact | where $it > 1 | math sum"# - ); - - assert_eq!(actual.out, "7"); -} - -#[test] -fn where_in_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name in ["foo"] | get size | math sum"# - ); - - assert_eq!(actual.out, "5"); -} - -#[test] -fn where_not_in_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name not-in ["foo"] | get size | math sum"# - ); - - assert_eq!(actual.out, "4"); -} - -#[cfg(feature = "sqlite")] -#[test] -fn explicit_block_condition() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == ints - | get table_values - | first 4 - | where {= $it.z > 4200} - | get z - "# - )); - - assert_eq!(actual.out, "4253"); -} - -#[cfg(feature = "sqlite")] -#[test] -fn binary_operator_comparisons() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == ints - | get table_values - | first 4 - | where z > 4200 - | get z - "# - )); - - assert_eq!(actual.out, "4253"); - - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == ints - | get table_values - | first 4 - | where z >= 4253 - | get z - "# - )); - - assert_eq!(actual.out, "4253"); - - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == ints - | get table_values - | first 4 - | where z < 10 - | get z - "# - )); - - assert_eq!(actual.out, "1"); - - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == ints - | get table_values - | first 4 - | where z <= 1 - | get z - "# - )); - - assert_eq!(actual.out, "1"); - - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == ints - | get table_values - | where z != 1 - | first 1 - | get z - "# - )); - - assert_eq!(actual.out, "42"); -} - -#[cfg(feature = "sqlite")] -#[test] -fn contains_operator() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == strings - | get table_values - | where x =~ ell - | length - "# - )); - - assert_eq!(actual.out, "4"); - - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | where table_name == strings - | get table_values - | where x !~ ell - | length - "# - )); - - assert_eq!(actual.out, "2"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/which.rs b/old_nushell/crates/nu-command/tests/commands/which.rs deleted file mode 100644 index a16e571c5..000000000 --- a/old_nushell/crates/nu-command/tests/commands/which.rs +++ /dev/null @@ -1,96 +0,0 @@ -use nu_test_support::nu; - -#[test] -fn which_ls() { - let actual = nu!( - cwd: ".", - "which ls | get path | str trim" - ); - - assert_eq!(actual.out, "Nushell built-in command"); -} - -#[test] -fn which_alias_ls() { - let actual = nu!( - cwd: ".", - "alias ls = ls -a; which ls | get path | str trim" - ); - - assert_eq!(actual.out, "Nushell alias: ls -a"); -} - -#[test] -fn which_def_ls() { - let actual = nu!( - cwd: ".", - "def ls [] {echo def}; which ls | get path | str trim" - ); - - assert_eq!(actual.out, "Nushell custom command"); -} - -#[test] -fn correct_precedence_alias_def_custom() { - let actual = nu!( - cwd: ".", - "def ls [] {echo def}; alias ls = echo alias; which ls | get path | str trim" - ); - - assert_eq!(actual.out, "Nushell alias: echo alias"); -} - -#[test] -fn multiple_reports_for_alias_def_custom() { - let actual = nu!( - cwd: ".", - "def ls [] {echo def}; alias ls = echo alias; which -a ls | length" - ); - - let length: i32 = actual.out.parse().unwrap(); - assert!(length >= 3); -} - -// `get_aliases_with_name` and `get_custom_commands_with_name` don't return the correct count of -// values -// I suspect this is due to the ScopeFrame getting discarded at '}' and the command is then -// executed in the parent scope -// See: parse_definition, line 2187 for reference. -#[ignore] -#[test] -fn multiple_reports_of_multiple_alias() { - let actual = nu!( - cwd: ".", - "alias xaz = echo alias1; def helper [] {alias xaz = echo alias2; which -a xaz}; helper | length" - ); - - let length: i32 = actual.out.parse().unwrap(); - assert_eq!(length, 2); -} - -#[ignore] -#[test] -fn multiple_reports_of_multiple_defs() { - let actual = nu!( - cwd: ".", - "def xaz [] {echo def1}; def helper [] { def xaz [] { echo def2 }; which -a xaz }; helper | length" - ); - - let length: i32 = actual.out.parse().unwrap(); - assert_eq!(length, 2); -} - -//Fails due to ParserScope::add_definition -// frame.custom_commands.insert(name.clone(), block.clone()); -// frame.commands.insert(name, whole_stream_command(block)); -#[ignore] -#[test] -fn def_only_seen_once() { - let actual = nu!( - cwd: ".", - "def xaz [] {echo def1}; which -a xaz | length" - ); - //length is 2. One custom_command (def) one built in ("wrongly" added) - let length: i32 = actual.out.parse().unwrap(); - assert_eq!(length, 1); -} diff --git a/old_nushell/crates/nu-command/tests/commands/with_env.rs b/old_nushell/crates/nu-command/tests/commands/with_env.rs deleted file mode 100644 index 46f135235..000000000 --- a/old_nushell/crates/nu-command/tests/commands/with_env.rs +++ /dev/null @@ -1,100 +0,0 @@ -use nu_test_support::nu; - -#[test] -fn with_env_extends_environment() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "with-env [FOO BARRRR] {echo $nu.env} | get FOO" - ); - - assert_eq!(actual.out, "BARRRR"); -} - -#[test] -fn with_env_shorthand() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "FOO=BARRRR echo $nu.env | get FOO" - ); - - assert_eq!(actual.out, "BARRRR"); -} - -#[test] -fn shorthand_doesnt_reorder_arguments() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "FOO=BARRRR nu --testbin cococo first second" - ); - - assert_eq!(actual.out, "first second"); -} - -#[test] -fn with_env_shorthand_trims_quotes() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "FOO='BARRRR' echo $nu.env | get FOO" - ); - - assert_eq!(actual.out, "BARRRR"); -} - -#[test] -fn with_env_and_shorthand_same_result() { - let actual_shorthand = nu!( - cwd: "tests/fixtures/formats", - "FOO='BARRRR' echo $nu.env | get FOO" - ); - - let actual_normal = nu!( - cwd: "tests/fixtures/formats", - "with-env [FOO BARRRR] {echo $nu.env} | get FOO" - ); - - assert_eq!(actual_shorthand.out, actual_normal.out); -} - -#[test] -fn with_env_shorthand_nested_quotes() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "FOO='-arg \"hello world\"' echo $nu.env | get FOO" - ); - - assert_eq!(actual.out, "-arg \"hello world\""); -} - -#[test] -fn with_env_hides_variables_in_parent_scope() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r#" - let-env FOO = "1" - echo $nu.env.FOO - with-env [FOO $nothing] { - echo $nu.env.FOO - } - echo $nu.env.FOO - "# - ); - - assert_eq!(actual.out, "11"); - assert!(actual.err.contains("error")); - assert!(actual.err.contains("Unknown column")); -} - -#[test] -fn with_env_shorthand_can_not_hide_variables() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r#" - let-env FOO = "1" - echo $nu.env.FOO - FOO=$nothing echo $nu.env.FOO - echo $nu.env.FOO - "# - ); - - assert_eq!(actual.out, "1$nothing1"); -} diff --git a/old_nushell/crates/nu-command/tests/commands/wrap.rs b/old_nushell/crates/nu-command/tests/commands/wrap.rs deleted file mode 100644 index 968e5f125..000000000 --- a/old_nushell/crates/nu-command/tests/commands/wrap.rs +++ /dev/null @@ -1,61 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn wrap_rows_into_a_row() { - Playground::setup("wrap_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name,last_name - Andrés,Robalino - Jonathan,Turner - Yehuda,Katz - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.txt - | from csv - | wrap caballeros - | get caballeros - | nth 0 - | get last_name - "# - )); - - assert_eq!(actual.out, "Robalino"); - }) -} - -#[test] -fn wrap_rows_into_a_table() { - Playground::setup("wrap_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name,last_name - Andrés,Robalino - Jonathan,Turner - Yehuda,Katz - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.txt - | from csv - | get last_name - | wrap caballero - | nth 2 - | get caballero - "# - )); - - assert_eq!(actual.out, "Katz"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/commands/zip.rs b/old_nushell/crates/nu-command/tests/commands/zip.rs deleted file mode 100644 index 20aa6bf64..000000000 --- a/old_nushell/crates/nu-command/tests/commands/zip.rs +++ /dev/null @@ -1,77 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContent; -use nu_test_support::pipeline as input; -use nu_test_support::playground::{says, Playground}; - -use hamcrest2::assert_that; -use hamcrest2::prelude::*; - -const ZIP_POWERED_TEST_ASSERTION_SCRIPT: &str = r#" -def expect [ - left, - right, - --to-eq -] { - $left | zip { $right } | all? { - $it.name.0 == $it.name.1 && $it.commits.0 == $it.commits.1 - } -} - -def add-commits [n] { - each { - let contributor = $it; - let name = $it.name; - let commits = $it.commits; - - $contributor | merge { - [[commits]; [($commits + $n)]] - } - } -} -"#; - -#[test] -fn zips_two_tables() { - Playground::setup("zip_test_1", |dirs, nu| { - nu.with_files(vec![FileWithContent( - "zip_test.nu", - &format!("{}\n", ZIP_POWERED_TEST_ASSERTION_SCRIPT), - )]); - - assert_that!( - nu.pipeline(&input(&format!( - r#" - source {} ; - - let contributors = ([ - [name, commits]; - [andres, 10] - [ jt, 20] - ]); - - let actual = ($contributors | add-commits 10); - - expect $actual --to-eq [[name, commits]; [andres, 20] [jt, 30]] - "#, - dirs.test().join("zip_test.nu").display() - ))), - says().stdout("true") - ); - }) -} - -#[test] -fn zips_two_lists() { - Playground::setup("zip_test_2", |_, nu| { - assert_that!( - nu.pipeline(&input( - r#" - echo [0 2 4 6 8] | zip { [1 3 5 7 9] } - | flatten - | into string - | str collect '-' - "# - )), - says().stdout("0-1-2-3-4-5-6-7-8-9") - ); - }) -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/bson.rs b/old_nushell/crates/nu-command/tests/format_conversions/bson.rs deleted file mode 100644 index cd7969e0f..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/bson.rs +++ /dev/null @@ -1,17 +0,0 @@ -#[cfg(feature = "bson")] -#[test] -fn table_to_bson_and_back_into_table() { - use nu_test_support::{nu, pipeline}; - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.bson - | to bson - | from bson - | get root - | get 1.b - "# - )); - - assert_eq!(actual.out, "whel"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/csv.rs b/old_nushell/crates/nu-command/tests/format_conversions/csv.rs deleted file mode 100644 index 0cddd3eae..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/csv.rs +++ /dev/null @@ -1,209 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn table_to_csv_text_and_from_csv_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open caco3_plastics.csv | to csv | from csv | first 1 | get origin " - ); - - assert_eq!(actual.out, "SPAIN"); -} - -#[test] -fn table_to_csv_text() { - Playground::setup("filter_to_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "csv_text_sample.txt", - r#" - importer,shipper,tariff_item,name,origin - Plasticos Rival,Reverte,2509000000,Calcium carbonate,Spain - Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open csv_text_sample.txt - | lines - | str trim - | split column "," a b c d origin - | last 1 - | to csv - | lines - | nth 1 - "# - )); - - assert!(actual - .out - .contains("Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia")); - }) -} - -#[test] -fn table_to_csv_text_skipping_headers_after_conversion() { - Playground::setup("filter_to_csv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "csv_text_sample.txt", - r#" - importer,shipper,tariff_item,name,origin - Plasticos Rival,Reverte,2509000000,Calcium carbonate,Spain - Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open csv_text_sample.txt - | lines - | str trim - | split column "," a b c d origin - | last 1 - | to csv --noheaders - "# - )); - - assert!(actual - .out - .contains("Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia")); - }) -} - -#[test] -fn infers_types() { - Playground::setup("filter_from_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_cuatro_mosqueteros.csv", - r#" - first_name,last_name,rusty_luck,d - Andrés,Robalino,1,d - Jonathan,Turner,1,d - Yehuda,Katz,1,d - Jason,Gedge,1,d - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_cuatro_mosqueteros.csv - | where rusty_luck > 0 - | length - "# - )); - - assert_eq!(actual.out, "4"); - }) -} - -#[test] -fn from_csv_text_to_table() { - Playground::setup("filter_from_csv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name,last_name,rusty_luck - Andrés,Robalino,1 - Jonathan,Turner,1 - Yehuda,Katz,1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.txt - | from csv - | get rusty_luck - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn from_csv_text_with_separator_to_table() { - Playground::setup("filter_from_csv_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name;last_name;rusty_luck - Andrés;Robalino;1 - Jonathan;Turner;1 - Yehuda;Katz;1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.txt - | from csv --separator ';' - | get rusty_luck - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn from_csv_text_with_tab_separator_to_table() { - Playground::setup("filter_from_csv_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name last_name rusty_luck - Andrés Robalino 1 - Jonathan Turner 1 - Yehuda Katz 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_caballeros.txt - | from csv --separator '\t' - | get rusty_luck - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn from_csv_text_skipping_headers_to_table() { - Playground::setup("filter_from_csv_test_5", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.txt", - r#" - Andrés,Robalino,1 - Jonathan,Turner,1 - Yehuda,Katz,1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_amigos.txt - | from csv --noheaders - | get Column3 - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/eml.rs b/old_nushell/crates/nu-command/tests/format_conversions/eml.rs deleted file mode 100644 index 41acb13cb..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/eml.rs +++ /dev/null @@ -1,93 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -const TEST_CWD: &str = "tests/fixtures/formats"; - -// The To field in this email is just "to@example.com", which gets parsed out as the Address. The Name is empty. -#[test] -fn from_eml_get_to_field() { - let actual = nu!( - cwd: TEST_CWD, - pipeline( - r#" - open sample.eml - | get To - | get Address - "# - ) - ); - - assert_eq!(actual.out, "to@example.com"); - - let actual = nu!( - cwd: TEST_CWD, - pipeline( - r#" - open sample.eml - | get To - | get Name - "# - ) - ); - - assert_eq!(actual.out, ""); -} - -// The Reply-To field in this email is "replyto@example.com" , meaning both the Name and Address values are identical. -#[test] -fn from_eml_get_replyto_field() { - let actual = nu!( - cwd: TEST_CWD, - pipeline( - r#" - open sample.eml - | get Reply-To - | get Address - "# - ) - ); - - assert_eq!(actual.out, "replyto@example.com"); - - let actual = nu!( - cwd: TEST_CWD, - pipeline( - r#" - open sample.eml - | get Reply-To - | get Name - "# - ) - ); - - assert_eq!(actual.out, "replyto@example.com"); -} - -#[test] -fn from_eml_get_subject_field() { - let actual = nu!( - cwd: TEST_CWD, - pipeline( - r#" - open sample.eml - | get Subject - "# - ) - ); - - assert_eq!(actual.out, "Test Message"); -} - -#[test] -fn from_eml_get_another_header_field() { - let actual = nu!( - cwd: TEST_CWD, - pipeline( - r#" - open sample.eml - | get MIME-Version - "# - ) - ); - - assert_eq!(actual.out, "1.0"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/html.rs b/old_nushell/crates/nu-command/tests/format_conversions/html.rs deleted file mode 100644 index 36ebfff4a..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/html.rs +++ /dev/null @@ -1,91 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn out_html_simple() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 3 | to html - "# - )); - - assert_eq!( - actual.out, - r"3" - ); -} - -#[test] -fn out_html_partial() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 3 | to html -p - "# - )); - - assert_eq!( - actual.out, - "
3
" - ); -} - -#[test] -fn out_html_table() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo '{"name": "darren"}' | from json | to html - "# - )); - - assert_eq!( - actual.out, - r"
name
darren
" - ); -} - -#[test] -fn test_cd_html_color_flag_dark_false() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cd --help | to html --html_color - "# - ) - ); - assert_eq!( - actual.out, - r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
>
cd

Change to your home directory (alternate version)
>
cd
~

Change to the previous directory
>
cd
-

" - ); -} - -#[test] -fn test_no_color_flag() { - let actual = nu!( - cwd: ".", pipeline( - r#" - cd --help | to html --no_color - "# - ) - ); - assert_eq!( - actual.out, - r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
> cd

Change to your home directory (alternate version)
> cd ~

Change to the previous directory
> cd -

" - ); -} - -#[test] -fn test_html_color_where_flag_dark_false() { - let actual = nu!( - cwd: ".", pipeline( - r#" - where --help | to html --html_color - "# - ) - ); - assert_eq!( - actual.out, - r"Filter table to match the condition.

Usage:
> where <condition> {flags}

Parameters:
<condition> the condition that must match

Flags:
-h, --help: Display this help message

Examples:
List all files in the current directory with sizes greater than 2kb
> ls | where size > 2kb

List only the files in the current directory
>
ls
| where type == File

List all files with names that contain "Car"
>
ls
| where name =~ "Car"

List all files that were modified in the last two weeks
>
ls
| where modified <= 2wk

" - ); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/ics.rs b/old_nushell/crates/nu-command/tests/format_conversions/ics.rs deleted file mode 100644 index 7e727cb72..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/ics.rs +++ /dev/null @@ -1,99 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn infers_types() { - Playground::setup("filter_from_ics_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "calendar.ics", - r#" - BEGIN:VCALENDAR - PRODID:-//Google Inc//Google Calendar 70.9054//EN - VERSION:2.0 - BEGIN:VEVENT - DTSTART:20171007T200000Z - DTEND:20171007T233000Z - DTSTAMP:20200319T182138Z - UID:4l80f6dcovnriq38g57g07btid@google.com - CREATED:20170719T202915Z - DESCRIPTION: - LAST-MODIFIED:20170930T190808Z - LOCATION: - SEQUENCE:1 - STATUS:CONFIRMED - SUMMARY:Maryland Game - TRANSP:TRANSPARENT - END:VEVENT - BEGIN:VEVENT - DTSTART:20171002T010000Z - DTEND:20171002T020000Z - DTSTAMP:20200319T182138Z - UID:2v61g7mij4s7ieoubm3sjpun5d@google.com - CREATED:20171001T180103Z - DESCRIPTION: - LAST-MODIFIED:20171001T180103Z - LOCATION: - SEQUENCE:0 - STATUS:CONFIRMED - SUMMARY:Halloween Wars - TRANSP:OPAQUE - END:VEVENT - END:VCALENDAR - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open calendar.ics - | get events - | length - "# - )); - - assert_eq!(actual.out, "2"); - }) -} - -#[test] -fn from_ics_text_to_table() { - Playground::setup("filter_from_ics_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "calendar.txt", - r#" - BEGIN:VCALENDAR - BEGIN:VEVENT - DTSTART:20171007T200000Z - DTEND:20171007T233000Z - DTSTAMP:20200319T182138Z - UID:4l80f6dcovnriq38g57g07btid@google.com - CREATED:20170719T202915Z - DESCRIPTION: - LAST-MODIFIED:20170930T190808Z - LOCATION: - SEQUENCE:1 - STATUS:CONFIRMED - SUMMARY:Maryland Game - TRANSP:TRANSPARENT - END:VEVENT - END:VCALENDAR - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open calendar.txt - | from ics - | get events - | get properties - | where name == "SUMMARY" - | first - | get value - "# - )); - - assert_eq!(actual.out, "Maryland Game"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/json.rs b/old_nushell/crates/nu-command/tests/format_conversions/json.rs deleted file mode 100644 index 1cb059c14..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/json.rs +++ /dev/null @@ -1,100 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn table_to_json_text_and_from_json_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sgml_description.json - | to json - | from json - | get glossary.GlossDiv.GlossList.GlossEntry.GlossSee - "# - )); - - assert_eq!(actual.out, "markup"); -} - -#[test] -fn from_json_text_to_table() { - Playground::setup("filter_from_json_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.txt", - r#" - { - "katz": [ - {"name": "Yehuda", "rusty_luck": 1}, - {"name": "Jonathan", "rusty_luck": 1}, - {"name": "Andres", "rusty_luck": 1}, - {"name":"GorbyPuff", "rusty_luck": 1} - ] - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open katz.txt | from json | get katz | get rusty_luck | length " - ); - - assert_eq!(actual.out, "4"); - }) -} - -#[test] -fn from_json_text_recognizing_objects_independently_to_table() { - Playground::setup("filter_from_json_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.txt", - r#" - {"name": "Yehuda", "rusty_luck": 1} - {"name": "Jonathan", "rusty_luck": 1} - {"name": "Andres", "rusty_luck": 1} - {"name":"GorbyPuff", "rusty_luck": 3} - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open katz.txt - | from json -o - | where name == "GorbyPuff" - | get rusty_luck - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn table_to_json_text() { - Playground::setup("filter_to_json_test", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.txt", - r#" - JonAndrehudaTZ,3 - GorbyPuff,100 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open sample.txt - | lines - | split column "," name luck - | select name - | to json - | from json - | nth 0 - | get name - "# - )); - - assert_eq!(actual.out, "JonAndrehudaTZ"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/markdown.rs b/old_nushell/crates/nu-command/tests/format_conversions/markdown.rs deleted file mode 100644 index 15aef3275..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/markdown.rs +++ /dev/null @@ -1,98 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn md_empty() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[]; []] | from json | to md - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn md_empty_pretty() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo "{}" | from json | to md -p - "# - )); - - assert_eq!(actual.out, ""); -} - -#[test] -fn md_simple() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 3 | to md - "# - )); - - assert_eq!(actual.out, "3"); -} - -#[test] -fn md_simple_pretty() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo 3 | to md -p - "# - )); - - assert_eq!(actual.out, "3"); -} - -#[test] -fn md_table() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[name]; [jason]] | to md - "# - )); - - assert_eq!(actual.out, "|name||-||jason|"); -} - -#[test] -fn md_table_pretty() { - let actual = nu!( - cwd: ".", pipeline( - r#" - echo [[name]; [joseph]] | to md -p - "# - )); - - assert_eq!(actual.out, "| name || ------ || joseph |"); -} - -#[test] -fn md_combined() { - let actual = nu!( - cwd: ".", pipeline( - r#" - def title [] { - echo [[H1]; ["Nu top meals"]] - }; - - def meals [] { - echo [[dish]; [Arepa] [Taco] [Pizza]] - }; - - title - | append (meals) - | to md --per-element --pretty - "# - )); - - assert_eq!( - actual.out, - "# Nu top meals| dish || ----- || Arepa || Taco || Pizza |" - ); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/mod.rs b/old_nushell/crates/nu-command/tests/format_conversions/mod.rs deleted file mode 100644 index 5af12f9fc..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -mod bson; -mod csv; -mod eml; -mod html; -mod ics; -mod json; -mod markdown; -mod ods; -mod sqlite; -mod ssv; -mod toml; -mod tsv; -mod url; -mod vcf; -mod xlsx; -mod xml; -mod yaml; diff --git a/old_nushell/crates/nu-command/tests/format_conversions/ods.rs b/old_nushell/crates/nu-command/tests/format_conversions/ods.rs deleted file mode 100644 index 5d5ce7ca7..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/ods.rs +++ /dev/null @@ -1,30 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn from_ods_file_to_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample_data.ods - | get SalesOrders - | nth 4 - | get Column2 - "# - )); - - assert_eq!(actual.out, "Gill"); -} - -#[test] -fn from_ods_file_to_table_select_sheet() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample_data.ods --raw - | from ods -s ["SalesOrders"] - | get - "# - )); - - assert_eq!(actual.out, "SalesOrders"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/sqlite.rs b/old_nushell/crates/nu-command/tests/format_conversions/sqlite.rs deleted file mode 100644 index de6ce8ccf..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/sqlite.rs +++ /dev/null @@ -1,36 +0,0 @@ -#[cfg(feature = "sqlite")] -use nu_test_support::{nu, pipeline}; - -#[cfg(feature = "sqlite")] -#[test] -fn table_to_sqlite_and_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | to sqlite - | from sqlite - | get table_values - | nth 2 - | get x - "# - )); - - assert_eq!(actual.out, "hello"); -} - -#[cfg(feature = "sqlite")] -#[test] -fn table_to_sqlite_and_back_into_table_select_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.db - | to sqlite - | from sqlite -t [strings] - | get table_names - "# - )); - - assert_eq!(actual.out, "strings"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/ssv.rs b/old_nushell/crates/nu-command/tests/format_conversions/ssv.rs deleted file mode 100644 index 76d704578..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/ssv.rs +++ /dev/null @@ -1,95 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn from_ssv_text_to_table() { - Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "oc_get_svc.txt", - r#" - NAME LABELS SELECTOR IP PORT(S) - docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP - kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP - kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open oc_get_svc.txt - | from ssv - | nth 0 - | get IP - "# - )); - - assert_eq!(actual.out, "172.30.78.158"); - }) -} - -#[test] -fn from_ssv_text_to_table_with_separator_specified() { - Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "oc_get_svc.txt", - r#" - NAME LABELS SELECTOR IP PORT(S) - docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP - kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP - kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open oc_get_svc.txt - | from ssv --minimum-spaces 3 - | nth 0 - | get IP - "# - )); - - assert_eq!(actual.out, "172.30.78.158"); - }) -} - -#[test] -fn from_ssv_text_treating_first_line_as_data_with_flag() { - Playground::setup("filter_from_ssv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "oc_get_svc.txt", - r#" - docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP - kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP - kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP - "#, - )]); - - let aligned_columns = nu!( - cwd: dirs.test(), pipeline( - r#" - open oc_get_svc.txt - | from ssv --noheaders -a - | first - | get Column1 - "# - )); - - let separator_based = nu!( - cwd: dirs.test(), pipeline( - r#" - open oc_get_svc.txt - | from ssv --noheaders - | first - | get Column1 - - "# - )); - - assert_eq!(aligned_columns.out, separator_based.out); - assert_eq!(separator_based.out, "docker-registry"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/toml.rs b/old_nushell/crates/nu-command/tests/format_conversions/toml.rs deleted file mode 100644 index cffeed1c2..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/toml.rs +++ /dev/null @@ -1,16 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn table_to_toml_text_and_from_toml_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open cargo_sample.toml - | to toml - | from toml - | get package.name - "# - )); - - assert_eq!(actual.out, "nu"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/tsv.rs b/old_nushell/crates/nu-command/tests/format_conversions/tsv.rs deleted file mode 100644 index 066fa16ad..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/tsv.rs +++ /dev/null @@ -1,132 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn table_to_tsv_text_and_from_tsv_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open caco3_plastics.tsv | to tsv | from tsv | first 1 | get origin" - ); - - assert_eq!(actual.out, "SPAIN"); -} - -#[test] -fn table_to_tsv_text_and_from_tsv_text_back_into_table_using_csv_separator() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r"open caco3_plastics.tsv | to tsv | from csv --separator '\t' | first 1 | get origin" - ); - - assert_eq!(actual.out, "SPAIN"); -} - -#[test] -fn table_to_tsv_text() { - Playground::setup("filter_to_tsv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "tsv_text_sample.txt", - r#" - importer shipper tariff_item name origin - Plasticos Rival Reverte 2509000000 Calcium carbonate Spain - Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open tsv_text_sample.txt - | lines - | split column "\t" a b c d origin - | last 1 - | to tsv - | lines - | nth 1 - "# - )); - - assert!(actual.out.contains("Colombia")); - }) -} - -#[test] -fn table_to_tsv_text_skipping_headers_after_conversion() { - Playground::setup("filter_to_tsv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "tsv_text_sample.txt", - r#" - importer shipper tariff_item name origin - Plasticos Rival Reverte 2509000000 Calcium carbonate Spain - Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open tsv_text_sample.txt - | lines - | split column "\t" a b c d origin - | last 1 - | to tsv --noheaders - "# - )); - - assert!(actual.out.contains("Colombia")); - }) -} - -#[test] -fn from_tsv_text_to_table() { - Playground::setup("filter_from_tsv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.txt", - r#" - first Name Last Name rusty_luck - Andrés Robalino 1 - Jonathan Turner 1 - Yehuda Katz 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_amigos.txt - | from tsv - | get rusty_luck - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} - -#[test] -fn from_tsv_text_skipping_headers_to_table() { - Playground::setup("filter_from_tsv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.txt", - r#" - Andrés Robalino 1 - Jonathan Turner 1 - Yehuda Katz 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open los_tres_amigos.txt - | from tsv --noheaders - | get Column3 - | length - "# - )); - - assert_eq!(actual.out, "3"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/url.rs b/old_nushell/crates/nu-command/tests/format_conversions/url.rs deleted file mode 100644 index 2187fa382..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/url.rs +++ /dev/null @@ -1,16 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn can_encode_and_decode_urlencoding() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample.url - | to url - | from url - | get cheese - "# - )); - - assert_eq!(actual.out, "comté"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/vcf.rs b/old_nushell/crates/nu-command/tests/format_conversions/vcf.rs deleted file mode 100644 index 9d03dd625..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/vcf.rs +++ /dev/null @@ -1,82 +0,0 @@ -use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; -use nu_test_support::playground::Playground; -use nu_test_support::{nu, pipeline}; - -#[test] -fn infers_types() { - Playground::setup("filter_from_vcf_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "contacts.vcf", - r#" - BEGIN:VCARD - VERSION:3.0 - FN:John Doe - N:Doe;John;;; - EMAIL;TYPE=INTERNET:john.doe99@gmail.com - item1.ORG:'Alpine Ski Resort' - item1.X-ABLabel:Other - item2.TITLE:'Ski Instructor' - item2.X-ABLabel:Other - BDAY:19001106 - NOTE:Facebook: john.doe.3\nWebsite: \nHometown: Cleveland\, Ohio - CATEGORIES:myContacts - END:VCARD - BEGIN:VCARD - VERSION:3.0 - FN:Alex Smith - N:Smith;Alex;;; - TEL;TYPE=CELL:(890) 123-4567 - CATEGORIES:Band,myContacts - END:VCARD - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open contacts.vcf - | length - "# - )); - - assert_eq!(actual.out, "2"); - }) -} - -#[test] -fn from_vcf_text_to_table() { - Playground::setup("filter_from_vcf_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "contacts.txt", - r#" - BEGIN:VCARD - VERSION:3.0 - FN:John Doe - N:Doe;John;;; - EMAIL;TYPE=INTERNET:john.doe99@gmail.com - item1.ORG:'Alpine Ski Resort' - item1.X-ABLabel:Other - item2.TITLE:'Ski Instructor' - item2.X-ABLabel:Other - BDAY:19001106 - NOTE:Facebook: john.doe.3\nWebsite: \nHometown: Cleveland\, Ohio - CATEGORIES:myContacts - END:VCARD - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), pipeline( - r#" - open contacts.txt - | from vcf - | get properties - | where name == "EMAIL" - | first - | get value - "# - )); - - assert_eq!(actual.out, "john.doe99@gmail.com"); - }) -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/xlsx.rs b/old_nushell/crates/nu-command/tests/format_conversions/xlsx.rs deleted file mode 100644 index 36b3aca17..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/xlsx.rs +++ /dev/null @@ -1,30 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn from_excel_file_to_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample_data.xlsx - | get SalesOrders - | nth 4 - | get Column2 - "# - )); - - assert_eq!(actual.out, "Gill"); -} - -#[test] -fn from_excel_file_to_table_select_sheet() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open sample_data.xlsx --raw - | from xlsx -s ["SalesOrders"] - | get - "# - )); - - assert_eq!(actual.out, "SalesOrders"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/xml.rs b/old_nushell/crates/nu-command/tests/format_conversions/xml.rs deleted file mode 100644 index 068296195..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/xml.rs +++ /dev/null @@ -1,16 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn table_to_xml_text_and_from_xml_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open jonathan.xml - | to xml - | from xml - | get rss.children.channel.children.0.item.children.0.guid.attributes.isPermaLink - "# - )); - - assert_eq!(actual.out, "true"); -} diff --git a/old_nushell/crates/nu-command/tests/format_conversions/yaml.rs b/old_nushell/crates/nu-command/tests/format_conversions/yaml.rs deleted file mode 100644 index 887256637..000000000 --- a/old_nushell/crates/nu-command/tests/format_conversions/yaml.rs +++ /dev/null @@ -1,16 +0,0 @@ -use nu_test_support::{nu, pipeline}; - -#[test] -fn table_to_yaml_text_and_from_yaml_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", pipeline( - r#" - open appveyor.yml - | to yaml - | from yaml - | get environment.global.PROJECT_NAME - "# - )); - - assert_eq!(actual.out, "nushell"); -} diff --git a/old_nushell/crates/nu-command/tests/main.rs b/old_nushell/crates/nu-command/tests/main.rs deleted file mode 100644 index bd02ef653..000000000 --- a/old_nushell/crates/nu-command/tests/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -use quickcheck_macros::quickcheck; - -mod commands; -mod format_conversions; - -use nu_engine::EvaluationContext; - -#[quickcheck] -fn quickcheck_parse(data: String) -> bool { - let (tokens, err) = nu_parser::lex(&data, 0, nu_parser::NewlineMode::Normal); - let (lite_block, err2) = nu_parser::parse_block(tokens); - - if err.is_none() && err2.is_none() { - let context = EvaluationContext::basic(); - let _ = nu_parser::classify_block(&lite_block, &context.scope); - } - true -} diff --git a/old_nushell/crates/nu-completion/Cargo.toml b/old_nushell/crates/nu-completion/Cargo.toml deleted file mode 100644 index 04153adf2..000000000 --- a/old_nushell/crates/nu-completion/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -authors = ["The Nu Project Contributors"] -description = "Completions for nushell" -edition = "2018" -license = "MIT" -name = "nu-completion" -version = "0.43.0" - -[lib] -doctest = false - -[dependencies] -nu-engine = { version = "0.43.0", path="../nu-engine" } -nu-data = { version = "0.43.0", path="../nu-data" } -nu-parser = { version = "0.43.0", path="../nu-parser" } -nu-path = { version = "0.43.0", path="../nu-path" } -nu-protocol = { version = "0.43.0", path="../nu-protocol" } -nu-source = { version = "0.43.0", path="../nu-source" } -nu-test-support = { version = "0.43.0", path="../nu-test-support" } -indexmap = { version="1.6.1", features=["serde-1"] } - -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -is_executable = "1.0.1" - -[dev-dependencies] -parking_lot = "0.11.1" diff --git a/old_nushell/crates/nu-completion/src/command.rs b/old_nushell/crates/nu-completion/src/command.rs deleted file mode 100644 index 7db121de2..000000000 --- a/old_nushell/crates/nu-completion/src/command.rs +++ /dev/null @@ -1,91 +0,0 @@ -use super::matchers::Matcher; -use crate::{Completer, CompletionContext, Suggestion}; -use indexmap::set::IndexSet; -#[cfg(not(target_arch = "wasm32"))] -use is_executable::IsExecutable; -use nu_test_support::NATIVE_PATH_ENV_VAR; -use std::iter::FromIterator; -use std::path::Path; - -pub struct CommandCompleter; - -impl Completer for CommandCompleter -where - Context: CompletionContext, -{ - fn complete(&self, ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec { - let registry = ctx.signature_registry(); - let mut commands: IndexSet = IndexSet::from_iter(registry.names()); - - // Command suggestions can come from three possible sets: - // 1. internal command names, - // 2. external command names relative to PATH env var, and - // 3. any other executable (that matches what's been typed so far). - - let path_executables = find_path_executables().unwrap_or_default(); - - // TODO quote these, if necessary - commands.extend(path_executables); - - let mut suggestions: Vec<_> = commands - .into_iter() - .filter(|v| matcher.matches(partial, v)) - .map(|v| Suggestion { - replacement: v.clone(), - display: v, - }) - .collect(); - - if !partial.is_empty() { - let path_completer = crate::path::PathCompleter; - let path_results = path_completer.path_suggestions(partial, matcher); - let iter = path_results.into_iter().filter_map(|path_suggestion| { - let path = path_suggestion.path; - if path.is_dir() || is_executable(&path) { - Some(path_suggestion.suggestion) - } else { - None - } - }); - - suggestions.extend(iter); - } - - suggestions - } -} - -#[cfg(not(target_arch = "wasm32"))] -fn is_executable(path: &Path) -> bool { - // This call to a crate essentially checks the PATHEXT on Windows and does some - // low level WinAPI calls to determine if the file is executable. It seems quite - // a bit faster than calling path.metadata(). - // On Unix, this checks the file metadata. The underlying code traverses symlinks. - path.is_executable() -} - -#[cfg(target_arch = "wasm32")] -fn is_executable(_path: &Path) -> bool { - false -} - -// TODO cache these, but watch for changes to PATH -fn find_path_executables() -> Option> { - let path_var = std::env::var_os(NATIVE_PATH_ENV_VAR)?; - let paths: Vec<_> = std::env::split_paths(&path_var).collect(); - - let mut executables: IndexSet = IndexSet::new(); - for path in paths { - if let Ok(mut contents) = std::fs::read_dir(path) { - while let Some(Ok(item)) = contents.next() { - if is_executable(&item.path()) { - if let Ok(name) = item.file_name().into_string() { - executables.insert(name); - } - } - } - } - } - - Some(executables) -} diff --git a/old_nushell/crates/nu-completion/src/completer.rs b/old_nushell/crates/nu-completion/src/completer.rs deleted file mode 100644 index def926f02..000000000 --- a/old_nushell/crates/nu-completion/src/completer.rs +++ /dev/null @@ -1,191 +0,0 @@ -use std::borrow::Cow; - -use nu_parser::NewlineMode; -use nu_source::{Span, Tag}; - -use crate::command::CommandCompleter; -use crate::engine; -use crate::flag::FlagCompleter; -use crate::matchers; -use crate::matchers::Matcher; -use crate::path::{PathCompleter, PathSuggestion}; -use crate::variable::VariableCompleter; -use crate::{Completer, CompletionContext, Suggestion}; - -pub struct NuCompleter {} - -impl NuCompleter {} - -impl NuCompleter { - pub fn complete( - &self, - line: &str, - pos: usize, - context: &Context, - ) -> (usize, Vec) { - use engine::LocationType; - - let tokens = nu_parser::lex(line, 0, NewlineMode::Normal).0; - - let locations = Some(nu_parser::parse_block(tokens).0) - .map(|block| nu_parser::classify_block(&block, context.scope())) - .map(|(block, _)| engine::completion_location(line, &block, pos)) - .unwrap_or_default(); - - let matcher = nu_data::config::config(Tag::unknown()) - .ok() - .and_then(|cfg| cfg.get("line_editor").cloned()) - .and_then(|le| { - le.row_entries() - .find(|&(idx, _value)| idx == "completion_match_method") - .and_then(|(_idx, value)| value.as_string().ok()) - }) - .unwrap_or_else(String::new); - - let matcher = matcher.as_str(); - let matcher: &dyn Matcher = match matcher { - "case-insensitive" => &matchers::case_insensitive::Matcher, - "case-sensitive" => &matchers::case_sensitive::Matcher, - #[cfg(target_os = "windows")] - _ => &matchers::case_insensitive::Matcher, - #[cfg(not(target_os = "windows"))] - _ => &matchers::case_sensitive::Matcher, - }; - - if locations.is_empty() { - (pos, Vec::new()) - } else { - let mut pos = locations[0].span.start(); - - for location in &locations { - if location.span.start() < pos { - pos = location.span.start(); - } - } - let suggestions = locations - .into_iter() - .flat_map(|location| { - let partial = location.span.slice(line).to_string(); - match location.item { - LocationType::Command => { - let command_completer = CommandCompleter; - command_completer.complete(context, &partial, matcher.to_owned()) - } - - LocationType::Flag(cmd) => { - let flag_completer = FlagCompleter { cmd }; - flag_completer.complete(context, &partial, matcher.to_owned()) - } - - LocationType::Argument(cmd, _arg_name) => { - let path_completer = PathCompleter; - let prepend = Span::new(pos, location.span.start()).slice(line); - - const QUOTE_CHARS: &[char] = &['\'', '"']; - - // TODO Find a better way to deal with quote chars. Can the completion - // engine relay this back to us? Maybe have two spans: inner and - // outer. The former is what we want to complete, the latter what - // we'd need to replace. - let (quote_char, partial) = if partial.starts_with(QUOTE_CHARS) { - let (head, tail) = partial.split_at(1); - (Some(head), tail.to_string()) - } else { - (None, partial) - }; - - let (mut partial, quoted) = if let Some(quote_char) = quote_char { - if partial.ends_with(quote_char) { - (partial[..partial.len() - 1].to_string(), true) - } else { - (partial, false) - } - } else { - (partial, false) - }; - - partial = partial.split('"').collect::>().join(""); - let completed_paths = - path_completer.path_suggestions(&partial, matcher); - match cmd.as_deref().unwrap_or("") { - "cd" => select_directory_suggestions(completed_paths), - _ => completed_paths, - } - .into_iter() - .map(|s| Suggestion { - replacement: format!( - "{}{}", - prepend, - requote(s.suggestion.replacement, quoted) - ), - display: s.suggestion.display, - }) - .collect() - } - - LocationType::Variable => { - let variable_completer = VariableCompleter; - variable_completer.complete(context, &partial, matcher.to_owned()) - } - } - }) - .collect(); - - (pos, suggestions) - } - } -} - -fn select_directory_suggestions(completed_paths: Vec) -> Vec { - completed_paths - .into_iter() - .filter(|suggestion| { - suggestion - .path - .metadata() - .map(|md| md.is_dir()) - .unwrap_or(false) - }) - .collect() -} - -fn requote(orig_value: String, previously_quoted: bool) -> String { - let value: Cow = { - #[cfg(feature = "rustyline-support")] - { - rustyline::completion::unescape(&orig_value, Some('\\')) - } - #[cfg(not(feature = "rustyline-support"))] - { - orig_value.into() - } - }; - - let mut quotes = vec!['"', '\'']; - let mut should_quote = false; - for c in value.chars() { - if c.is_whitespace() || c == '#' { - should_quote = true; - } else if let Some(index) = quotes.iter().position(|q| *q == c) { - should_quote = true; - quotes.swap_remove(index); - } - } - - if should_quote { - if quotes.is_empty() { - // TODO we don't really have an escape character, so there isn't a great option right - // now. One possibility is `{{(char backtick)}}` - value.to_string() - } else { - let quote = quotes[0]; - if previously_quoted { - format!("{}{}", quote, value) - } else { - format!("{}{}{}", quote, value, quote) - } - } - } else { - value.to_string() - } -} diff --git a/old_nushell/crates/nu-completion/src/engine.rs b/old_nushell/crates/nu-completion/src/engine.rs deleted file mode 100644 index 67158548e..000000000 --- a/old_nushell/crates/nu-completion/src/engine.rs +++ /dev/null @@ -1,497 +0,0 @@ -use nu_protocol::hir::*; -use nu_source::{Span, Spanned, SpannedItem}; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum LocationType { - Command, - Flag(String), // command name - Argument(Option, Option), // command name, argument name - Variable, -} - -pub type CompletionLocation = Spanned; - -// TODO The below is very similar to shapes / expression_to_flat_shape. Check back October 2020 -// to see if we're close enough to just make use of those. - -struct Flatten<'s> { - line: &'s str, - command: Option, - flag: Option, -} - -impl<'s> Flatten<'s> { - /// Converts a SpannedExpression into a completion location for use in NuCompleter - fn expression(&self, e: &SpannedExpression) -> Vec { - match &e.expr { - Expression::Block(block) => self.completion_locations(block), - Expression::Subexpression(block) => self.completion_locations(block), - Expression::List(exprs) => exprs.iter().flat_map(|v| self.expression(v)).collect(), - Expression::Table(headers, cells) => headers - .iter() - .flat_map(|v| self.expression(v)) - .chain( - cells - .iter() - .flat_map(|v| v.iter().flat_map(|v| self.expression(v))), - ) - .collect(), - Expression::Command => vec![LocationType::Command.spanned(e.span)], - Expression::FullColumnPath(path) => self.expression(&path.head), - Expression::Variable(_, _) => vec![LocationType::Variable.spanned(e.span)], - - Expression::Boolean(_) - | Expression::FilePath(_) - | Expression::Literal(Literal::ColumnPath(_)) - | Expression::Literal(Literal::GlobPattern(_)) - | Expression::Literal(Literal::Number(_)) - | Expression::Literal(Literal::Size(_, _)) - | Expression::Literal(Literal::String(_)) => { - vec![ - LocationType::Argument(self.command.clone(), self.flag.clone()).spanned(e.span), - ] - } - - Expression::Binary(binary) => { - let mut result = Vec::new(); - result.append(&mut self.expression(&binary.left)); - result.append(&mut self.expression(&binary.right)); - result - } - Expression::Range(range) => { - let mut result = Vec::new(); - if let Some(left) = &range.left { - result.append(&mut self.expression(left)); - } - if let Some(right) = &range.right { - result.append(&mut self.expression(right)); - } - result - } - - Expression::ExternalWord - | Expression::ExternalCommand(_) - | Expression::Synthetic(_) - | Expression::Literal(Literal::Operator(_)) - | Expression::Literal(Literal::Bare(_)) - | Expression::Garbage => Vec::new(), - } - } - - fn internal_command(&self, internal: &InternalCommand) -> Vec { - let mut result = Vec::new(); - - match internal.args.head.expr { - Expression::Command => { - result.push(LocationType::Command.spanned(internal.name_span)); - } - Expression::Literal(Literal::String(_)) => { - result.push(LocationType::Command.spanned(internal.name_span)); - } - _ => (), - } - - if let Some(positionals) = &internal.args.positional { - let mut positionals = positionals.iter(); - - if internal.name == "run_external" { - if let Some(external_command) = positionals.next() { - result.push(LocationType::Command.spanned(external_command.span)); - } - } - - result.extend(positionals.flat_map(|positional| match positional.expr { - Expression::Garbage => { - let garbage = positional.span.slice(self.line); - let location = if garbage.starts_with('-') { - LocationType::Flag(internal.name.clone()) - } else { - // TODO we may be able to map this to the name of a positional, - // but we'll need a signature - LocationType::Argument(Some(internal.name.clone()), None) - }; - - vec![location.spanned(positional.span)] - } - - _ => self.expression(positional), - })); - } - - if let Some(named) = &internal.args.named { - for (name, kind) in &named.named { - match kind { - NamedValue::PresentSwitch(span) => { - result.push(LocationType::Flag(internal.name.clone()).spanned(*span)); - } - - NamedValue::Value(span, expr) => { - result.push(LocationType::Flag(internal.name.clone()).spanned(*span)); - result.append(&mut self.with_flag(name.clone()).expression(expr)); - } - - _ => (), - } - } - } - - result - } - - fn pipeline(&self, pipeline: &Pipeline) -> Vec { - let mut result = Vec::new(); - - for command in &pipeline.list { - match command { - ClassifiedCommand::Internal(internal) => { - let engine = self.with_command(internal.name.clone()); - result.append(&mut engine.internal_command(internal)); - } - - ClassifiedCommand::Expr(expr) => result.append(&mut self.expression(expr)), - _ => (), - } - } - - result - } - - /// Flattens the block into a Vec of completion locations - pub fn completion_locations(&self, block: &Block) -> Vec { - block - .block - .iter() - .flat_map(|g| g.pipelines.iter().flat_map(|v| self.pipeline(v))) - .collect() - } - - pub fn new(line: &'s str) -> Flatten<'s> { - Flatten { - line, - command: None, - flag: None, - } - } - - pub fn with_command(&self, command: String) -> Flatten<'s> { - Flatten { - line: self.line, - command: Some(command), - flag: None, - } - } - - pub fn with_flag(&self, flag: String) -> Flatten<'s> { - Flatten { - line: self.line, - command: self.command.clone(), - flag: Some(flag), - } - } -} - -/// Characters that precede a command name -const BEFORE_COMMAND_CHARS: &[char] = &['|', '(', ';']; - -/// Determines the completion location for a given block at the given cursor position -pub fn completion_location(line: &str, block: &Block, pos: usize) -> Vec { - let completion_engine = Flatten::new(line); - let locations = completion_engine.completion_locations(block); - - if locations.is_empty() { - vec![LocationType::Command.spanned(Span::unknown())] - } else { - let mut command = None; - let mut prev = None; - - for loc in &locations { - // We don't use span.contains because we want to include the end. This handles the case - // where the cursor is just after the text (i.e., no space between cursor and text) - if loc.span.start() <= pos && pos <= loc.span.end() { - // The parser sees the "-" in `cmd -` as an argument, but the user is likely - // expecting a flag. - return match loc.item { - LocationType::Argument(ref cmd, _) => { - if loc.span.slice(line) == "-" { - let cmd = cmd.clone(); - let span = loc.span; - vec![ - loc.clone(), - LocationType::Flag(cmd.unwrap_or_default()).spanned(span), - ] - } else { - let mut output = vec![]; - - for rloc in locations.iter().rev() { - if let Spanned { - span, - item: LocationType::Command, - } = &rloc - { - if span.start() <= pos { - output.push( - LocationType::Command - .spanned(Span::new(span.start(), pos)), - ); - break; - } - } - } - - output.push({ - let mut partial_loc = loc.clone(); - partial_loc.span = Span::new(loc.span.start(), pos); - partial_loc - }); - output - } - } - _ => vec![{ - let mut partial_loc = loc.clone(); - partial_loc.span = Span::new(loc.span.start(), pos); - partial_loc - }], - }; - } else if pos < loc.span.start() { - break; - } - - if let LocationType::Command = loc.item { - command = Some(String::from(loc.span.slice(line))); - } - - prev = Some(loc); - } - - if let Some(prev) = prev { - let mut locations = vec![]; - // Cursor is between locations (or at the end). Look at the line to see if the cursor - // is after some character that would imply we're in the command position. - let start = prev.span.end(); - - if let Spanned { - item: LocationType::Command, - span, - } = &prev - { - locations.push(LocationType::Command.spanned(Span::new(span.start(), pos))); - } - if line[start..pos].contains(BEFORE_COMMAND_CHARS) { - locations.push(LocationType::Command.spanned(Span::new(pos, pos))); - } else { - // TODO this should be able to be mapped to a command - locations.push(LocationType::Argument(command, None).spanned(Span::new(pos, pos))); - } - locations - } else { - // Cursor is before any possible completion location, so must be a command - vec![LocationType::Command.spanned(Span::unknown())] - } - } -} - -#[cfg(test)] -mod tests { - use std::sync::Arc; - - use super::*; - - use nu_parser::{classify_block, lex, parse_block, ParserScope}; - use nu_protocol::{Signature, SyntaxShape}; - - #[derive(Clone, Debug)] - struct VecRegistry(Vec); - - impl From> for VecRegistry { - fn from(v: Vec) -> Self { - VecRegistry(v) - } - } - - impl ParserScope for VecRegistry { - fn has_signature(&self, name: &str) -> bool { - self.0.iter().any(|v| v.name == name) - } - - fn get_signature(&self, name: &str) -> Option { - self.0.iter().find(|v| v.name == name).cloned() - } - - fn get_alias(&self, _name: &str) -> Option>> { - None - } - - fn add_alias(&self, _name: &str, _replacement: Vec>) { - todo!() - } - - fn remove_alias(&self, _name: &str) { - todo!() - } - - fn add_definition(&self, _block: Arc) {} - - fn get_definitions(&self) -> Vec> { - vec![] - } - - fn enter_scope(&self) {} - - fn exit_scope(&self) {} - } - - mod completion_location { - use super::*; - - fn completion_location( - line: &str, - scope: &dyn ParserScope, - pos: usize, - ) -> Vec { - let (tokens, _) = lex(line, 0, nu_parser::NewlineMode::Normal); - let (lite_block, _) = parse_block(tokens); - - scope.enter_scope(); - let (block, _) = classify_block(&lite_block, scope); - scope.exit_scope(); - - super::completion_location(line, &block, pos) - } - - #[test] - fn completes_internal_command_names() { - let registry: VecRegistry = - vec![Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo")] - .into(); - let line = "echo 1 | echo 2"; - - assert_eq!( - completion_location(line, ®istry, 10), - vec![LocationType::Command.spanned(Span::new(9, 10)),], - ); - } - - #[test] - fn completes_external_command_names() { - let registry: VecRegistry = Vec::new().into(); - let line = "echo 1 | echo 2"; - - assert_eq!( - completion_location(line, ®istry, 10), - vec![LocationType::Command.spanned(Span::new(9, 10)),], - ); - } - - #[test] - fn completes_command_names_when_cursor_immediately_after_command_name() { - let registry: VecRegistry = Vec::new().into(); - let line = "echo 1 | echo 2"; - - assert_eq!( - completion_location(line, ®istry, 4), - vec![LocationType::Command.spanned(Span::new(0, 4)),], - ); - } - - #[test] - fn completes_variables() { - let registry: VecRegistry = Vec::new().into(); - let line = "echo $nu.env."; - - assert_eq!( - completion_location(line, ®istry, 13), - vec![LocationType::Variable.spanned(Span::new(5, 13)),], - ); - } - - #[test] - fn completes_flags() { - let registry: VecRegistry = vec![Signature::build("du") - .switch("recursive", "the values to echo", None) - .rest("rest", SyntaxShape::Any, "blah")] - .into(); - - let line = "du --recurs"; - - assert_eq!( - completion_location(line, ®istry, 7), - vec![LocationType::Flag("du".to_string()).spanned(Span::new(3, 7)),], - ); - } - - #[test] - fn completes_incomplete_nested_structure() { - let registry: VecRegistry = vec![Signature::build("sys")].into(); - let line = "echo (sy"; - - assert_eq!( - completion_location(line, ®istry, 8), - vec![LocationType::Command.spanned(Span::new(6, 8)),], - ); - } - - #[test] - fn has_correct_command_name_for_argument() { - let registry: VecRegistry = vec![Signature::build("cd")].into(); - let line = "cd "; - - assert_eq!( - completion_location(line, ®istry, 3), - vec![ - LocationType::Command.spanned(Span::new(0, 3)), - LocationType::Argument(Some("cd".to_string()), None).spanned(Span::new(3, 3)), - ], - ); - } - - #[test] - fn completes_flags_with_just_a_single_hyphen() { - let registry: VecRegistry = vec![Signature::build("du") - .switch("recursive", "the values to echo", None) - .rest("rest", SyntaxShape::Any, "blah")] - .into(); - - let line = "du -"; - - assert_eq!( - completion_location(line, ®istry, 3), - vec![ - LocationType::Argument(Some("du".to_string()), None).spanned(Span::new(3, 4)), - LocationType::Flag("du".to_string()).spanned(Span::new(3, 4)), - ], - ); - } - - #[test] - fn completes_arguments() { - let registry: VecRegistry = - vec![Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo")] - .into(); - let line = "echo 1 | echo 2"; - - assert_eq!( - completion_location(line, ®istry, 6), - vec![ - LocationType::Command.spanned(Span::new(0, 6)), - LocationType::Argument(Some("echo".to_string()), None).spanned(Span::new(5, 6)), - ], - ); - } - - #[test] - fn completes_argument_when_cursor_inside_argument() { - let registry: VecRegistry = - vec![Signature::build("echo").rest("rest", SyntaxShape::Any, "the values to echo")] - .into(); - let line = "echo 123"; - - assert_eq!( - completion_location(line, ®istry, 6), - vec![ - LocationType::Command.spanned(Span::new(0, 6)), - LocationType::Argument(Some("echo".to_string()), None).spanned(Span::new(5, 6)), - ], - ); - } - } -} diff --git a/old_nushell/crates/nu-completion/src/flag.rs b/old_nushell/crates/nu-completion/src/flag.rs deleted file mode 100644 index 88b8ddaf8..000000000 --- a/old_nushell/crates/nu-completion/src/flag.rs +++ /dev/null @@ -1,35 +0,0 @@ -use super::matchers::Matcher; -use crate::{Completer, CompletionContext, Suggestion}; - -pub struct FlagCompleter { - pub(crate) cmd: String, -} - -impl Completer for FlagCompleter -where - Context: CompletionContext, -{ - fn complete(&self, ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec { - if let Some(sig) = ctx.signature_registry().get(&self.cmd) { - let mut suggestions = Vec::new(); - for (name, (named_type, _desc)) in &sig.named { - suggestions.push(format!("--{}", name)); - - if let Some(c) = named_type.get_short() { - suggestions.push(format!("-{}", c)); - } - } - - suggestions - .into_iter() - .filter(|v| matcher.matches(partial, v)) - .map(|v| Suggestion { - replacement: format!("{} ", v), - display: v, - }) - .collect() - } else { - Vec::new() - } - } -} diff --git a/old_nushell/crates/nu-completion/src/lib.rs b/old_nushell/crates/nu-completion/src/lib.rs deleted file mode 100644 index 4774f933f..000000000 --- a/old_nushell/crates/nu-completion/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -pub(crate) mod command; -pub(crate) mod completer; -pub(crate) mod engine; -pub(crate) mod flag; -pub(crate) mod matchers; -pub(crate) mod path; -pub(crate) mod variable; - -use nu_engine::EvaluationContext; -use nu_protocol::{SignatureRegistry, VariableRegistry}; - -use matchers::Matcher; - -pub use completer::NuCompleter; - -#[derive(Debug, Eq, PartialEq)] -pub struct Suggestion { - pub display: String, - pub replacement: String, -} - -impl Suggestion { - fn new(display: impl Into, replacement: impl Into) -> Self { - Self { - display: display.into(), - replacement: replacement.into(), - } - } -} - -pub trait CompletionContext { - fn signature_registry(&self) -> &dyn SignatureRegistry; - fn scope(&self) -> &dyn nu_parser::ParserScope; - fn source(&self) -> &EvaluationContext; - fn variable_registry(&self) -> &dyn VariableRegistry; -} - -pub trait Completer { - fn complete(&self, ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec; -} diff --git a/old_nushell/crates/nu-completion/src/matchers/case_insensitive.rs b/old_nushell/crates/nu-completion/src/matchers/case_insensitive.rs deleted file mode 100644 index 9c3ad47a5..000000000 --- a/old_nushell/crates/nu-completion/src/matchers/case_insensitive.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::matchers; - -pub struct Matcher; - -impl matchers::Matcher for Matcher { - fn matches(&self, partial: &str, from: &str) -> bool { - from.to_ascii_lowercase() - .starts_with(&partial.to_ascii_lowercase()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - // TODO: check some unicode matches if this becomes relevant - - // FIXME: could work exhaustively through ['-', '--'. ''] in a loop for each test - #[test] - fn completes_exact_matches() { - let matcher: Box = Box::new(Matcher); - - assert!(matcher.matches("shouldmatch", "shouldmatch")); - assert!(matcher.matches("shouldm", "shouldmatch")); - assert!(matcher.matches("--also-should-m", "--also-should-match")); - assert!(matcher.matches("-also-should-m", "-also-should-match")); - } - - #[test] - fn completes_case_insensitive_matches() { - let matcher: Box = Box::new(Matcher); - - assert!(matcher.matches("thisshould", "Thisshouldmatch")); - assert!(matcher.matches("--Shouldm", "--shouldmatch")); - assert!(matcher.matches("-Shouldm", "-shouldmatch")); - } - - #[test] - fn should_not_match_when_unequal() { - let matcher: Box = Box::new(Matcher); - - assert!(!matcher.matches("ashouldmatch", "Shouldnotmatch")); - assert!(!matcher.matches("--ashouldnotmatch", "--Shouldnotmatch")); - assert!(!matcher.matches("-ashouldnotmatch", "-Shouldnotmatch")); - } -} diff --git a/old_nushell/crates/nu-completion/src/matchers/case_sensitive.rs b/old_nushell/crates/nu-completion/src/matchers/case_sensitive.rs deleted file mode 100644 index 6a00aac6d..000000000 --- a/old_nushell/crates/nu-completion/src/matchers/case_sensitive.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::matchers; - -pub struct Matcher; - -impl matchers::Matcher for Matcher { - fn matches(&self, partial: &str, from: &str) -> bool { - from.starts_with(partial) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn completes_case_sensitive() { - let matcher: Box = Box::new(Matcher); - - //Should match - assert!(matcher.matches("shouldmatch", "shouldmatch")); - assert!(matcher.matches("shouldm", "shouldmatch")); - assert!(matcher.matches("--also-should-m", "--also-should-match")); - assert!(matcher.matches("-also-should-m", "-also-should-match")); - - // Should not match - assert!(!matcher.matches("--Shouldnot", "--shouldnotmatch")); - } -} diff --git a/old_nushell/crates/nu-completion/src/matchers/mod.rs b/old_nushell/crates/nu-completion/src/matchers/mod.rs deleted file mode 100644 index c14b0d50c..000000000 --- a/old_nushell/crates/nu-completion/src/matchers/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub(crate) mod case_insensitive; -pub(crate) mod case_sensitive; - -pub trait Matcher { - fn matches(&self, partial: &str, from: &str) -> bool; -} diff --git a/old_nushell/crates/nu-completion/src/path.rs b/old_nushell/crates/nu-completion/src/path.rs deleted file mode 100644 index df804bf89..000000000 --- a/old_nushell/crates/nu-completion/src/path.rs +++ /dev/null @@ -1,77 +0,0 @@ -use std::path::{is_separator, Path, PathBuf}; - -use super::matchers::Matcher; -use crate::{Completer, CompletionContext, Suggestion}; - -const SEP: char = std::path::MAIN_SEPARATOR; - -pub struct PathCompleter; - -#[derive(Debug)] -pub struct PathSuggestion { - pub(crate) path: PathBuf, - pub(crate) suggestion: Suggestion, -} - -impl PathCompleter { - pub fn path_suggestions(&self, partial: &str, matcher: &dyn Matcher) -> Vec { - let (base_dir_name, partial) = { - // If partial is only a word we want to search in the current dir - let (base, rest) = partial.rsplit_once(is_separator).unwrap_or((".", partial)); - // On windows, this standardizes paths to use \ - let mut base = base.replace(is_separator, &SEP.to_string()); - - // rsplit_once removes the separator - base.push(SEP); - (base, rest) - }; - - let base_dir = nu_path::expand_path(&base_dir_name); - // This check is here as base_dir.read_dir() with base_dir == "" will open the current dir - // which we don't want in this case (if we did, base_dir would already be ".") - if base_dir == Path::new("") { - return Vec::new(); - } - - if let Ok(result) = base_dir.read_dir() { - result - .filter_map(|entry| { - entry.ok().and_then(|entry| { - let mut file_name = entry.file_name().to_string_lossy().into_owned(); - if matcher.matches(partial, &file_name) { - let mut path = format!("{}{}", base_dir_name, file_name); - if entry.path().is_dir() { - path.push(SEP); - file_name.push(SEP); - } - - Some(PathSuggestion { - path: entry.path(), - suggestion: Suggestion { - replacement: path, - display: file_name, - }, - }) - } else { - None - } - }) - }) - .collect() - } else { - Vec::new() - } - } -} - -impl Completer for PathCompleter -where - Context: CompletionContext, -{ - fn complete(&self, _ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec { - self.path_suggestions(partial, matcher) - .into_iter() - .map(|ps| ps.suggestion) - .collect() - } -} diff --git a/old_nushell/crates/nu-completion/src/variable.rs b/old_nushell/crates/nu-completion/src/variable.rs deleted file mode 100644 index 4d450101b..000000000 --- a/old_nushell/crates/nu-completion/src/variable.rs +++ /dev/null @@ -1,187 +0,0 @@ -use nu_engine::value_shell::ValueShell; -use nu_protocol::ColumnPath; -use nu_source::SpannedItem; - -use super::matchers::Matcher; -use crate::{Completer, CompletionContext, Suggestion}; -use std::path::{Path, PathBuf}; - -fn build_path(head: &str, members: &Path, entry: &str) -> String { - let mut full_path = head.to_string(); - full_path.push_str( - &members - .join(entry) - .display() - .to_string() - .replace(std::path::MAIN_SEPARATOR, "."), - ); - full_path -} - -fn collect_entries(value_fs: &ValueShell, head: &str, path: &Path) -> Vec { - value_fs - .members_under(path) - .iter() - .flat_map(|entry| { - entry - .row_entries() - .map(|(entry_name, _)| build_path(head, path, entry_name)) - }) - .collect() -} - -pub struct VariableCompleter; - -impl Completer for VariableCompleter -where - Context: CompletionContext, -{ - fn complete(&self, ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec { - let registry = ctx.variable_registry(); - let variables_available = registry.variables(); - let partial_column_path = ColumnPath::with_head(&partial.to_string().spanned_unknown()); - - partial_column_path - .map(|(head, members)| { - variables_available - .iter() - .filter(|candidate| matcher.matches(&head, candidate)) - .into_iter() - .filter_map(|candidate| { - if !partial.ends_with('.') && members.is_empty() { - Some(vec![candidate.to_string()]) - } else { - let value = registry.get_variable(&candidate[..].spanned_unknown()); - let path = PathBuf::from(members.path()); - - value.map(|candidate| { - let fs = ValueShell::new(candidate); - - fs.find(&path) - .map(|fs| collect_entries(fs, &head, &path)) - .or_else(|| { - path.parent().map(|parent| { - fs.find(parent) - .map(|fs| collect_entries(fs, &head, parent)) - .unwrap_or_default() - }) - }) - .unwrap_or_default() - }) - } - }) - .flatten() - .filter_map(|candidate| { - if matcher.matches(partial, &candidate) { - Some(Suggestion::new(&candidate, &candidate)) - } else { - None - } - }) - .collect() - }) - .unwrap_or_default() - } -} - -#[cfg(test)] -mod tests { - use super::{Completer, Suggestion as S, VariableCompleter}; - use crate::matchers::case_insensitive::Matcher as CaseInsensitiveMatcher; - - use nu_engine::EnvVar; - use nu_engine::{ - evaluation_context::EngineState, ConfigHolder, EvaluationContext, FakeHost, Host, Scope, - ShellManager, - }; - use nu_protocol::{SignatureRegistry, VariableRegistry}; - use parking_lot::Mutex; - use std::ffi::OsString; - use std::sync::{atomic::AtomicBool, Arc}; - - struct CompletionContext<'a>(&'a EvaluationContext); - - impl<'a> crate::CompletionContext for CompletionContext<'a> { - fn signature_registry(&self) -> &dyn SignatureRegistry { - &self.0.scope - } - - fn source(&self) -> &nu_engine::EvaluationContext { - self.0 - } - - fn scope(&self) -> &dyn nu_parser::ParserScope { - &self.0.scope - } - - fn variable_registry(&self) -> &dyn VariableRegistry { - self.0 - } - } - - fn create_context_with_host(host: Box) -> EvaluationContext { - let scope = Scope::new(); - let env_vars = host - .vars() - .iter() - .cloned() - .map(|(k, v)| (k, EnvVar::from(v))) - .collect(); - scope.add_env(env_vars); - - EvaluationContext { - scope, - engine_state: Arc::new(EngineState { - host: Arc::new(parking_lot::Mutex::new(host)), - current_errors: Arc::new(Mutex::new(vec![])), - ctrl_c: Arc::new(AtomicBool::new(false)), - configs: Arc::new(Mutex::new(ConfigHolder::new())), - shell_manager: ShellManager::basic(), - windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())), - }), - } - } - - fn set_envs(host: &mut FakeHost, values: Vec<(&str, &str)>) { - values.iter().for_each(|(key, value)| { - host.env_set(OsString::from(key), OsString::from(value)); - }); - } - - #[test] - fn structure() { - let mut host = nu_engine::FakeHost::new(); - set_envs(&mut host, vec![("COMPLETER", "VARIABLE"), ("SHELL", "NU")]); - let context = create_context_with_host(Box::new(host)); - - assert_eq!( - VariableCompleter {}.complete( - &CompletionContext(&context), - "$nu.env.", - &CaseInsensitiveMatcher - ), - vec![ - S::new("$nu.env.COMPLETER", "$nu.env.COMPLETER"), - S::new("$nu.env.SHELL", "$nu.env.SHELL") - ] - ); - - assert_eq!( - VariableCompleter {}.complete( - &CompletionContext(&context), - "$nu.env.CO", - &CaseInsensitiveMatcher - ), - vec![S::new("$nu.env.COMPLETER", "$nu.env.COMPLETER"),] - ); - - assert_eq!( - VariableCompleter {}.complete( - &CompletionContext(&context), - "$nu.en", - &CaseInsensitiveMatcher - ), - vec![S::new("$nu.env", "$nu.env"),] - ); - } -} diff --git a/old_nushell/crates/nu-data/Cargo.toml b/old_nushell/crates/nu-data/Cargo.toml deleted file mode 100644 index 118300129..000000000 --- a/old_nushell/crates/nu-data/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -authors = ["The Nu Project Contributors"] -description = "Data for Nushell" -edition = "2018" -license = "MIT" -name = "nu-data" -version = "0.43.0" - -[lib] -doctest = false - -[dependencies] -bigdecimal = { package = "bigdecimal", version = "0.3.0", features = ["serde"] } -byte-unit = "4.0.9" -chrono = "0.4.19" -common-path = "1.0.0" -derive-new = "0.5.8" -directories-next = "2.0.0" -getset = "0.1.1" -indexmap = { version="1.6.1", features=["serde-1"] } -log = "0.4.14" -num-bigint = { version="0.4.3", features=["serde"] } -num-format = "0.4.0" -num-traits = "0.2.14" -serde = { version="1.0.123", features=["derive"] } -sha2 = "0.9.3" -sys-locale = "0.1.0" -toml = "0.5.8" - -nu-errors = { version = "0.43.0", path="../nu-errors" } -nu-path = { version = "0.43.0", path="../nu-path" } -nu-protocol = { version = "0.43.0", path="../nu-protocol" } -nu-source = { version = "0.43.0", path="../nu-source" } -nu-table = { version = "0.43.0", path="../nu-table" } -nu-test-support = { version = "0.43.0", path="../nu-test-support" } -nu-value-ext = { version = "0.43.0", path="../nu-value-ext" } -nu-ansi-term = { version = "0.43.0", path="../nu-ansi-term" } - -[features] -dataframe = ["nu-protocol/dataframe"] diff --git a/old_nushell/crates/nu-data/src/base.rs b/old_nushell/crates/nu-data/src/base.rs deleted file mode 100644 index f0b76d7ac..000000000 --- a/old_nushell/crates/nu-data/src/base.rs +++ /dev/null @@ -1,466 +0,0 @@ -pub mod shape; - -use bigdecimal::BigDecimal; -use chrono::{DateTime, FixedOffset, Utc}; -use derive_new::new; -use nu_errors::ShellError; -use nu_protocol::{ - hir, Primitive, ShellTypeName, SpannedTypeName, TaggedDictBuilder, UntaggedValue, Value, -}; -use nu_source::{Span, Tag}; -use nu_value_ext::ValueExt; -use num_bigint::BigInt; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)] -pub struct Operation { - pub(crate) left: Value, - pub(crate) operator: hir::Operator, - pub(crate) right: Value, -} - -#[derive(Serialize, Deserialize)] -pub enum Switch { - Present, - Absent, -} - -impl std::convert::TryFrom> for Switch { - type Error = ShellError; - - fn try_from(value: Option<&Value>) -> Result { - match value { - None => Ok(Switch::Absent), - Some(value) => match &value.value { - UntaggedValue::Primitive(Primitive::Boolean(true)) => Ok(Switch::Present), - _ => Err(ShellError::type_error("Boolean", value.spanned_type_name())), - }, - } - } -} - -pub fn select_fields(obj: &Value, fields: &[String], tag: impl Into) -> Value { - let mut out = TaggedDictBuilder::new(tag); - - let descs = obj.data_descriptors(); - - for column_name in fields { - match descs.iter().find(|&d| d == column_name) { - None => out.insert_untagged(column_name, UntaggedValue::nothing()), - Some(desc) => out.insert_value(desc.clone(), obj.get_data(desc).borrow().clone()), - } - } - - out.into_value() -} - -pub fn reject_fields(obj: &Value, fields: &[String], tag: impl Into) -> Value { - let mut out = TaggedDictBuilder::new(tag); - - let descs = obj.data_descriptors(); - - for desc in descs { - if fields.iter().any(|field| *field == desc) { - continue; - } else { - out.insert_value(desc.clone(), obj.get_data(&desc).borrow().clone()) - } - } - - out.into_value() -} - -pub enum CompareValues { - Ints(i64, i64), - Filesizes(u64, u64), - BigInts(BigInt, BigInt), - Decimals(BigDecimal, BigDecimal), - String(String, String), - Date(DateTime, DateTime), - DateDuration(DateTime, BigInt), - TimeDuration(BigInt, BigInt), - Booleans(bool, bool), -} - -impl CompareValues { - pub fn compare(&self) -> std::cmp::Ordering { - match self { - CompareValues::BigInts(left, right) => left.cmp(right), - CompareValues::Ints(left, right) => left.cmp(right), - CompareValues::Filesizes(left, right) => left.cmp(right), - CompareValues::Decimals(left, right) => left.cmp(right), - CompareValues::String(left, right) => left.cmp(right), - CompareValues::Date(left, right) => left.cmp(right), - CompareValues::DateDuration(left, right) => { - // FIXME: Not sure if I could do something better with the Span. - let duration = Primitive::into_chrono_duration( - Primitive::Duration(right.clone()), - Span::unknown(), - ) - .expect("Could not convert nushell Duration into chrono Duration."); - let right: DateTime = Utc::now() - .checked_sub_signed(duration) - .expect("Data overflow") - .into(); - right.cmp(left) - } - CompareValues::Booleans(left, right) => left.cmp(right), - CompareValues::TimeDuration(left, right) => left.cmp(right), - } - } -} - -pub fn coerce_compare( - left: &UntaggedValue, - right: &UntaggedValue, -) -> Result { - match (left, right) { - (UntaggedValue::Primitive(left), UntaggedValue::Primitive(right)) => { - coerce_compare_primitive(left, right) - } - - _ => Err((left.type_name(), right.type_name())), - } -} - -pub fn coerce_compare_primitive( - left: &Primitive, - right: &Primitive, -) -> Result { - use Primitive::*; - - Ok(match (left, right) { - (Int(left), Int(right)) => CompareValues::Ints(*left, *right), - (Int(left), BigInt(right)) => { - CompareValues::BigInts(num_bigint::BigInt::from(*left), right.clone()) - } - (BigInt(left), Int(right)) => { - CompareValues::BigInts(left.clone(), num_bigint::BigInt::from(*right)) - } - (BigInt(left), BigInt(right)) => CompareValues::BigInts(left.clone(), right.clone()), - - (Int(left), Decimal(right)) => { - CompareValues::Decimals(BigDecimal::from(*left), right.clone()) - } - (BigInt(left), Decimal(right)) => { - CompareValues::Decimals(BigDecimal::from(left.clone()), right.clone()) - } - (Decimal(left), Decimal(right)) => CompareValues::Decimals(left.clone(), right.clone()), - (Decimal(left), Int(right)) => { - CompareValues::Decimals(left.clone(), BigDecimal::from(*right)) - } - (Decimal(left), BigInt(right)) => { - CompareValues::Decimals(left.clone(), BigDecimal::from(right.clone())) - } - (Decimal(left), Filesize(right)) => { - CompareValues::Decimals(left.clone(), BigDecimal::from(*right)) - } - (Filesize(left), Filesize(right)) => CompareValues::Filesizes(*left, *right), - (Filesize(left), Decimal(right)) => { - CompareValues::Decimals(BigDecimal::from(*left), right.clone()) - } - (Nothing, Nothing) => CompareValues::Booleans(true, true), - (String(left), String(right)) => CompareValues::String(left.clone(), right.clone()), - (Date(left), Date(right)) => CompareValues::Date(*left, *right), - (Date(left), Duration(right)) => CompareValues::DateDuration(*left, right.clone()), - (Boolean(left), Boolean(right)) => CompareValues::Booleans(*left, *right), - (Boolean(left), Nothing) => CompareValues::Ints(if *left { 1 } else { 0 }, -1), - (Nothing, Boolean(right)) => CompareValues::Ints(-1, if *right { 1 } else { 0 }), - (String(left), Nothing) => CompareValues::String(left.clone(), std::string::String::new()), - (Nothing, String(right)) => { - CompareValues::String(std::string::String::new(), right.clone()) - } - (FilePath(left), String(right)) => { - CompareValues::String(left.as_path().display().to_string(), right.clone()) - } - (String(left), FilePath(right)) => { - CompareValues::String(left.clone(), right.as_path().display().to_string()) - } - (Duration(left), Duration(right)) => { - CompareValues::TimeDuration(left.clone(), right.clone()) - } - _ => return Err((left.type_name(), right.type_name())), - }) -} -#[cfg(test)] -mod tests { - use nu_errors::ShellError; - use nu_protocol::UntaggedValue; - use nu_source::SpannedItem; - use nu_test_support::value::*; - use nu_value_ext::ValueExt; - - use indexmap::indexmap; - - #[test] - fn gets_matching_field_from_a_row() -> Result<(), ShellError> { - let row = UntaggedValue::row(indexmap! { - "amigos".into() => table(&[string("andres"),string("jonathan"),string("yehuda")]) - }) - .into_untagged_value(); - - assert_eq!( - row.get_data_by_key("amigos".spanned_unknown()) - .ok_or_else(|| ShellError::unexpected("Failure during testing"))?, - table(&[string("andres"), string("jonathan"), string("yehuda")]) - ); - - Ok(()) - } - - #[test] - fn gets_matching_field_from_nested_rows_inside_a_row() -> Result<(), ShellError> { - let field_path = column_path("package.version").as_column_path()?; - - let (version, tag) = string("0.4.0").into_parts(); - - let value = UntaggedValue::row(indexmap! { - "package".into() => - row(indexmap! { - "name".into() => string("nu"), - "version".into() => string("0.4.0") - }) - }); - - assert_eq!( - *value.into_value(tag).get_data_by_column_path( - &field_path.item, - Box::new(error_callback("package.version")) - )?, - version - ); - - Ok(()) - } - - #[test] - fn gets_first_matching_field_from_rows_with_same_field_inside_a_table() -> Result<(), ShellError> - { - let field_path = column_path("package.authors.name").as_column_path()?; - - let (_, tag) = string("Andrés N. Robalino").into_parts(); - - let value = UntaggedValue::row(indexmap! { - "package".into() => row(indexmap! { - "name".into() => string("nu"), - "version".into() => string("0.4.0"), - "authors".into() => table(&[ - row(indexmap!{"name".into() => string("Andrés N. Robalino")}), - row(indexmap!{"name".into() => string("Jonathan Turner")}), - row(indexmap!{"name".into() => string("Yehuda Katz")}) - ]) - }) - }); - - assert_eq!( - value.into_value(tag).get_data_by_column_path( - &field_path.item, - Box::new(error_callback("package.authors.name")) - )?, - table(&[ - string("Andrés N. Robalino"), - string("Jonathan Turner"), - string("Yehuda Katz") - ]) - ); - - Ok(()) - } - - #[test] - fn column_path_that_contains_just_a_number_gets_a_row_from_a_table() -> Result<(), ShellError> { - let field_path = column_path("package.authors.0").as_column_path()?; - - let (_, tag) = string("Andrés N. Robalino").into_parts(); - - let value = UntaggedValue::row(indexmap! { - "package".into() => row(indexmap! { - "name".into() => string("nu"), - "version".into() => string("0.4.0"), - "authors".into() => table(&[ - row(indexmap!{"name".into() => string("Andrés N. Robalino")}), - row(indexmap!{"name".into() => string("Jonathan Turner")}), - row(indexmap!{"name".into() => string("Yehuda Katz")}) - ]) - }) - }); - - assert_eq!( - *value.into_value(tag).get_data_by_column_path( - &field_path.item, - Box::new(error_callback("package.authors.0")) - )?, - UntaggedValue::row(indexmap! { - "name".into() => string("Andrés N. Robalino") - }) - ); - - Ok(()) - } - - #[test] - fn column_path_that_contains_just_a_number_gets_a_row_from_a_row() -> Result<(), ShellError> { - let field_path = column_path(r#"package.authors."0""#).as_column_path()?; - - let (_, tag) = string("Andrés N. Robalino").into_parts(); - - let value = UntaggedValue::row(indexmap! { - "package".into() => row(indexmap! { - "name".into() => string("nu"), - "version".into() => string("0.4.0"), - "authors".into() => row(indexmap! { - "0".into() => row(indexmap!{"name".into() => string("Andrés N. Robalino")}), - "1".into() => row(indexmap!{"name".into() => string("Jonathan Turner")}), - "2".into() => row(indexmap!{"name".into() => string("Yehuda Katz")}), - }) - }) - }); - - assert_eq!( - *value.into_value(tag).get_data_by_column_path( - &field_path.item, - Box::new(error_callback("package.authors.\"0\"")) - )?, - UntaggedValue::row(indexmap! { - "name".into() => string("Andrés N. Robalino") - }) - ); - - Ok(()) - } - - #[test] - fn replaces_matching_field_from_a_row() -> Result<(), ShellError> { - let field_path = column_path("amigos").as_column_path()?; - - let sample = UntaggedValue::row(indexmap! { - "amigos".into() => table(&[ - string("andres"), - string("jonathan"), - string("yehuda"), - ]), - }); - - let replacement = string("jonas"); - - let actual = sample - .into_untagged_value() - .replace_data_at_column_path(&field_path.item, replacement) - .ok_or_else(|| ShellError::untagged_runtime_error("Could not replace column"))?; - - assert_eq!(actual, row(indexmap! {"amigos".into() => string("jonas")})); - - Ok(()) - } - - #[test] - fn replaces_matching_field_from_nested_rows_inside_a_row() -> Result<(), ShellError> { - let field_path = column_path(r#"package.authors."los.3.caballeros""#).as_column_path()?; - - let sample = UntaggedValue::row(indexmap! { - "package".into() => row(indexmap! { - "authors".into() => row(indexmap! { - "los.3.mosqueteros".into() => table(&[string("andres::yehuda::jonathan")]), - "los.3.amigos".into() => table(&[string("andres::yehuda::jonathan")]), - "los.3.caballeros".into() => table(&[string("andres::yehuda::jonathan")]) - }) - }) - }); - - let replacement = table(&[string("yehuda::jonathan::andres")]); - let tag = replacement.tag.clone(); - - let actual = sample - .into_value(&tag) - .replace_data_at_column_path(&field_path.item, replacement.clone()) - .ok_or_else(|| { - ShellError::labeled_error( - "Could not replace column", - "could not replace column", - &tag, - ) - })?; - - assert_eq!( - actual, - UntaggedValue::row(indexmap! { - "package".into() => row(indexmap! { - "authors".into() => row(indexmap! { - "los.3.mosqueteros".into() => table(&[string("andres::yehuda::jonathan")]), - "los.3.amigos".into() => table(&[string("andres::yehuda::jonathan")]), - "los.3.caballeros".into() => replacement})})}) - .into_value(tag) - ); - - Ok(()) - } - #[test] - fn replaces_matching_field_from_rows_inside_a_table() -> Result<(), ShellError> { - let field_path = - column_path(r#"shell_policy.releases."nu.version.arepa""#).as_column_path()?; - - let sample = UntaggedValue::row(indexmap! { - "shell_policy".into() => row(indexmap! { - "releases".into() => table(&[ - row(indexmap! { - "nu.version.arepa".into() => row(indexmap! { - "code".into() => string("0.4.0"), "tag_line".into() => string("GitHub-era") - }) - }), - row(indexmap! { - "nu.version.taco".into() => row(indexmap! { - "code".into() => string("0.3.0"), "tag_line".into() => string("GitHub-era") - }) - }), - row(indexmap! { - "nu.version.stable".into() => row(indexmap! { - "code".into() => string("0.2.0"), "tag_line".into() => string("GitHub-era") - }) - }) - ]) - }) - }); - - let replacement = row(indexmap! { - "code".into() => string("0.5.0"), - "tag_line".into() => string("CABALLEROS") - }); - let tag = replacement.tag.clone(); - - let actual = sample - .into_value(tag.clone()) - .replace_data_at_column_path(&field_path.item, replacement.clone()) - .ok_or_else(|| { - ShellError::labeled_error( - "Could not replace column", - "could not replace column", - &tag, - ) - })?; - - assert_eq!( - actual, - UntaggedValue::row(indexmap! { - "shell_policy".into() => row(indexmap! { - "releases".into() => table(&[ - row(indexmap! { - "nu.version.arepa".into() => replacement - }), - row(indexmap! { - "nu.version.taco".into() => row(indexmap! { - "code".into() => string("0.3.0"), "tag_line".into() => string("GitHub-era") - }) - }), - row(indexmap! { - "nu.version.stable".into() => row(indexmap! { - "code".into() => string("0.2.0"), "tag_line".into() => string("GitHub-era") - }) - }) - ]) - }) - }).into_value(&tag) - ); - - Ok(()) - } -} diff --git a/old_nushell/crates/nu-data/src/base/shape.rs b/old_nushell/crates/nu-data/src/base/shape.rs deleted file mode 100644 index c2a912216..000000000 --- a/old_nushell/crates/nu-data/src/base/shape.rs +++ /dev/null @@ -1,479 +0,0 @@ -use bigdecimal::BigDecimal; -use chrono::{DateTime, FixedOffset}; -use indexmap::map::IndexMap; -use nu_protocol::RangeInclusion; -use nu_protocol::{format_primitive, ColumnPath, Dictionary, Primitive, UntaggedValue, Value}; -use nu_source::{DbgDocBldr, DebugDocBuilder, PrettyDebug, Tag}; -use num_bigint::BigInt; -use num_format::{Locale, ToFormattedString}; -use serde::{Deserialize, Serialize}; -use std::cmp::Ordering; -use std::fmt::Debug; -use std::hash::{Hash, Hasher}; -use std::path::PathBuf; -use sys_locale::get_locale; - -#[cfg(feature = "dataframe")] -use nu_protocol::dataframe::{FrameStruct, NuDataFrame}; - -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] -pub struct InlineRange { - from: (InlineShape, RangeInclusion), - to: (InlineShape, RangeInclusion), -} - -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] -pub enum InlineShape { - Nothing, - Int(i64), - BigInt(BigInt), - Decimal(BigDecimal), - Range(Box), - Bytesize(u64), - String(String), - Line(String), - ColumnPath(ColumnPath), - GlobPattern(String), - Boolean(bool), - Date(DateTime), - Duration(BigInt), - FilePath(PathBuf), - Binary(usize), - - Row(Row), - Table(Vec), - - // TODO: Block arguments - Block, - // TODO: Error type - Error, - - #[cfg(feature = "dataframe")] - DataFrame(String), - - #[cfg(feature = "dataframe")] - FrameStruct(String), - - // Stream markers (used as bookend markers rather than actual values) - BeginningOfStream, - EndOfStream, -} - -pub struct FormatInlineShape { - shape: InlineShape, - column: Option, -} - -pub fn get_config_filesize_metric() -> bool { - let res = crate::config::config(Tag::unknown()); - if res.is_err() { - return true; - } - let value = res - .unwrap_or_default() - .get("filesize_metric") - .map(|s| s.value.is_true()) - .unwrap_or(true); - value -} - -impl InlineShape { - pub fn from_primitive(primitive: &Primitive) -> InlineShape { - match primitive { - Primitive::Nothing => InlineShape::Nothing, - Primitive::Int(int) => InlineShape::Int(*int), - Primitive::BigInt(int) => InlineShape::BigInt(int.clone()), - Primitive::Range(range) => { - let (left, left_inclusion) = &range.from; - let (right, right_inclusion) = &range.to; - - InlineShape::Range(Box::new(InlineRange { - from: (InlineShape::from_primitive(left), *left_inclusion), - to: (InlineShape::from_primitive(right), *right_inclusion), - })) - } - Primitive::Decimal(decimal) => InlineShape::Decimal(decimal.clone()), - Primitive::Filesize(bytesize) => InlineShape::Bytesize(*bytesize), - Primitive::String(string) => InlineShape::String(string.clone()), - Primitive::ColumnPath(path) => InlineShape::ColumnPath(path.clone()), - Primitive::GlobPattern(pattern) => InlineShape::GlobPattern(pattern.clone()), - Primitive::Boolean(boolean) => InlineShape::Boolean(*boolean), - Primitive::Date(date) => InlineShape::Date(*date), - Primitive::Duration(duration) => InlineShape::Duration(duration.clone()), - Primitive::FilePath(path) => InlineShape::FilePath(path.clone()), - Primitive::Binary(b) => InlineShape::Binary(b.len()), - Primitive::BeginningOfStream => InlineShape::BeginningOfStream, - Primitive::EndOfStream => InlineShape::EndOfStream, - } - } - - pub fn from_dictionary(dictionary: &Dictionary) -> InlineShape { - let mut map = IndexMap::new(); - - for (key, value) in &dictionary.entries { - let column = Column::String(key.clone()); - map.insert(column, InlineShape::from_value(value)); - } - - InlineShape::Row(Row { map }) - } - - pub fn from_table<'a>(table: impl IntoIterator) -> InlineShape { - let vec = table.into_iter().map(InlineShape::from_value).collect(); - - InlineShape::Table(vec) - } - - #[cfg(feature = "dataframe")] - pub fn from_df(df: &NuDataFrame) -> InlineShape { - let msg = format!("{} rows {} cols", df.as_ref().height(), df.as_ref().width()); - - InlineShape::DataFrame(msg) - } - - #[cfg(feature = "dataframe")] - pub fn from_frame_struct(s: &FrameStruct) -> InlineShape { - match s { - FrameStruct::GroupBy(groupby) => { - let msg = groupby.by().join(","); - let msg = format!("groupby {}", msg); - InlineShape::DataFrame(msg) - } - } - } - - pub fn from_value<'a>(value: impl Into<&'a UntaggedValue>) -> InlineShape { - match value.into() { - UntaggedValue::Primitive(p) => InlineShape::from_primitive(p), - UntaggedValue::Row(row) => InlineShape::from_dictionary(row), - UntaggedValue::Table(table) => InlineShape::from_table(table), - UntaggedValue::Error(_) => InlineShape::Error, - UntaggedValue::Block(_) => InlineShape::Block, - #[cfg(feature = "dataframe")] - UntaggedValue::DataFrame(df) => InlineShape::from_df(df), - #[cfg(feature = "dataframe")] - UntaggedValue::FrameStruct(s) => InlineShape::from_frame_struct(s), - } - } - - #[allow(unused)] - pub fn format_for_column(self, column: impl Into) -> FormatInlineShape { - FormatInlineShape { - shape: self, - column: Some(column.into()), - } - } - - pub fn format(self) -> FormatInlineShape { - FormatInlineShape { - shape: self, - column: None, - } - } - - pub fn format_bytes(bytesize: u64, forced_format: Option<&str>) -> (DbgDocBldr, String) { - use bigdecimal::ToPrimitive; - - // get the config value, if it doesn't exist make it 'auto' so it works how it originally did - let filesize_format_var; - if let Some(fmt) = forced_format { - filesize_format_var = fmt.to_ascii_lowercase(); - } else { - filesize_format_var = match crate::config::config(Tag::unknown()) { - Ok(cfg) => cfg - .get("filesize_format") - .map(|val| val.convert_to_string().to_ascii_lowercase()) - .unwrap_or_else(|| "auto".to_string()), - _ => "auto".to_string(), - } - } - - // if there is a value, match it to one of the valid values for byte units - let filesize_format = match filesize_format_var.as_str() { - "b" => (byte_unit::ByteUnit::B, ""), - "kb" => (byte_unit::ByteUnit::KB, ""), - "kib" => (byte_unit::ByteUnit::KiB, ""), - "mb" => (byte_unit::ByteUnit::MB, ""), - "mib" => (byte_unit::ByteUnit::MiB, ""), - "gb" => (byte_unit::ByteUnit::GB, ""), - "gib" => (byte_unit::ByteUnit::GiB, ""), - "tb" => (byte_unit::ByteUnit::TB, ""), - "tib" => (byte_unit::ByteUnit::TiB, ""), - "pb" => (byte_unit::ByteUnit::PB, ""), - "pib" => (byte_unit::ByteUnit::PiB, ""), - "eb" => (byte_unit::ByteUnit::EB, ""), - "eib" => (byte_unit::ByteUnit::EiB, ""), - "zb" => (byte_unit::ByteUnit::ZB, ""), - "zib" => (byte_unit::ByteUnit::ZiB, ""), - _ => (byte_unit::ByteUnit::B, "auto"), - }; - - if let Some(value) = bytesize.to_u128() { - let byte = byte_unit::Byte::from_bytes(value); - let adj_byte = - if filesize_format.0 == byte_unit::ByteUnit::B && filesize_format.1 == "auto" { - byte.get_appropriate_unit(!get_config_filesize_metric()) - } else { - byte.get_adjusted_unit(filesize_format.0) - }; - - match adj_byte.get_unit() { - byte_unit::ByteUnit::B => { - let locale_string = get_locale().unwrap_or_else(|| String::from("en-US")); - // Since get_locale() and Locale::from_name() don't always return the same items - // we need to try and parse it to match. For instance, a valid locale is de_DE - // however Locale::from_name() wants only de so we split and parse it out. - let locale_string = locale_string.replace("_", "-"); // en_AU -> en-AU - let locale = match Locale::from_name(&locale_string) { - Ok(loc) => loc, - _ => { - let all = num_format::Locale::available_names(); - let locale_prefix = &locale_string.split('-').collect::>(); - if all.contains(&locale_prefix[0]) { - // eprintln!("Found alternate: {}", &locale_prefix[0]); - Locale::from_name(locale_prefix[0]).unwrap_or(Locale::en) - } else { - // eprintln!("Unable to find matching locale. Defaulting to en-US"); - Locale::en - } - } - }; - let locale_byte = adj_byte.get_value() as u64; - let locale_byte_string = locale_byte.to_formatted_string(&locale); - if filesize_format.1 == "auto" { - let doc = (DbgDocBldr::primitive(locale_byte_string) - + DbgDocBldr::space() - + DbgDocBldr::kind("B")) - .group(); - (doc.clone(), InlineShape::render_doc(&doc)) - } else { - let doc = (DbgDocBldr::primitive(locale_byte_string)).group(); - (doc.clone(), InlineShape::render_doc(&doc)) - } - } - _ => { - let doc = DbgDocBldr::primitive(adj_byte.format(1)); - (doc.clone(), InlineShape::render_doc(&doc)) - } - } - } else { - let doc = - (DbgDocBldr::primitive(bytesize) + DbgDocBldr::space() + DbgDocBldr::kind("B")) - .group(); - (doc.clone(), InlineShape::render_doc(&doc)) - } - } - - pub fn render_doc(doc: &DebugDocBuilder) -> String { - let mut w = Vec::new(); - doc.to_doc() - .render(1000, &mut w) - .expect("Error rendering bytes"); - String::from_utf8_lossy(&w).to_string() - } -} - -impl PrettyDebug for FormatInlineShape { - fn pretty(&self) -> DebugDocBuilder { - let column = &self.column; - - match &self.shape { - InlineShape::Nothing => DbgDocBldr::blank(), - InlineShape::Int(int) => DbgDocBldr::primitive(int), - InlineShape::BigInt(int) => DbgDocBldr::primitive(int), - InlineShape::Decimal(decimal) => DbgDocBldr::description(format_primitive( - &Primitive::Decimal(decimal.clone()), - None, - )), - InlineShape::Range(range) => { - let (left, left_inclusion) = &range.from; - let (right, right_inclusion) = &range.to; - - let op = match (left_inclusion, right_inclusion) { - (RangeInclusion::Inclusive, RangeInclusion::Inclusive) => "..", - (RangeInclusion::Inclusive, RangeInclusion::Exclusive) => "..<", - _ => unimplemented!( - "No syntax for ranges that aren't inclusive on the left and exclusive \ - or inclusive on the right" - ), - }; - - left.clone().format().pretty() - + DbgDocBldr::operator(op) - + right.clone().format().pretty() - } - InlineShape::Bytesize(bytesize) => { - let bytes = InlineShape::format_bytes(*bytesize, None); - bytes.0 - } - InlineShape::String(string) => DbgDocBldr::primitive(string), - InlineShape::Line(string) => DbgDocBldr::primitive(string), - InlineShape::ColumnPath(path) => DbgDocBldr::intersperse( - path.iter().map(|member| member.pretty()), - DbgDocBldr::keyword("."), - ), - InlineShape::GlobPattern(pattern) => DbgDocBldr::primitive(pattern), - InlineShape::Boolean(boolean) => DbgDocBldr::primitive( - match (boolean, column) { - (true, None) => "true", - (false, None) => "false", - (true, Some(Column::String(s))) if !s.is_empty() => s, - (false, Some(Column::String(s))) if !s.is_empty() => "", - (true, Some(_)) => "true", - (false, Some(_)) => "false", - } - .to_owned(), - ), - InlineShape::Date(date) => DbgDocBldr::primitive(nu_protocol::format_date(date)), - InlineShape::Duration(duration) => DbgDocBldr::description(format_primitive( - &Primitive::Duration(duration.clone()), - None, - )), - InlineShape::FilePath(path) => DbgDocBldr::primitive(path.display()), - InlineShape::Binary(length) => { - DbgDocBldr::opaque(format!("", length)) - } - InlineShape::Row(row) => DbgDocBldr::delimit( - "[", - DbgDocBldr::kind("row") - + DbgDocBldr::space() - + if row.map.keys().len() <= 6 { - DbgDocBldr::intersperse( - row.map.keys().map(|key| match key { - Column::String(string) => DbgDocBldr::description(string), - Column::Value => DbgDocBldr::blank(), - }), - DbgDocBldr::space(), - ) - } else { - DbgDocBldr::description(format!("{} columns", row.map.keys().len())) - }, - "]", - ) - .group(), - InlineShape::Table(rows) => DbgDocBldr::delimit( - "[", - DbgDocBldr::kind("table") - + DbgDocBldr::space() - + DbgDocBldr::primitive(rows.len()) - + DbgDocBldr::space() - + DbgDocBldr::description("rows"), - "]", - ) - .group(), - InlineShape::Block => DbgDocBldr::opaque("block"), - InlineShape::Error => DbgDocBldr::error("error"), - #[cfg(feature = "dataframe")] - InlineShape::DataFrame(msg) => DbgDocBldr::delimit( - "[", - DbgDocBldr::kind("dataframe") + DbgDocBldr::space() + DbgDocBldr::primitive(msg), - "]", - ) - .group(), - #[cfg(feature = "dataframe")] - InlineShape::FrameStruct(msg) => { - DbgDocBldr::delimit("[", DbgDocBldr::primitive(msg), "]").group() - } - InlineShape::BeginningOfStream => DbgDocBldr::blank(), - InlineShape::EndOfStream => DbgDocBldr::blank(), - } - } -} - -pub trait GroupedValue: Debug + Clone { - type Item; - - fn new() -> Self; - fn merge(&mut self, value: Self::Item); -} - -impl GroupedValue for Vec<(usize, usize)> { - type Item = usize; - - fn new() -> Vec<(usize, usize)> { - vec![] - } - - fn merge(&mut self, new_value: usize) { - match self.last_mut() { - Some(value) if value.1 == new_value - 1 => { - value.1 += 1; - } - - _ => self.push((new_value, new_value)), - } - } -} - -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)] -pub enum Column { - String(String), - Value, -} - -impl From for Column { - fn from(x: String) -> Self { - Column::String(x) - } -} - -impl From<&String> for Column { - fn from(x: &String) -> Self { - Column::String(x.clone()) - } -} - -impl From<&str> for Column { - fn from(x: &str) -> Self { - Column::String(x.to_string()) - } -} - -/// A shape representation of the type of a row -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] -pub struct Row { - map: IndexMap, -} - -#[allow(clippy::derive_hash_xor_eq)] -impl Hash for Row { - fn hash(&self, state: &mut H) { - let mut entries = self.map.clone(); - entries.sort_keys(); - entries.keys().collect::>().hash(state); - entries.values().collect::>().hash(state); - } -} - -impl PartialOrd for Row { - fn partial_cmp(&self, other: &Row) -> Option { - let this: Vec<&Column> = self.map.keys().collect(); - let that: Vec<&Column> = other.map.keys().collect(); - - if this != that { - return this.partial_cmp(&that); - } - - let this: Vec<&InlineShape> = self.map.values().collect(); - let that: Vec<&InlineShape> = self.map.values().collect(); - - this.partial_cmp(&that) - } -} - -impl Ord for Row { - /// Compare two dictionaries for ordering - fn cmp(&self, other: &Row) -> Ordering { - let this: Vec<&Column> = self.map.keys().collect(); - let that: Vec<&Column> = other.map.keys().collect(); - - if this != that { - return this.cmp(&that); - } - - let this: Vec<&InlineShape> = self.map.values().collect(); - let that: Vec<&InlineShape> = self.map.values().collect(); - - this.cmp(&that) - } -} diff --git a/old_nushell/crates/nu-data/src/config.rs b/old_nushell/crates/nu-data/src/config.rs deleted file mode 100644 index 3181db46a..000000000 --- a/old_nushell/crates/nu-data/src/config.rs +++ /dev/null @@ -1,319 +0,0 @@ -mod conf; -mod config_trust; -mod local_config; -mod nuconfig; -pub mod path; - -pub use conf::Conf; -pub use config_trust::is_file_trusted; -pub use config_trust::read_trusted; -pub use config_trust::Trusted; -pub use local_config::loadable_cfg_exists_in_dir; -pub use local_config::LocalConfigDiff; -pub use nuconfig::NuConfig; - -use indexmap::IndexMap; -use log::trace; -use nu_errors::{CoerceInto, ShellError}; -use nu_protocol::{ - Dictionary, Primitive, ShellTypeName, TaggedDictBuilder, UnspannedPathMember, UntaggedValue, - Value, -}; -use nu_source::{SpannedItem, Tag, TaggedItem}; -use std::env::var; -use std::fs::{self, OpenOptions}; -use std::io; -use std::path::{Path, PathBuf}; - -pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into) -> Value { - let tag = tag.into(); - - match v { - toml::Value::Boolean(b) => UntaggedValue::boolean(*b).into_value(tag), - toml::Value::Integer(n) => UntaggedValue::int(*n).into_value(tag), - toml::Value::Float(n) => UntaggedValue::decimal_from_float(*n, tag.span).into_value(tag), - toml::Value::String(s) => { - UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(tag) - } - toml::Value::Array(a) => UntaggedValue::Table( - a.iter() - .map(|x| convert_toml_value_to_nu_value(x, &tag)) - .collect(), - ) - .into_value(tag), - toml::Value::Datetime(dt) => { - UntaggedValue::Primitive(Primitive::String(dt.to_string())).into_value(tag) - } - toml::Value::Table(t) => { - let mut collected = TaggedDictBuilder::new(&tag); - - for (k, v) in t { - collected.insert_value(k.clone(), convert_toml_value_to_nu_value(v, &tag)); - } - - collected.into_value() - } - } -} - -fn collect_values(input: &[Value]) -> Result, ShellError> { - let mut out = vec![]; - - for value in input { - out.push(helper(value)?); - } - - Ok(out) -} -// Helper method to recursively convert nu_protocol::Value -> toml::Value -// This shouldn't be called at the top-level -fn helper(v: &Value) -> Result { - use bigdecimal::ToPrimitive; - - Ok(match &v.value { - UntaggedValue::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b), - UntaggedValue::Primitive(Primitive::Filesize(b)) => { - if let Some(value) = b.to_i64() { - toml::Value::Integer(value) - } else { - return Err(ShellError::labeled_error( - "Value too large to convert to toml value", - "value too large", - v.tag.span, - )); - } - } - UntaggedValue::Primitive(Primitive::Duration(i)) => toml::Value::String(i.to_string()), - UntaggedValue::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()), - UntaggedValue::Primitive(Primitive::EndOfStream) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::BeginningOfStream) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::Decimal(f)) => { - toml::Value::Float(f.tagged(&v.tag).coerce_into("converting to TOML float")?) - } - UntaggedValue::Primitive(Primitive::Int(i)) => toml::Value::Integer(*i), - UntaggedValue::Primitive(Primitive::BigInt(i)) => { - toml::Value::Integer(i.tagged(&v.tag).coerce_into("converting to TOML integer")?) - } - UntaggedValue::Primitive(Primitive::Nothing) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::GlobPattern(s)) => toml::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()), - UntaggedValue::Primitive(Primitive::FilePath(s)) => { - toml::Value::String(s.display().to_string()) - } - UntaggedValue::Primitive(Primitive::ColumnPath(path)) => toml::Value::Array( - path.iter() - .map(|x| match &x.unspanned { - UnspannedPathMember::String(string) => Ok(toml::Value::String(string.clone())), - UnspannedPathMember::Int(int) => Ok(toml::Value::Integer(*int)), - }) - .collect::, ShellError>>()?, - ), - UntaggedValue::Table(l) => toml::Value::Array(collect_values(l)?), - UntaggedValue::Error(e) => return Err(e.clone()), - UntaggedValue::Block(_) => toml::Value::String("".to_string()), - #[cfg(feature = "dataframe")] - UntaggedValue::DataFrame(_) | UntaggedValue::FrameStruct(_) => { - toml::Value::String("".to_string()) - } - UntaggedValue::Primitive(Primitive::Range(_)) => toml::Value::String("".to_string()), - UntaggedValue::Primitive(Primitive::Binary(b)) => { - toml::Value::Array(b.iter().map(|x| toml::Value::Integer(*x as i64)).collect()) - } - UntaggedValue::Row(o) => { - let mut m = toml::map::Map::new(); - for (k, v) in &o.entries { - m.insert(k.clone(), helper(v)?); - } - toml::Value::Table(m) - } - }) -} - -/// Converts a nu_protocol::Value into a toml::Value -/// Will return a Shell Error, if the Nu Value is not a valid top-level TOML Value -pub fn value_to_toml_value(v: &Value) -> Result { - match &v.value { - UntaggedValue::Row(o) => { - let mut m = toml::map::Map::new(); - for (k, v) in &o.entries { - m.insert(k.clone(), helper(v)?); - } - Ok(toml::Value::Table(m)) - } - UntaggedValue::Primitive(Primitive::String(s)) => { - // Attempt to de-serialize the String - toml::de::from_str(s).map_err(|_| { - ShellError::labeled_error( - format!("{:?} unable to de-serialize string to TOML", s), - "invalid TOML", - v.tag(), - ) - }) - } - _ => Err(ShellError::labeled_error( - format!("{:?} is not a valid top-level TOML", v.value), - "invalid TOML", - v.tag(), - )), - } -} - -pub fn config_path() -> Result { - use directories_next::ProjectDirs; - - let dir = ProjectDirs::from("org", "nushell", "nu") - .ok_or_else(|| ShellError::untagged_runtime_error("Couldn't find project directory"))?; - let path = var("NU_CONFIG_DIR").map_or(ProjectDirs::config_dir(&dir).to_owned(), |path| { - PathBuf::from(path) - }); - std::fs::create_dir_all(&path).map_err(|err| { - ShellError::untagged_runtime_error(&format!("Couldn't create {} path:\n{}", "config", err)) - })?; - - Ok(path) -} - -pub fn default_path() -> Result { - default_path_for(&None) -} - -pub fn default_path_for(file: &Option) -> Result { - let mut filename = config_path()?; - let file: &Path = file.as_deref().unwrap_or_else(|| "config.toml".as_ref()); - filename.push(file); - - Ok(filename) -} - -pub fn user_data() -> Result { - use directories_next::ProjectDirs; - - let dir = ProjectDirs::from("org", "nushell", "nu") - .ok_or_else(|| ShellError::untagged_runtime_error("Couldn't find project directory"))?; - let path = ProjectDirs::data_local_dir(&dir).to_owned(); - std::fs::create_dir_all(&path).map_err(|err| { - ShellError::untagged_runtime_error(&format!( - "Couldn't create {} path:\n{}", - "user data", err - )) - })?; - - Ok(path) -} - -#[derive(Debug, Clone)] -pub enum Status { - LastModified(std::time::SystemTime), - Unavailable, -} - -impl Default for Status { - fn default() -> Self { - Status::Unavailable - } -} - -pub fn last_modified(at: &Option) -> Result> { - let filename = default_path()?; - - let filename = match at { - None => filename, - Some(ref file) => file.clone(), - }; - - if let Ok(time) = filename.metadata()?.modified() { - return Ok(Status::LastModified(time)); - } - - Ok(Status::Unavailable) -} - -pub fn read( - tag: impl Into, - at: &Option, -) -> Result, ShellError> { - let filename = default_path()?; - - let filename = match at { - None => filename, - Some(ref file) => file.clone(), - }; - - if !filename.exists() && touch(&filename).is_err() { - // If we can't create configs, let's just return an empty indexmap instead as we may be in - // a readonly environment - return Ok(IndexMap::new()); - } - - trace!("config file = {}", filename.display()); - - let tag = tag.into(); - let contents = fs::read_to_string(filename) - .map(|v| v.tagged(&tag)) - .map_err(|err| { - ShellError::labeled_error( - &format!("Couldn't read config file:\n{}", err), - "file name", - &tag, - ) - })?; - - let parsed: toml::Value = toml::from_str(&contents).map_err(|err| { - ShellError::labeled_error( - &format!("Couldn't parse config file:\n{}", err), - "file name", - &tag, - ) - })?; - - let value = convert_toml_value_to_nu_value(&parsed, tag); - let tag = value.tag(); - match value.value { - UntaggedValue::Row(Dictionary { entries }) => Ok(entries), - other => Err(ShellError::type_error( - "Dictionary", - other.type_name().spanned(tag.span), - )), - } -} - -pub fn config(tag: impl Into) -> Result, ShellError> { - read(tag, &None) -} - -pub fn write(config: &IndexMap, at: &Option) -> Result<(), ShellError> { - let filename = default_path()?; - - let filename = match at { - None => filename, - Some(ref file) => file.clone(), - }; - - let contents = value_to_toml_value( - &UntaggedValue::Row(Dictionary::new(config.clone())).into_untagged_value(), - )?; - - let contents = toml::to_string(&contents)?; - - fs::write(&filename, &contents)?; - - Ok(()) -} - -// A simple implementation of `% touch path` (ignores existing files) -fn touch(path: &Path) -> io::Result<()> { - match OpenOptions::new().create(true).write(true).open(path) { - Ok(_) => Ok(()), - Err(e) => Err(e), - } -} - -pub fn cfg_path_to_scope_tag(cfg_path: &Path) -> String { - cfg_path.to_string_lossy().to_string() -} diff --git a/old_nushell/crates/nu-data/src/config/conf.rs b/old_nushell/crates/nu-data/src/config/conf.rs deleted file mode 100644 index 784184eaa..000000000 --- a/old_nushell/crates/nu-data/src/config/conf.rs +++ /dev/null @@ -1,38 +0,0 @@ -use nu_errors::ShellError; -use nu_protocol::Value; -use std::{fmt::Debug, path::PathBuf}; - -pub trait Conf: Debug + Send { - fn is_modified(&self) -> Result>; - fn var(&self, key: &str) -> Option; - fn env(&self) -> Option; - fn path(&self) -> Result>, ShellError>; - fn clone_box(&self) -> Box; - fn reload(&mut self); -} - -impl Conf for Box { - fn is_modified(&self) -> Result> { - (**self).is_modified() - } - - fn var(&self, key: &str) -> Option { - (**self).var(key) - } - - fn env(&self) -> Option { - (**self).env() - } - - fn reload(&mut self) { - (**self).reload(); - } - - fn clone_box(&self) -> Box { - (**self).clone_box() - } - - fn path(&self) -> Result>, ShellError> { - (**self).path() - } -} diff --git a/old_nushell/crates/nu-data/src/config/config_trust.rs b/old_nushell/crates/nu-data/src/config/config_trust.rs deleted file mode 100644 index 98012cdf8..000000000 --- a/old_nushell/crates/nu-data/src/config/config_trust.rs +++ /dev/null @@ -1,44 +0,0 @@ -use serde::Deserialize; -use serde::Serialize; -use sha2::{Digest, Sha256}; -use std::{io::Read, path::Path, path::PathBuf}; - -use indexmap::IndexMap; -use nu_errors::ShellError; - -#[derive(Deserialize, Serialize, Debug, Default)] -pub struct Trusted { - pub files: IndexMap>, -} - -impl Trusted { - pub fn new() -> Self { - Trusted { - files: IndexMap::new(), - } - } -} - -pub fn is_file_trusted(nu_env_file: &Path, content: &[u8]) -> Result { - let contentdigest = Sha256::digest(content).as_slice().to_vec(); - let nufile = nu_path::canonicalize(nu_env_file)?; - - let trusted = read_trusted()?; - Ok(trusted.files.get(&nufile.to_string_lossy().to_string()) == Some(&contentdigest)) -} - -pub fn read_trusted() -> Result { - let config_path = crate::config::default_path_for(&Some(PathBuf::from("nu-env.toml")))?; - - let mut file = std::fs::OpenOptions::new() - .read(true) - .create(true) - .write(true) - .open(config_path) - .map_err(|_| ShellError::untagged_runtime_error("Couldn't open nu-env.toml"))?; - let mut doc = String::new(); - file.read_to_string(&mut doc)?; - - let allowed = toml::de::from_str(&doc).unwrap_or_else(|_| Trusted::new()); - Ok(allowed) -} diff --git a/old_nushell/crates/nu-data/src/config/local_config.rs b/old_nushell/crates/nu-data/src/config/local_config.rs deleted file mode 100644 index b96c1f809..000000000 --- a/old_nushell/crates/nu-data/src/config/local_config.rs +++ /dev/null @@ -1,150 +0,0 @@ -use nu_errors::ShellError; -use std::path::{Path, PathBuf}; - -static LOCAL_CFG_FILE_NAME: &str = ".nu-env"; - -pub struct LocalConfigDiff { - pub cfgs_to_load: Vec, - pub cfgs_to_unload: Vec, -} - -/// Finds all local configs between `from` up to `to`. -/// Every config seen while going up the filesystem (e.G. from `/foo` to `/foo/bar`) is returned -/// as a config to load -/// Every config seen while going down the filesystem (e.G. from `/foo/bar` to `/foo/bar`) is -/// returned as a config to unload -/// If both paths are unrelated to each other, (e.G. windows paths as: `C:/foo` and `D:/bar`) -/// this function first walks `from` completely down the filesystem and then it walks up until `to`. -/// -/// Both paths are required to be absolute. -impl LocalConfigDiff { - pub fn between(from: PathBuf, to: PathBuf) -> (LocalConfigDiff, Vec) { - let common_prefix = common_path::common_path(&from, &to); - let (cfgs_to_unload, err_down) = walk_down(&from, &common_prefix); - let (cfgs_to_load, err_up) = walk_up(&common_prefix, &to); - - ( - LocalConfigDiff { - cfgs_to_load, - cfgs_to_unload, - }, - err_down.into_iter().chain(err_up).collect(), - ) - } -} - -///Walks from the first parameter down the filesystem to the second parameter. Marking all -///configs found in directories on the way as to remove. -///If to is None, this method walks from the first parameter down to the beginning of the -///filesystem -///Returns tuple of (configs to remove, errors from io). -fn walk_down( - from_inclusive: &Path, - to_exclusive: &Option, -) -> (Vec, Vec) { - let mut all_err = vec![]; - let mut all_cfgs_to_unload = vec![]; - for dir in from_inclusive.ancestors().take_while(|cur_path| { - if let Some(until_path) = to_exclusive { - //Stop before `to_exclusive` - *cur_path != until_path - } else { - //No end, walk all the way down - true - } - }) { - match local_cfg_should_be_unloaded(dir.to_path_buf()) { - Ok(Some(cfg)) => all_cfgs_to_unload.push(cfg), - Err(e) => all_err.push(e), - _ => {} - } - } - - (all_cfgs_to_unload, all_err) -} - -///Walks from the first parameter up the filesystem to the second parameter, returns all configs -///found in directories on the way to load. -///Returns combined errors from checking directories on the way -///If from is None, this method walks from the beginning of the second parameter up to the -///second parameter -fn walk_up( - from_exclusive: &Option, - to_inclusive: &Path, -) -> (Vec, Vec) { - let mut all_err = vec![]; - let mut all_cfgs_to_load = vec![]; - - //skip all paths until (inclusive) from (or 0 if from is None) - let skip_ahead = from_exclusive - .as_ref() - .map(|p| p.ancestors().count()) - .unwrap_or(0); - //We have to traverse ancestors in reverse order (apply lower directories first) - //ancestors() does not yield iter with .rev() method. So we store all ancestors - //and then iterate over the vec - let dirs: Vec<_> = to_inclusive.ancestors().map(Path::to_path_buf).collect(); - for dir in dirs.iter().rev().skip(skip_ahead) { - match loadable_cfg_exists_in_dir(dir.clone()) { - Ok(Some(cfg)) => all_cfgs_to_load.push(cfg), - Err(e) => all_err.push(e), - _ => {} - } - } - - (all_cfgs_to_load, all_err) -} - -fn is_existent_local_cfg(cfg_file_path: &Path) -> Result { - if !cfg_file_path.exists() || cfg_file_path.parent() == super::default_path()?.parent() { - //Don't treat global cfg as local one - Ok(false) - } else { - Ok(true) - } -} - -fn is_trusted_local_cfg_content(cfg_file_path: &Path, content: &[u8]) -> Result { - //This checks whether user used `autoenv trust` to mark this cfg as secure - if !super::is_file_trusted(cfg_file_path, content)? { - //Notify user about present config, but not trusted - Err(ShellError::untagged_runtime_error( - format!("{:?} is untrusted. Run 'autoenv trust {:?}' to trust it.\nThis needs to be done after each change to the file.", - cfg_file_path, cfg_file_path.parent().unwrap_or_else(|| Path::new(""))))) - } else { - Ok(true) - } -} - -fn local_cfg_should_be_unloaded>(cfg_dir: P) -> Result, ShellError> { - let mut cfg = cfg_dir.as_ref().to_path_buf(); - cfg.push(LOCAL_CFG_FILE_NAME); - if is_existent_local_cfg(&cfg)? { - //No need to compute whether content is good. If it is not loaded before, unloading does - //nothing - Ok(Some(cfg)) - } else { - Ok(None) - } -} - -/// Checks whether a local_cfg exists in cfg_dir and returns: -/// Ok(Some(cfg_path)) if cfg exists and is good to load -/// Ok(None) if no cfg exists -/// Err(error) if cfg exits, but is not good to load -pub fn loadable_cfg_exists_in_dir(mut cfg_dir: PathBuf) -> Result, ShellError> { - cfg_dir.push(LOCAL_CFG_FILE_NAME); - let cfg_path = cfg_dir; - - if !is_existent_local_cfg(&cfg_path)? { - return Ok(None); - } - - let content = std::fs::read(&cfg_path)?; - - if !is_trusted_local_cfg_content(&cfg_path, &content)? { - return Ok(None); - } - - Ok(Some(cfg_path)) -} diff --git a/old_nushell/crates/nu-data/src/config/nuconfig.rs b/old_nushell/crates/nu-data/src/config/nuconfig.rs deleted file mode 100644 index 7cecb8e91..000000000 --- a/old_nushell/crates/nu-data/src/config/nuconfig.rs +++ /dev/null @@ -1,187 +0,0 @@ -use crate::config::{last_modified, read, Conf, Status}; -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_protocol::Value; -use nu_source::Tag; -use nu_test_support::NATIVE_PATH_ENV_VAR; -use std::{fmt::Debug, path::PathBuf}; - -use super::write; - -#[derive(Debug, Clone, Default)] -pub struct NuConfig { - pub vars: IndexMap, - pub file_path: PathBuf, - pub modified_at: Status, -} - -impl Conf for NuConfig { - fn is_modified(&self) -> Result> { - self.is_modified() - } - - fn var(&self, key: &str) -> Option { - self.var(key) - } - - fn env(&self) -> Option { - self.env() - } - - fn path(&self) -> Result>, ShellError> { - self.path() - } - - fn reload(&mut self) { - if let Ok(variables) = read(Tag::unknown(), &Some(self.file_path.clone())) { - self.vars = variables; - - self.modified_at = if let Ok(status) = last_modified(&Some(self.file_path.clone())) { - status - } else { - Status::Unavailable - }; - } - } - - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } -} - -impl NuConfig { - pub fn load(cfg_file_path: Option) -> Result { - let vars = read(Tag::unknown(), &cfg_file_path)?; - let modified_at = NuConfig::get_last_modified(&cfg_file_path); - let file_path = if let Some(file_path) = cfg_file_path { - file_path - } else { - crate::config::default_path()? - }; - - Ok(NuConfig { - vars, - file_path, - modified_at, - }) - } - - /// Writes self.values under self.file_path - pub fn write(&self) -> Result<(), ShellError> { - write(&self.vars, &Some(self.file_path.clone())) - } - - pub fn new() -> NuConfig { - let vars = if let Ok(variables) = read(Tag::unknown(), &None) { - variables - } else { - IndexMap::default() - }; - let path = if let Ok(path) = crate::config::default_path() { - path - } else { - PathBuf::new() - }; - - NuConfig { - vars, - modified_at: NuConfig::get_last_modified(&None), - file_path: path, - } - } - - pub fn get_last_modified(config_file: &Option) -> Status { - if let Ok(status) = last_modified(config_file) { - status - } else { - Status::Unavailable - } - } - - pub fn is_modified(&self) -> Result> { - let modified_at = &self.modified_at; - - Ok(match (NuConfig::get_last_modified(&None), modified_at) { - (Status::LastModified(left), Status::LastModified(right)) => { - let left = left.duration_since(std::time::UNIX_EPOCH)?; - let right = (*right).duration_since(std::time::UNIX_EPOCH)?; - - left != right - } - (_, _) => false, - }) - } - - pub fn var(&self, key: &str) -> Option { - let vars = &self.vars; - - if let Some(value) = vars.get(key) { - return Some(value.clone()); - } - - None - } - - /// Return environment variables as map - pub fn env_map(&self) -> IndexMap { - let mut result = IndexMap::new(); - if let Some(variables) = self.env() { - for var in variables.row_entries() { - if let Ok(value) = var.1.as_string() { - result.insert(var.0.clone(), value); - } - } - } - result - } - - pub fn env(&self) -> Option { - let vars = &self.vars; - - if let Some(env_vars) = vars.get("env") { - return Some(env_vars.clone()); - } - - None - } - - pub fn path(&self) -> Result>, ShellError> { - let vars = &self.vars; - - if let Some(path) = vars.get("path").or_else(|| vars.get(NATIVE_PATH_ENV_VAR)) { - path - .table_entries() - .map(|p| { - p.as_string().map(PathBuf::from).map_err(|_| { - ShellError::untagged_runtime_error("Could not format path entry as string!\nPath entry from config won't be added") - }) - }) - .collect::, ShellError>>().map(Some) - } else { - Ok(None) - } - } - - fn load_scripts_if_present(&self, scripts_name: &str) -> Result, ShellError> { - if let Some(array) = self.var(scripts_name) { - if !array.is_table() { - Err(ShellError::untagged_runtime_error(format!( - "expected an array of strings as {} commands", - scripts_name - ))) - } else { - array.table_entries().map(Value::as_string).collect() - } - } else { - Ok(vec![]) - } - } - - pub fn exit_scripts(&self) -> Result, ShellError> { - self.load_scripts_if_present("on_exit") - } - - pub fn startup_scripts(&self) -> Result, ShellError> { - self.load_scripts_if_present("startup") - } -} diff --git a/old_nushell/crates/nu-data/src/config/path.rs b/old_nushell/crates/nu-data/src/config/path.rs deleted file mode 100644 index 5a9fdb031..000000000 --- a/old_nushell/crates/nu-data/src/config/path.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::path::PathBuf; - -use super::NuConfig; - -const DEFAULT_LOCATION: &str = "history.txt"; - -pub fn default_history_path() -> PathBuf { - crate::config::user_data() - .map(|mut p| { - p.push(DEFAULT_LOCATION); - p - }) - .unwrap_or_else(|_| PathBuf::from(DEFAULT_LOCATION)) -} - -/// Get history path of config, if present -pub fn history_path(config: &NuConfig) -> Option { - config - .var("history-path") - .and_then(|custom_path| custom_path.as_string().map(PathBuf::from).ok()) -} - -/// Get history path in config or default -pub fn history_path_or_default(config: &NuConfig) -> PathBuf { - history_path(config).unwrap_or_else(default_history_path) -} diff --git a/old_nushell/crates/nu-data/src/config/tests.rs b/old_nushell/crates/nu-data/src/config/tests.rs deleted file mode 100644 index 9a8935537..000000000 --- a/old_nushell/crates/nu-data/src/config/tests.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::config::{Conf, NuConfig, Status}; -use nu_protocol::Value; -use std::path::{Path, PathBuf}; - -#[derive(Debug, Clone)] -pub struct FakeConfig { - pub config: NuConfig, - source_file: Option, -} - -impl Conf for FakeConfig { - fn is_modified(&self) -> Result> { - self.is_modified() - } - - fn var(&self, key: &str) -> Option { - self.config.var(key) - } - - fn env(&self) -> Option { - self.config.env() - } - - fn path(&self) -> Option { - self.config.path() - } - - fn reload(&mut self) { - self.reload() - } - - fn clone_box(&self) -> Box { - self.config.clone_box() - } -} - -impl FakeConfig { - pub fn new(config_file: &Path) -> FakeConfig { - let config_file = config_file.to_path_buf(); - - FakeConfig { - config: NuConfig::with(Some(config_file.clone().into_os_string())), - source_file: Some(config_file), - } - } - - pub fn is_modified(&self) -> Result> { - let modified_at = &self.config.modified_at; - - Ok( - match (NuConfig::get_last_modified(&self.source_file), modified_at) { - (Status::LastModified(left), Status::LastModified(right)) => { - let left = left.duration_since(std::time::UNIX_EPOCH)?; - let right = (*right).duration_since(std::time::UNIX_EPOCH)?; - - left != right - } - (_, _) => false, - }, - ) - } - - pub fn reload(&mut self) { - self.config = NuConfig::with(self.source_file.clone().map(|x| x.into_os_string())); - } -} diff --git a/old_nushell/crates/nu-data/src/dict.rs b/old_nushell/crates/nu-data/src/dict.rs deleted file mode 100644 index fa48110fc..000000000 --- a/old_nushell/crates/nu-data/src/dict.rs +++ /dev/null @@ -1,105 +0,0 @@ -use derive_new::new; -use nu_protocol::{Dictionary, MaybeOwned, Primitive, UntaggedValue, Value}; -use nu_source::{DbgDocBldr, DebugDocBuilder, PrettyDebug, Spanned, Tag}; - -#[derive(Debug, new)] -struct DebugEntry<'a> { - key: &'a str, - value: &'a Value, -} - -impl<'a> PrettyDebug for DebugEntry<'a> { - fn pretty(&self) -> DebugDocBuilder { - (DbgDocBldr::key(self.key.to_string()) - + DbgDocBldr::equals() - + self.value.pretty().into_value()) - .group() - } -} - -pub trait DictionaryExt { - fn get_data(&self, desc: &str) -> MaybeOwned<'_, Value>; - - fn keys(&self) -> indexmap::map::Keys; - fn get_data_by_key(&self, name: Spanned<&str>) -> Option; - fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value>; - fn insert_data_at_key(&mut self, name: &str, value: Value); -} - -impl DictionaryExt for Dictionary { - fn get_data(&self, desc: &str) -> MaybeOwned<'_, Value> { - match self.entries.get(desc) { - Some(v) => MaybeOwned::Borrowed(v), - None => MaybeOwned::Owned( - UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(), - ), - } - } - - fn keys(&self) -> indexmap::map::Keys { - self.entries.keys() - } - - fn get_data_by_key(&self, name: Spanned<&str>) -> Option { - let result = self - .entries - .iter() - .find(|&(desc_name, _)| desc_name == name.item)? - .1; - - Some( - result - .value - .clone() - .into_value(Tag::new(result.anchor(), name.span)), - ) - } - - fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> { - self.entries - .iter_mut() - .find(|&(desc_name, _)| desc_name == name) - .map_or_else(|| None, |x| Some(x.1)) - } - - fn insert_data_at_key(&mut self, name: &str, value: Value) { - self.entries.insert(name.to_string(), value); - } -} - -#[derive(Debug)] -pub struct TaggedListBuilder { - tag: Tag, - pub list: Vec, -} - -impl TaggedListBuilder { - pub fn new(tag: impl Into) -> TaggedListBuilder { - TaggedListBuilder { - tag: tag.into(), - list: vec![], - } - } - - pub fn push_value(&mut self, value: impl Into) { - self.list.push(value.into()); - } - - pub fn push_untagged(&mut self, value: impl Into) { - self.list.push(value.into().into_value(self.tag.clone())); - } - - pub fn into_value(self) -> Value { - UntaggedValue::Table(self.list).into_value(self.tag) - } - - pub fn into_untagged_value(self) -> UntaggedValue { - UntaggedValue::Table(self.list).into_value(self.tag).value - } -} - -impl From for Value { - fn from(input: TaggedListBuilder) -> Value { - input.into_value() - } -} diff --git a/old_nushell/crates/nu-data/src/keybinding.rs b/old_nushell/crates/nu-data/src/keybinding.rs deleted file mode 100644 index 9c36d463c..000000000 --- a/old_nushell/crates/nu-data/src/keybinding.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub fn keybinding_path() -> Result { - crate::config::default_path_for(&Some(std::path::PathBuf::from("keybindings.yml"))) -} diff --git a/old_nushell/crates/nu-data/src/lib.rs b/old_nushell/crates/nu-data/src/lib.rs deleted file mode 100644 index 44d0862bb..000000000 --- a/old_nushell/crates/nu-data/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod base; -pub mod config; -pub mod dict; -pub mod keybinding; -pub mod primitive; -pub mod utils; -pub mod value; - -pub use dict::TaggedListBuilder; diff --git a/old_nushell/crates/nu-data/src/primitive.rs b/old_nushell/crates/nu-data/src/primitive.rs deleted file mode 100644 index 3d0ad340c..000000000 --- a/old_nushell/crates/nu-data/src/primitive.rs +++ /dev/null @@ -1,378 +0,0 @@ -use crate::config::NuConfig; -use nu_ansi_term::{Color, Style}; -use nu_protocol::{hir::Number, Primitive, Value}; -use nu_table::{Alignment, TextStyle}; -use std::collections::HashMap; - -pub fn number(number: impl Into) -> Primitive { - let number = number.into(); - - match number { - Number::BigInt(int) => Primitive::BigInt(int), - Number::Int(int) => Primitive::Int(int), - Number::Decimal(decimal) => Primitive::Decimal(decimal), - } -} - -pub fn lookup_ansi_color_style(s: String) -> Style { - match s.as_str() { - "g" | "green" => Color::Green.normal(), - "gb" | "green_bold" => Color::Green.bold(), - "gu" | "green_underline" => Color::Green.underline(), - "gi" | "green_italic" => Color::Green.italic(), - "gd" | "green_dimmed" => Color::Green.dimmed(), - "gr" | "green_reverse" => Color::Green.reverse(), - "gbl" | "green_blink" => Color::Green.blink(), - "gst" | "green_strike" => Color::Green.strikethrough(), - "r" | "red" => Color::Red.normal(), - "rb" | "red_bold" => Color::Red.bold(), - "ru" | "red_underline" => Color::Red.underline(), - "ri" | "red_italic" => Color::Red.italic(), - "rd" | "red_dimmed" => Color::Red.dimmed(), - "rr" | "red_reverse" => Color::Red.reverse(), - "rbl" | "red_blink" => Color::Red.blink(), - "rst" | "red_strike" => Color::Red.strikethrough(), - "u" | "blue" => Color::Blue.normal(), - "ub" | "blue_bold" => Color::Blue.bold(), - "uu" | "blue_underline" => Color::Blue.underline(), - "ui" | "blue_italic" => Color::Blue.italic(), - "ud" | "blue_dimmed" => Color::Blue.dimmed(), - "ur" | "blue_reverse" => Color::Blue.reverse(), - "ubl" | "blue_blink" => Color::Blue.blink(), - "ust" | "blue_strike" => Color::Blue.strikethrough(), - "b" | "black" => Color::Black.normal(), - "bb" | "black_bold" => Color::Black.bold(), - "bu" | "black_underline" => Color::Black.underline(), - "bi" | "black_italic" => Color::Black.italic(), - "bd" | "black_dimmed" => Color::Black.dimmed(), - "br" | "black_reverse" => Color::Black.reverse(), - "bbl" | "black_blink" => Color::Black.blink(), - "bst" | "black_strike" => Color::Black.strikethrough(), - "y" | "yellow" => Color::Yellow.normal(), - "yb" | "yellow_bold" => Color::Yellow.bold(), - "yu" | "yellow_underline" => Color::Yellow.underline(), - "yi" | "yellow_italic" => Color::Yellow.italic(), - "yd" | "yellow_dimmed" => Color::Yellow.dimmed(), - "yr" | "yellow_reverse" => Color::Yellow.reverse(), - "ybl" | "yellow_blink" => Color::Yellow.blink(), - "yst" | "yellow_strike" => Color::Yellow.strikethrough(), - "p" | "purple" => Color::Purple.normal(), - "pb" | "purple_bold" => Color::Purple.bold(), - "pu" | "purple_underline" => Color::Purple.underline(), - "pi" | "purple_italic" => Color::Purple.italic(), - "pd" | "purple_dimmed" => Color::Purple.dimmed(), - "pr" | "purple_reverse" => Color::Purple.reverse(), - "pbl" | "purple_blink" => Color::Purple.blink(), - "pst" | "purple_strike" => Color::Purple.strikethrough(), - "c" | "cyan" => Color::Cyan.normal(), - "cb" | "cyan_bold" => Color::Cyan.bold(), - "cu" | "cyan_underline" => Color::Cyan.underline(), - "ci" | "cyan_italic" => Color::Cyan.italic(), - "cd" | "cyan_dimmed" => Color::Cyan.dimmed(), - "cr" | "cyan_reverse" => Color::Cyan.reverse(), - "cbl" | "cyan_blink" => Color::Cyan.blink(), - "cst" | "cyan_strike" => Color::Cyan.strikethrough(), - "w" | "white" => Color::White.normal(), - "wb" | "white_bold" => Color::White.bold(), - "wu" | "white_underline" => Color::White.underline(), - "wi" | "white_italic" => Color::White.italic(), - "wd" | "white_dimmed" => Color::White.dimmed(), - "wr" | "white_reverse" => Color::White.reverse(), - "wbl" | "white_blink" => Color::White.blink(), - "wst" | "white_strike" => Color::White.strikethrough(), - _ => Color::White.normal(), - } -} - -pub fn string_to_lookup_value(str_prim: &str) -> String { - match str_prim { - "primitive_int" => "Primitive::Int".to_string(), - "primitive_decimal" => "Primitive::Decimal".to_string(), - "primitive_filesize" => "Primitive::Filesize".to_string(), - "primitive_string" => "Primitive::String".to_string(), - "primitive_line" => "Primitive::Line".to_string(), - "primitive_columnpath" => "Primitive::ColumnPath".to_string(), - "primitive_pattern" => "Primitive::GlobPattern".to_string(), - "primitive_boolean" => "Primitive::Boolean".to_string(), - "primitive_date" => "Primitive::Date".to_string(), - "primitive_duration" => "Primitive::Duration".to_string(), - "primitive_range" => "Primitive::Range".to_string(), - "primitive_path" => "Primitive::FilePath".to_string(), - "primitive_binary" => "Primitive::Binary".to_string(), - "separator_color" => "separator_color".to_string(), - "header_align" => "header_align".to_string(), - "header_color" => "header_color".to_string(), - "header_style" => "header_style".to_string(), - "index_color" => "index_color".to_string(), - "leading_trailing_space_bg" => "leading_trailing_space_bg".to_string(), - _ => "Primitive::Nothing".to_string(), - } -} - -fn update_hashmap(key: &str, val: &Value, hm: &mut HashMap) { - if let Ok(var) = val.as_string() { - let color = lookup_ansi_color_style(var); - let prim = string_to_lookup_value(key); - if let Some(v) = hm.get_mut(&prim) { - *v = color; - } else { - hm.insert(prim, color); - } - } -} - -pub fn get_color_config(config: &NuConfig) -> HashMap { - let config = &config.vars; - - // create the hashmap - let mut hm: HashMap = HashMap::new(); - // set some defaults - hm.insert("primitive_int".to_string(), Color::White.normal()); - hm.insert("primitive_decimal".to_string(), Color::White.normal()); - hm.insert("primitive_filesize".to_string(), Color::White.normal()); - hm.insert("primitive_string".to_string(), Color::White.normal()); - hm.insert("primitive_line".to_string(), Color::White.normal()); - hm.insert("primitive_columnpath".to_string(), Color::White.normal()); - hm.insert("primitive_pattern".to_string(), Color::White.normal()); - hm.insert("primitive_boolean".to_string(), Color::White.normal()); - hm.insert("primitive_date".to_string(), Color::White.normal()); - hm.insert("primitive_duration".to_string(), Color::White.normal()); - hm.insert("primitive_range".to_string(), Color::White.normal()); - hm.insert("primitive_path".to_string(), Color::White.normal()); - hm.insert("primitive_binary".to_string(), Color::White.normal()); - hm.insert("separator_color".to_string(), Color::White.normal()); - hm.insert("header_align".to_string(), Color::Green.bold()); - hm.insert("header_color".to_string(), Color::Green.bold()); - hm.insert("header_style".to_string(), Style::default()); - hm.insert("index_color".to_string(), Color::Green.bold()); - hm.insert( - "leading_trailing_space_bg".to_string(), - Style::default().on(Color::Rgb(128, 128, 128)), - ); - - // populate hashmap from config values - if let Some(primitive_color_vars) = config.get("color_config") { - for (key, value) in primitive_color_vars.row_entries() { - match key.as_ref() { - "primitive_int" => { - update_hashmap(key, value, &mut hm); - } - "primitive_decimal" => { - update_hashmap(key, value, &mut hm); - } - "primitive_filesize" => { - update_hashmap(key, value, &mut hm); - } - "primitive_string" => { - update_hashmap(key, value, &mut hm); - } - "primitive_line" => { - update_hashmap(key, value, &mut hm); - } - "primitive_columnpath" => { - update_hashmap(key, value, &mut hm); - } - "primitive_pattern" => { - update_hashmap(key, value, &mut hm); - } - "primitive_boolean" => { - update_hashmap(key, value, &mut hm); - } - "primitive_date" => { - update_hashmap(key, value, &mut hm); - } - "primitive_duration" => { - update_hashmap(key, value, &mut hm); - } - "primitive_range" => { - update_hashmap(key, value, &mut hm); - } - "primitive_path" => { - update_hashmap(key, value, &mut hm); - } - "primitive_binary" => { - update_hashmap(key, value, &mut hm); - } - "separator_color" => { - update_hashmap(key, value, &mut hm); - } - "header_align" => { - update_hashmap(key, value, &mut hm); - } - "header_color" => { - update_hashmap(key, value, &mut hm); - } - "header_style" => { - update_hashmap(key, value, &mut hm); - } - "index_color" => { - update_hashmap(key, value, &mut hm); - } - "leading_trailing_space_bg" => { - update_hashmap(key, value, &mut hm); - } - _ => (), - } - } - } - - hm -} - -// This function will assign a text style to a primitive, or really any string that's -// in the hashmap. The hashmap actually contains the style to be applied. -pub fn style_primitive(primitive: &str, color_hm: &HashMap) -> TextStyle { - match primitive { - "Int" => { - let style = color_hm.get("Primitive::Int"); - match style { - Some(s) => TextStyle::with_style(Alignment::Right, *s), - None => TextStyle::basic_right(), - } - } - "Decimal" => { - let style = color_hm.get("Primitive::Decimal"); - match style { - Some(s) => TextStyle::with_style(Alignment::Right, *s), - None => TextStyle::basic_right(), - } - } - "Filesize" => { - let style = color_hm.get("Primitive::Filesize"); - match style { - Some(s) => TextStyle::with_style(Alignment::Right, *s), - None => TextStyle::basic_right(), - } - } - "String" => { - let style = color_hm.get("Primitive::String"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "Line" => { - let style = color_hm.get("Primitive::Line"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "ColumnPath" => { - let style = color_hm.get("Primitive::ColumnPath"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "GlobPattern" => { - let style = color_hm.get("Primitive::GlobPattern"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "Boolean" => { - let style = color_hm.get("Primitive::Boolean"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "Date" => { - let style = color_hm.get("Primitive::Date"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "Duration" => { - let style = color_hm.get("Primitive::Duration"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "Range" => { - let style = color_hm.get("Primitive::Range"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "FilePath" => { - let style = color_hm.get("Primitive::FilePath"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "Binary" => { - let style = color_hm.get("Primitive::Binary"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "BeginningOfStream" => { - let style = color_hm.get("Primitive::BeginningOfStream"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "EndOfStream" => { - let style = color_hm.get("Primitive::EndOfStream"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "Nothing" => { - let style = color_hm.get("Primitive::Nothing"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "separator_color" => { - let style = color_hm.get("separator"); - match style { - Some(s) => TextStyle::with_style(Alignment::Left, *s), - None => TextStyle::basic_left(), - } - } - "header_align" => { - let style = color_hm.get("header_align"); - match style { - Some(s) => TextStyle::with_style(Alignment::Center, *s), - None => TextStyle::default_header(), - } - } - "header_color" => { - let style = color_hm.get("header_color"); - match style { - Some(s) => TextStyle::with_style(Alignment::Center, *s), - None => TextStyle::default_header().bold(Some(true)), - } - } - "header_style" => { - let style = color_hm.get("header_style"); - match style { - Some(s) => TextStyle::with_style(Alignment::Center, *s), - None => TextStyle::default_header(), - } - } - "index_color" => { - let style = color_hm.get("index_color"); - match style { - Some(s) => TextStyle::with_style(Alignment::Right, *s), - None => TextStyle::new() - .alignment(Alignment::Right) - .fg(Color::Green) - .bold(Some(true)), - } - } - _ => TextStyle::basic_center(), - } -} diff --git a/old_nushell/crates/nu-data/src/utils/group.rs b/old_nushell/crates/nu-data/src/utils/group.rs deleted file mode 100644 index 75c020887..000000000 --- a/old_nushell/crates/nu-data/src/utils/group.rs +++ /dev/null @@ -1,35 +0,0 @@ -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tag; -use nu_value_ext::as_string; - -#[allow(clippy::type_complexity)] -pub fn group( - values: &Value, - grouper: &Option Result + Send>>, - tag: impl Into, -) -> Result { - let tag = tag.into(); - - let mut groups: IndexMap> = IndexMap::new(); - - for (idx, value) in values.table_entries().enumerate() { - let group_key = if let Some(ref grouper) = grouper { - grouper(idx, value) - } else { - as_string(value) - }; - - let group = groups.entry(group_key?).or_insert(vec![]); - group.push((*value).clone()); - } - - let mut out = TaggedDictBuilder::new(&tag); - - for (k, v) in &groups { - out.insert_untagged(k, UntaggedValue::table(v)); - } - - Ok(out.into_value()) -} diff --git a/old_nushell/crates/nu-data/src/utils/internal.rs b/old_nushell/crates/nu-data/src/utils/internal.rs deleted file mode 100644 index b9b05ef65..000000000 --- a/old_nushell/crates/nu-data/src/utils/internal.rs +++ /dev/null @@ -1,332 +0,0 @@ -#![allow(clippy::type_complexity)] - -use crate::value::unsafe_compute_values; -use derive_new::new; -use nu_errors::ShellError; -use nu_protocol::hir::Operator; -use nu_protocol::{UntaggedValue, Value}; -use nu_source::{SpannedItem, Tag, TaggedItem}; -use nu_value_ext::ValueExt; - -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new)] -pub struct Labels { - pub x: Vec, - pub y: Vec, -} - -impl Labels { - pub fn at(&self, idx: usize) -> Option<&str> { - self.x.get(idx).map(|k| &k[..]) - } - - pub fn at_split(&self, idx: usize) -> Option<&str> { - self.y.get(idx).map(|k| &k[..]) - } - - pub fn grouped(&self) -> impl Iterator { - self.x.iter() - } - - pub fn grouping_total(&self) -> Value { - UntaggedValue::int(self.x.len() as i64).into_untagged_value() - } - - pub fn splits(&self) -> impl Iterator { - self.y.iter() - } - - pub fn splits_total(&self) -> Value { - UntaggedValue::big_int(self.y.len()).into_untagged_value() - } -} - -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new)] -pub struct Range { - pub start: Value, - pub end: Value, -} - -fn formula( - acc_begin: Value, - calculator: Box) -> Result + Send + Sync + 'static>, -) -> Box) -> Result + Send + Sync + 'static> { - Box::new(move |acc, datax| -> Result { - let result = match unsafe_compute_values(Operator::Multiply, acc, &acc_begin) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned_unknown(), - right_type.spanned_unknown(), - )) - } - }; - - match calculator(datax) { - Ok(total) => Ok( - match unsafe_compute_values(Operator::Plus, &result, &total) { - Ok(v) => v.into_untagged_value(), - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned_unknown(), - right_type.spanned_unknown(), - )) - } - }, - ), - Err(reason) => Err(reason), - } - }) -} - -pub fn reducer_for( - command: &Reduction, -) -> Box) -> Result + Send + Sync + 'static> { - match command { - Reduction::Accumulate => Box::new(formula( - UntaggedValue::int(1).into_untagged_value(), - Box::new(sum), - )), - Reduction::Count => Box::new(formula( - UntaggedValue::int(0).into_untagged_value(), - Box::new(sum), - )), - } -} - -pub fn max(values: &Value, tag: impl Into) -> Result { - let tag = tag.into(); - - let mut x = UntaggedValue::int(0); - - for split in values.table_entries() { - match split.value { - UntaggedValue::Table(ref values) => { - let inner = inner_max(values)?; - - if let Ok(greater_than) = - crate::value::compare_values(Operator::GreaterThan, &inner.value, &x) - { - if greater_than { - x = inner.value.clone(); - } - } else { - return Err(ShellError::unexpected(format!( - "Could not compare\nleft: {:?}\nright: {:?}", - inner.value, x - ))); - } - } - _ => { - return Err(ShellError::labeled_error( - "Attempted to compute the sum of a value that cannot be summed.", - "value appears here", - split.tag.span, - )) - } - } - } - - Ok(x.into_value(&tag)) -} - -pub fn inner_max(data: &[Value]) -> Result { - let mut biggest = data - .first() - .ok_or_else(|| { - ShellError::unexpected("Cannot perform aggregate math operation on empty data") - })? - .value - .clone(); - - for value in data { - if let Ok(greater_than) = - crate::value::compare_values(Operator::GreaterThan, &value.value, &biggest) - { - if greater_than { - biggest = value.value.clone(); - } - } else { - return Err(ShellError::unexpected(format!( - "Could not compare\nleft: {:?}\nright: {:?}", - biggest, value.value - ))); - } - } - Ok(Value { - value: biggest, - tag: Tag::unknown(), - }) -} - -pub fn sum(data: Vec<&Value>) -> Result { - let mut acc = UntaggedValue::int(0); - - for value in data { - match value.value { - UntaggedValue::Primitive(_) => { - acc = match unsafe_compute_values(Operator::Plus, &acc, value) { - Ok(v) => v, - Err((left_type, right_type)) => { - return Err(ShellError::coerce_error( - left_type.spanned_unknown(), - right_type.spanned_unknown(), - )) - } - }; - } - _ => { - return Err(ShellError::labeled_error( - "Attempted to compute the sum of a value that cannot be summed.", - "value appears here", - value.tag.span, - )) - } - } - } - Ok(acc.into_untagged_value()) -} - -pub fn sort_columns( - values: &[String], - format: &Option Result>>, -) -> Result, ShellError> { - let mut keys = values.to_vec(); - - if format.is_none() { - keys.sort(); - } - - Ok(keys) -} - -pub fn sort(planes: &Labels, values: &Value, tag: impl Into) -> Result { - let tag = tag.into(); - - let mut x = vec![]; - for column in planes.splits() { - let key = column.clone().tagged_unknown(); - let groups = values - .get_data_by_key(key.borrow_spanned()) - .ok_or_else(|| { - ShellError::labeled_error("unknown column", "unknown column", key.span()) - })?; - - let mut y = vec![]; - for inner_column in planes.grouped() { - let key = inner_column.clone().tagged_unknown(); - let grouped = groups.get_data_by_key(key.borrow_spanned()); - - if let Some(grouped) = grouped { - y.push(grouped); - } else { - y.push(UntaggedValue::Table(vec![]).into_value(&tag)); - } - } - - x.push(UntaggedValue::table(&y).into_value(&tag)); - } - - Ok(UntaggedValue::table(&x).into_value(&tag)) -} - -pub fn evaluate( - values: &Value, - evaluator: &Option Result + Send>>, - tag: impl Into, -) -> Result { - let tag = tag.into(); - - let mut x = vec![]; - for split in values.table_entries() { - let mut y = vec![]; - - for (idx, subset) in split.table_entries().enumerate() { - if let UntaggedValue::Table(values) = &subset.value { - if let Some(ref evaluator) = evaluator { - let mut evaluations = vec![]; - - for set in values { - evaluations.push(evaluator(idx, set)?); - } - - y.push(UntaggedValue::Table(evaluations).into_value(&tag)); - } else { - y.push( - UntaggedValue::Table( - values - .iter() - .map(|_| UntaggedValue::int(1).into_value(&tag)) - .collect::>(), - ) - .into_value(&tag), - ); - } - } - } - - x.push(UntaggedValue::table(&y).into_value(&tag)); - } - - Ok(UntaggedValue::table(&x).into_value(&tag)) -} - -pub enum Reduction { - Count, - Accumulate, -} - -pub fn reduce( - values: &Value, - reduction_with: &Reduction, - tag: impl Into, -) -> Result { - let tag = tag.into(); - let reduce_with = reducer_for(reduction_with); - - let mut datasets = vec![]; - for dataset in values.table_entries() { - let mut acc = UntaggedValue::int(0).into_value(&tag); - - let mut subsets = vec![]; - for subset in dataset.table_entries() { - acc = reduce_with(&acc, subset.table_entries().collect::>())?; - subsets.push(acc.clone()); - } - datasets.push(UntaggedValue::table(&subsets).into_value(&tag)); - } - - Ok(UntaggedValue::table(&datasets).into_value(&tag)) -} - -pub fn percentages( - maxima: &Value, - values: &Value, - tag: impl Into, -) -> Result { - let tag = tag.into(); - - let mut x = vec![]; - for split in values.table_entries() { - x.push( - UntaggedValue::table( - &split - .table_entries() - .filter_map(|s| { - let hundred = UntaggedValue::decimal_from_float(100.0, tag.span); - - match unsafe_compute_values(Operator::Divide, &hundred, maxima) { - Ok(v) => match unsafe_compute_values(Operator::Multiply, s, &v) { - Ok(v) => Some(v.into_untagged_value()), - Err(_) => None, - }, - Err(_) => None, - } - }) - .collect::>(), - ) - .into_value(&tag), - ); - } - - Ok(UntaggedValue::table(&x).into_value(&tag)) -} diff --git a/old_nushell/crates/nu-data/src/utils/mod.rs b/old_nushell/crates/nu-data/src/utils/mod.rs deleted file mode 100644 index d2712b14d..000000000 --- a/old_nushell/crates/nu-data/src/utils/mod.rs +++ /dev/null @@ -1,292 +0,0 @@ -pub mod group; -pub mod split; - -mod internal; - -pub use crate::utils::group::group; -pub use crate::utils::split::split; - -pub use crate::utils::internal::Reduction; -use crate::utils::internal::*; - -use derive_new::new; -use getset::Getters; -use nu_errors::ShellError; -use nu_protocol::{UntaggedValue, Value}; -use nu_source::Tag; - -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Getters, Clone, new)] -pub struct Model { - pub labels: Labels, - pub ranges: (Range, Range), - - pub data: Value, - pub percentages: Value, -} - -#[allow(clippy::type_complexity)] -pub struct Operation<'a> { - pub grouper: Option Result + Send>>, - pub splitter: Option Result + Send>>, - pub format: &'a Option Result>>, - pub eval: &'a Option Result + Send>>, - pub reduction: &'a Reduction, -} - -pub fn report( - values: &Value, - options: Operation, - tag: impl Into, -) -> Result { - let tag = tag.into(); - - let grouped = group(values, &options.grouper, &tag)?; - let splitted = split(&grouped, &options.splitter, &tag)?; - - let x = grouped - .row_entries() - .map(|(key, _)| key.clone()) - .collect::>(); - - let x = sort_columns(&x, options.format)?; - - let mut y = splitted - .row_entries() - .map(|(key, _)| key.clone()) - .collect::>(); - - y.sort(); - - let planes = Labels { x, y }; - - let sorted = sort(&planes, &splitted, &tag)?; - - let evaluated = evaluate( - &sorted, - if options.eval.is_some() { - options.eval - } else { - &None - }, - &tag, - )?; - - let group_labels = planes.grouping_total(); - - let reduced = reduce(&evaluated, options.reduction, &tag)?; - - let maxima = max(&reduced, &tag)?; - - let percents = percentages(&maxima, &reduced, &tag)?; - - Ok(Model { - labels: planes, - ranges: ( - Range { - start: UntaggedValue::int(0).into_untagged_value(), - end: group_labels, - }, - Range { - start: UntaggedValue::int(0).into_untagged_value(), - end: maxima, - }, - ), - data: reduced, - percentages: percents, - }) -} - -pub mod helpers { - use nu_errors::ShellError; - use nu_protocol::{row, Value}; - use nu_source::{Tag, TaggedItem}; - use nu_test_support::value::{date, int, string, table}; - use nu_value_ext::ValueExt; - - pub fn committers() -> Vec { - vec![ - row! { - "date".into() => date("2019-07-23"), - "name".into() => string("AR"), - "country".into() => string("EC"), - "chickens".into() => int(10) - }, - row! { - "date".into() => date("2019-07-23"), - "name".into() => string("JT"), - "country".into() => string("NZ"), - "chickens".into() => int(5) - }, - row! { - "date".into() => date("2019-10-10"), - "name".into() => string("YK"), - "country".into() => string("US"), - "chickens".into() => int(6) - }, - row! { - "date".into() => date("2019-09-24"), - "name".into() => string("AR"), - "country".into() => string("EC"), - "chickens".into() => int(20) - }, - row! { - "date".into() => date("2019-10-10"), - "name".into() => string("JT"), - "country".into() => string("NZ"), - "chickens".into() => int(15) - }, - row! { - "date".into() => date("2019-09-24"), - "name".into() => string("YK"), - "country".into() => string("US"), - "chickens".into() => int(4) - }, - row! { - "date".into() => date("2019-10-10"), - "name".into() => string("AR"), - "country".into() => string("EC"), - "chickens".into() => int(30) - }, - row! { - "date".into() => date("2019-09-24"), - "name".into() => string("JT"), - "country".into() => string("NZ"), - "chickens".into() => int(10) - }, - row! { - "date".into() => date("2019-07-23"), - "name".into() => string("YK"), - "country".into() => string("US"), - "chickens".into() => int(2) - }, - ] - } - - pub fn committers_grouped_by_date() -> Value { - let sample = table(&committers()); - - let grouper = Box::new(move |_, row: &Value| { - let key = String::from("date").tagged_unknown(); - let group_key = row - .get_data_by_key(key.borrow_spanned()) - .expect("get key failed"); - - group_key.format("%Y-%m-%d") - }); - - crate::utils::group(&sample, &Some(grouper), Tag::unknown()) - .expect("failed to create group") - } - - pub fn date_formatter( - fmt: String, - ) -> Box Result> { - Box::new(move |date: &Value, _: String| { - let fmt = fmt.clone(); - date.format(&fmt) - }) - } -} - -#[cfg(test)] -mod tests { - use super::helpers::{committers, date_formatter}; - use super::{report, Labels, Model, Operation, Range, Reduction}; - use nu_errors::ShellError; - use nu_protocol::Value; - use nu_source::{Tag, TaggedItem}; - use nu_test_support::value::{decimal_from_float, int, table}; - use nu_value_ext::ValueExt; - - pub fn assert_without_checking_percentages(report_a: Model, report_b: Model) { - assert_eq!(report_a.labels.x, report_b.labels.x); - assert_eq!(report_a.labels.y, report_b.labels.y); - assert_eq!(report_a.ranges, report_b.ranges); - assert_eq!(report_a.data, report_b.data); - } - - #[test] - fn prepares_report_using_counting_value() { - let committers = table(&committers()); - - let by_date = Box::new(move |_, row: &Value| { - let key = String::from("date").tagged_unknown(); - let key = row.get_data_by_key(key.borrow_spanned()).unwrap(); - - let callback = date_formatter("%Y-%m-%d".to_string()); - callback(&key, "nothing".to_string()) - }); - - let by_country = Box::new(move |_, row: &Value| { - let key = String::from("country").tagged_unknown(); - let key = row.get_data_by_key(key.borrow_spanned()).unwrap(); - nu_value_ext::as_string(&key) - }); - - let options = Operation { - grouper: Some(by_date), - splitter: Some(by_country), - format: &None, - eval: /* value to be used for accumulation */ &Some(Box::new(move |_, value: &Value| { - let chickens_key = String::from("chickens").tagged_unknown(); - - value - .get_data_by_key(chickens_key.borrow_spanned()) - .ok_or_else(|| { - ShellError::labeled_error( - "unknown column", - "unknown column", - chickens_key.span(), - ) - }) - })), - reduction: &Reduction::Count - }; - - assert_without_checking_percentages( - report(&committers, options, Tag::unknown()).unwrap(), - Model { - labels: Labels { - x: vec![ - String::from("2019-07-23"), - String::from("2019-09-24"), - String::from("2019-10-10"), - ], - y: vec![String::from("EC"), String::from("NZ"), String::from("US")], - }, - ranges: ( - Range { - start: int(0), - end: int(3), - }, - Range { - start: int(0), - end: int(30), - }, - ), - data: table(&[ - table(&[int(10), int(20), int(30)]), - table(&[int(5), int(10), int(15)]), - table(&[int(2), int(4), int(6)]), - ]), - percentages: table(&[ - table(&[ - decimal_from_float(33.33), - decimal_from_float(66.66), - decimal_from_float(99.99), - ]), - table(&[ - decimal_from_float(16.66), - decimal_from_float(33.33), - decimal_from_float(49.99), - ]), - table(&[ - decimal_from_float(6.66), - decimal_from_float(13.33), - decimal_from_float(19.99), - ]), - ]), - }, - ); - } -} diff --git a/old_nushell/crates/nu-data/src/utils/split.rs b/old_nushell/crates/nu-data/src/utils/split.rs deleted file mode 100644 index 94c43befd..000000000 --- a/old_nushell/crates/nu-data/src/utils/split.rs +++ /dev/null @@ -1,59 +0,0 @@ -use nu_errors::ShellError; -use nu_protocol::{SpannedTypeName, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::Tag; - -use crate::utils::group; - -#[allow(clippy::type_complexity)] -pub fn split( - value: &Value, - splitter: &Option Result + Send>>, - tag: impl Into, -) -> Result { - let tag = tag.into(); - - let mut splits = indexmap::IndexMap::new(); - let mut out = TaggedDictBuilder::new(&tag); - - if splitter.is_none() { - out.insert_untagged("table", value.clone()); - return Ok(out.into_value()); - } - - for (column, value) in value.row_entries() { - if !&value.is_table() { - return Err(ShellError::type_error( - "a table value", - value.spanned_type_name(), - )); - } - - match group(value, splitter, &tag) { - Ok(grouped) => { - for (split_label, subset) in grouped.row_entries() { - let s = splits - .entry(split_label.clone()) - .or_insert(indexmap::IndexMap::new()); - - if !&subset.is_table() { - return Err(ShellError::type_error( - "a table value", - subset.spanned_type_name(), - )); - } - - s.insert(column.clone(), subset.clone()); - } - } - Err(err) => return Err(err), - } - } - - let mut out = TaggedDictBuilder::new(&tag); - - for (k, v) in splits { - out.insert_untagged(k, UntaggedValue::row(v)); - } - - Ok(out.into_value()) -} diff --git a/old_nushell/crates/nu-data/src/value.rs b/old_nushell/crates/nu-data/src/value.rs deleted file mode 100644 index c4e85016c..000000000 --- a/old_nushell/crates/nu-data/src/value.rs +++ /dev/null @@ -1,838 +0,0 @@ -use crate::base::coerce_compare; -use crate::base::shape::{Column, InlineShape}; -use crate::primitive::style_primitive; -use bigdecimal::Signed; -use chrono::{DateTime, NaiveDate, Utc}; -use nu_errors::ShellError; -use nu_protocol::hir::Operator; -use nu_protocol::ShellTypeName; -use nu_protocol::{Primitive, Type, UntaggedValue}; -use nu_source::{DebugDocBuilder, PrettyDebug, Span, Tagged}; -use nu_table::TextStyle; -use num_bigint::BigInt; -use num_bigint::ToBigInt; -use num_traits::{ToPrimitive, Zero}; -use std::collections::HashMap; - -pub struct Date; - -impl Date { - pub fn from_regular_str(s: Tagged<&str>) -> Result { - let date = DateTime::parse_from_rfc3339(s.item).map_err(|err| { - ShellError::labeled_error( - &format!("Date parse error: {}", err), - "original value", - s.tag, - ) - })?; - - let date = date.with_timezone(&chrono::offset::Utc); - - Ok(UntaggedValue::Primitive(Primitive::Date(date.into()))) - } - - pub fn naive_from_str(s: Tagged<&str>) -> Result { - let date = NaiveDate::parse_from_str(s.item, "%Y-%m-%d").map_err(|reason| { - ShellError::labeled_error( - &format!("Date parse error: {}", reason), - "original value", - s.tag, - ) - })?; - - Ok(UntaggedValue::Primitive(Primitive::Date( - DateTime::::from_utc(date.and_hms(12, 34, 56), Utc).into(), - ))) - } -} - -pub fn date_from_str(s: Tagged<&str>) -> Result { - Date::from_regular_str(s) -} - -pub fn date_naive_from_str(s: Tagged<&str>) -> Result { - Date::naive_from_str(s) -} - -pub fn merge_values( - left: &UntaggedValue, - right: &UntaggedValue, -) -> Result { - match (left, right) { - (UntaggedValue::Row(columns), UntaggedValue::Row(columns_b)) => { - Ok(UntaggedValue::Row(columns.merge_from(columns_b))) - } - (left, right) => Err((left.type_name(), right.type_name())), - } -} - -fn zero_division_error() -> UntaggedValue { - UntaggedValue::Error(ShellError::untagged_runtime_error("division by zero")) -} - -pub fn unsafe_compute_values( - operator: Operator, - left: &UntaggedValue, - right: &UntaggedValue, -) -> Result { - let computed = compute_values(operator, left, right); - - if computed.is_ok() { - return computed; - } - - match (left, right) { - (UntaggedValue::Primitive(lhs), UntaggedValue::Primitive(rhs)) => match (lhs, rhs) { - (Primitive::Filesize(x), Primitive::Int(y)) => match operator { - Operator::Multiply => { - Ok(UntaggedValue::Primitive(Primitive::Filesize(x * *y as u64))) - } - Operator::Divide => { - Ok(UntaggedValue::Primitive(Primitive::Filesize(x / *y as u64))) - } - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::Int(x), Primitive::Filesize(y)) => match operator { - Operator::Multiply => { - Ok(UntaggedValue::Primitive(Primitive::Filesize(*x as u64 * y))) - } - _ => Err((left.type_name(), right.type_name())), - }, - _ => Err((left.type_name(), right.type_name())), - }, - _ => Err((left.type_name(), right.type_name())), - } -} - -pub fn compute_values( - operator: Operator, - left: &UntaggedValue, - right: &UntaggedValue, -) -> Result { - match (left, right) { - (UntaggedValue::Primitive(lhs), UntaggedValue::Primitive(rhs)) => match (lhs, rhs) { - (Primitive::Filesize(x), Primitive::Filesize(y)) => { - let result = match operator { - Operator::Plus => Ok(x + y), - Operator::Minus => Ok(x - y), - Operator::Multiply => Ok(x * y), - Operator::Divide => { - if y.is_zero() { - Err((left.type_name(), right.type_name())) - } else { - Ok(x / y) - } - } - _ => Err((left.type_name(), right.type_name())), - }?; - Ok(UntaggedValue::Primitive(Primitive::Filesize(result))) - } - (Primitive::Filesize(x), Primitive::Int(y)) => match operator { - // Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::Filesize(x + *y as u64))), - // Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::Filesize(x - *y as u64))), - Operator::Multiply => { - Ok(UntaggedValue::Primitive(Primitive::Filesize(x * *y as u64))) - } - Operator::Divide => { - Ok(UntaggedValue::Primitive(Primitive::Filesize(x / *y as u64))) - } - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::Int(x), Primitive::Filesize(y)) => match operator { - // Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::Filesize(*x as u64 + y))), - // Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::Filesize(*x as u64 - y))), - Operator::Multiply => { - Ok(UntaggedValue::Primitive(Primitive::Filesize(*x as u64 * y))) - } - // Operator::Divide => { - // Ok(UntaggedValue::Primitive(Primitive::Filesize(*x as u64 / y))) - // } - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::Int(x), Primitive::Int(y)) => match operator { - Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::Int(x + y))), - Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::Int(x - y))), - Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::Int(x * y))), - Operator::Divide => { - if y.is_zero() { - Ok(zero_division_error()) - } else if x - (y * (x / y)) == 0 { - Ok(UntaggedValue::Primitive(Primitive::Int(x / y))) - } else { - Ok(UntaggedValue::Primitive(Primitive::Decimal( - bigdecimal::BigDecimal::from(*x) / bigdecimal::BigDecimal::from(*y), - ))) - } - } - Operator::Modulo => { - if y.is_zero() { - Ok(zero_division_error()) - } else { - Ok(UntaggedValue::Primitive(Primitive::Int(x % y))) - } - } - Operator::Pow => { - let prim_u32 = ToPrimitive::to_u32(y); - - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - if !y.is_negative() { - match prim_u32 { - Some(num) => Ok(UntaggedValue::Primitive(Primitive::Int( - sign * (x.pow(num)), - ))), - _ => Err((left.type_name(), right.type_name())), - } - } else { - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - - match pow { - Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))), - _ => Err((left.type_name(), right.type_name())), - } - } - } - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::Int(x), Primitive::BigInt(y)) => match operator { - Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::BigInt( - BigInt::from(*x) + y, - ))), - Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::BigInt( - BigInt::from(*x) - y, - ))), - Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::BigInt( - BigInt::from(*x) * y, - ))), - Operator::Divide => { - if y.is_zero() { - Ok(zero_division_error()) - } else if x - (y * (x / y)) == BigInt::from(0) { - Ok(UntaggedValue::Primitive(Primitive::BigInt( - BigInt::from(*x) / y, - ))) - } else { - Ok(UntaggedValue::Primitive(Primitive::Decimal( - bigdecimal::BigDecimal::from(*x) - / bigdecimal::BigDecimal::from(y.clone()), - ))) - } - } - Operator::Modulo => { - if y.is_zero() { - Ok(zero_division_error()) - } else { - Ok(UntaggedValue::Primitive(Primitive::BigInt(x % y))) - } - } - Operator::Pow => { - let prim_u32 = ToPrimitive::to_u32(y); - - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - if !y.is_negative() { - match prim_u32 { - Some(num) => Ok(UntaggedValue::Primitive(Primitive::Int( - sign * (x.pow(num)), - ))), - _ => Err((left.type_name(), right.type_name())), - } - } else { - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - match pow { - Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))), - _ => Err((left.type_name(), right.type_name())), - } - } - } - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::BigInt(x), Primitive::Int(y)) => match operator { - Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::BigInt( - x + BigInt::from(*y), - ))), - Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::BigInt( - x - BigInt::from(*y), - ))), - Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::BigInt( - x * BigInt::from(*y), - ))), - Operator::Divide => { - if y.is_zero() { - Ok(zero_division_error()) - } else if x - (y * (x / y)) == BigInt::from(0) { - Ok(UntaggedValue::Primitive(Primitive::BigInt( - x / BigInt::from(*y), - ))) - } else { - Ok(UntaggedValue::Primitive(Primitive::Decimal( - bigdecimal::BigDecimal::from(x.clone()) - / bigdecimal::BigDecimal::from(*y), - ))) - } - } - Operator::Modulo => { - if y.is_zero() { - Ok(zero_division_error()) - } else { - Ok(UntaggedValue::Primitive(Primitive::BigInt(x % y))) - } - } - Operator::Pow => { - let prim_u32 = ToPrimitive::to_u32(y); - - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - if !y.is_negative() { - match prim_u32 { - Some(num) => Ok(UntaggedValue::Primitive(Primitive::BigInt( - (sign.to_bigint().unwrap_or_default()) * x.pow(num), - ))), - _ => Err((left.type_name(), right.type_name())), - } - } else { - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - let pow = bigdecimal::FromPrimitive::from_f64((sign as f64) * xp.powf(yp)); - match pow { - Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))), - _ => Err((left.type_name(), right.type_name())), - } - } - } - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::BigInt(x), Primitive::BigInt(y)) => match operator { - Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::BigInt(x + y))), - Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::BigInt(x - y))), - Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::BigInt(x * y))), - Operator::Divide => { - if y.is_zero() { - Ok(zero_division_error()) - } else if x - (y * (x / y)) == BigInt::from(0) { - Ok(UntaggedValue::Primitive(Primitive::BigInt(x / y))) - } else { - Ok(UntaggedValue::Primitive(Primitive::Decimal( - bigdecimal::BigDecimal::from(x.clone()) - / bigdecimal::BigDecimal::from(y.clone()), - ))) - } - } - Operator::Modulo => { - if y.is_zero() { - Ok(zero_division_error()) - } else { - Ok(UntaggedValue::Primitive(Primitive::BigInt(x % y))) - } - } - Operator::Pow => { - let prim_u32 = ToPrimitive::to_u32(y); - - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - if !y.is_negative() { - match prim_u32 { - Some(num) => Ok(UntaggedValue::Primitive(Primitive::BigInt( - (sign.to_bigint().unwrap_or_default()).pow(num), - ))), - _ => Err((left.type_name(), right.type_name())), - } - } else { - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - - match pow { - Some(p) => Ok(UntaggedValue::Primitive(Primitive::Decimal(p))), - _ => Err((left.type_name(), right.type_name())), - } - } - } - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::Decimal(x), Primitive::Int(y)) => { - let result = match operator { - Operator::Plus => Ok(x + bigdecimal::BigDecimal::from(*y)), - Operator::Minus => Ok(x - bigdecimal::BigDecimal::from(*y)), - Operator::Multiply => Ok(x * bigdecimal::BigDecimal::from(*y)), - Operator::Divide => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(x / bigdecimal::BigDecimal::from(*y)) - } - Operator::Modulo => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(x % bigdecimal::BigDecimal::from(*y)) - } - - Operator::Pow => { - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - match pow { - Some(p) => Ok(p), - None => Err((left.type_name(), right.type_name())), - } - } - _ => Err((left.type_name(), right.type_name())), - }?; - Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) - } - (Primitive::Int(x), Primitive::Decimal(y)) => { - let result = match operator { - Operator::Plus => Ok(bigdecimal::BigDecimal::from(*x) + y), - Operator::Minus => Ok(bigdecimal::BigDecimal::from(*x) - y), - Operator::Multiply => Ok(bigdecimal::BigDecimal::from(*x) * y), - Operator::Divide => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(bigdecimal::BigDecimal::from(*x) / y) - } - Operator::Modulo => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(bigdecimal::BigDecimal::from(*x) % y) - } - - Operator::Pow => { - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - match pow { - Some(p) => Ok(p), - None => Err((left.type_name(), right.type_name())), - } - } - _ => Err((left.type_name(), right.type_name())), - }?; - Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) - } - (Primitive::Decimal(x), Primitive::BigInt(y)) => { - let result = match operator { - Operator::Plus => Ok(x + bigdecimal::BigDecimal::from(y.clone())), - Operator::Minus => Ok(x - bigdecimal::BigDecimal::from(y.clone())), - Operator::Multiply => Ok(x * bigdecimal::BigDecimal::from(y.clone())), - Operator::Divide => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(x / bigdecimal::BigDecimal::from(y.clone())) - } - Operator::Modulo => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(x % bigdecimal::BigDecimal::from(y.clone())) - } - - Operator::Pow => { - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - match pow { - Some(p) => Ok(p), - None => Err((left.type_name(), right.type_name())), - } - } - _ => Err((left.type_name(), right.type_name())), - }?; - Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) - } - (Primitive::BigInt(x), Primitive::Decimal(y)) => { - let result = match operator { - Operator::Plus => Ok(bigdecimal::BigDecimal::from(x.clone()) + y), - Operator::Minus => Ok(bigdecimal::BigDecimal::from(x.clone()) - y), - Operator::Multiply => Ok(bigdecimal::BigDecimal::from(x.clone()) * y), - Operator::Divide => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(bigdecimal::BigDecimal::from(x.clone()) / y) - } - Operator::Modulo => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(bigdecimal::BigDecimal::from(x.clone()) % y) - } - - Operator::Pow => { - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - match pow { - Some(p) => Ok(p), - None => Err((left.type_name(), right.type_name())), - } - } - _ => Err((left.type_name(), right.type_name())), - }?; - Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) - } - (Primitive::Decimal(x), Primitive::Decimal(y)) => { - let result = match operator { - Operator::Plus => Ok(x + y), - Operator::Minus => Ok(x - y), - Operator::Multiply => Ok(x * y), - Operator::Divide => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(x / y) - } - Operator::Modulo => { - if y.is_zero() { - return Ok(zero_division_error()); - } - Ok(x % y) - } - - Operator::Pow => { - let sign = match x.is_negative() { - true => -1, - false => 1, - }; - - let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0); - let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0); - let pow = - bigdecimal::FromPrimitive::from_f64((sign as f64) * (xp.powf(yp))); - match pow { - Some(p) => Ok(p), - None => Err((left.type_name(), right.type_name())), - } - } - _ => Err((left.type_name(), right.type_name())), - }?; - Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) - } - (Primitive::Date(x), Primitive::Date(y)) => match operator { - Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::from( - x.signed_duration_since(*y), - ))), - _ => Err((left.type_name(), right.type_name())), - }, - (Primitive::Date(x), Primitive::Duration(_)) => { - let result = match operator { - Operator::Plus => { - // FIXME: Not sure if I could do something better with the Span. - match Primitive::into_chrono_duration(rhs.clone(), Span::unknown()) { - Ok(y) => match x.checked_add_signed(y) { - Some(value) => Ok(value), - None => Err(("Date", "Duration and date addition overflow")), - }, - Err(_) => Err(("Date", "Duration overflow")), - } - } - Operator::Minus => { - match Primitive::into_chrono_duration(rhs.clone(), Span::unknown()) { - Ok(y) => match x.checked_sub_signed(y) { - Some(value) => Ok(value), - None => Err(("Date", "Duration and date addition overflow")), - }, - Err(_) => Err(("Date", "Duration overflow")), - } - } - _ => Err((left.type_name(), right.type_name())), - }?; - Ok(UntaggedValue::Primitive(Primitive::Date(result))) - } - (Primitive::Duration(x), Primitive::Duration(y)) => { - let result = match operator { - Operator::Plus => Ok(x + y), - Operator::Minus => Ok(x - y), - _ => Err((left.type_name(), right.type_name())), - }?; - - Ok(UntaggedValue::Primitive(Primitive::Duration(result))) - } - (Primitive::Int(x), Primitive::Duration(y)) => { - let result = match operator { - Operator::Plus => Ok(x + y), - Operator::Minus => Ok(x - y), - _ => Err((left.type_name(), right.type_name())), - }?; - - Ok(UntaggedValue::Primitive(Primitive::Duration(result))) - } - (Primitive::Duration(x), Primitive::Decimal(y)) => { - let result = match operator { - Operator::Divide => { - if y.is_zero() { - return Ok(zero_division_error()); - } - - let y = y.as_bigint_and_exponent(); - Ok(x / y.0) - } - _ => Err((left.type_name(), right.type_name())), - }?; - - Ok(UntaggedValue::Primitive(Primitive::Duration(result))) - } - (Primitive::String(x), Primitive::String(y)) => { - let mut new_string = x.clone(); - new_string.push_str(y); - Ok(UntaggedValue::Primitive(Primitive::String(new_string))) - } - _ => Err((left.type_name(), right.type_name())), - }, - _ => Err((left.type_name(), right.type_name())), - } -} - -/// If left is {{ Operator }} right -pub fn compare_values( - operator: Operator, - left: &UntaggedValue, - right: &UntaggedValue, -) -> Result { - let coerced = coerce_compare(left, right)?; - let ordering = coerced.compare(); - - use std::cmp::Ordering; - - let result = matches!( - (operator, ordering), - (Operator::Equal, Ordering::Equal) - | (Operator::GreaterThan, Ordering::Greater) - | (Operator::GreaterThanOrEqual, Ordering::Greater) - | (Operator::GreaterThanOrEqual, Ordering::Equal) - | (Operator::LessThan, Ordering::Less) - | (Operator::LessThanOrEqual, Ordering::Less) - | (Operator::LessThanOrEqual, Ordering::Equal) - | (Operator::NotEqual, Ordering::Greater) - | (Operator::NotEqual, Ordering::Less) - ); - - Ok(result) -} - -pub fn plain_type<'a>(value: impl Into<&'a UntaggedValue>, width: usize) -> String { - Type::from_value(value.into()).plain_string(width) -} - -pub fn format_type<'a>(value: impl Into<&'a UntaggedValue>, width: usize) -> String { - Type::from_value(value.into()).colored_string(width) -} - -pub fn format_leaf<'a>(value: impl Into<&'a UntaggedValue>) -> DebugDocBuilder { - InlineShape::from_value(value.into()).format().pretty() -} - -pub fn style_leaf<'a>( - value: impl Into<&'a UntaggedValue>, - color_hash_map: &HashMap, -) -> TextStyle { - match value.into() { - UntaggedValue::Primitive(p) => { - // This is just to return the name of the type so that style_primitive - // can work on a string versus a type like String("some_text") - let str: &str = &p.to_string(); - let str_len = str.len(); - let paren_index = str.find('(').unwrap_or(str_len - 1); - let prim_type = str[0..paren_index].to_string(); - style_primitive(&prim_type, color_hash_map) - } - _ => TextStyle::basic_left(), - } -} - -pub fn format_for_column<'a>( - value: impl Into<&'a UntaggedValue>, - column: impl Into, -) -> DebugDocBuilder { - InlineShape::from_value(value.into()) - .format_for_column(column) - .pretty() -} - -#[cfg(test)] -mod tests { - use super::Date as d; - use super::UntaggedValue as v; - use super::{compute_values, merge_values}; - use nu_protocol::hir::Operator; - use nu_protocol::{Primitive, UntaggedValue}; - use nu_source::TaggedItem; - - use indexmap::indexmap; - - #[test] - fn merges_tables() { - let (author_1_date, author_2_date) = ( - "2020-04-29".to_string().tagged_unknown(), - "2019-10-10".to_string().tagged_unknown(), - ); - - let table_author_row = v::row(indexmap! { - "name".into() => v::string("Andrés").into_untagged_value(), - "country".into() => v::string("EC").into_untagged_value(), - "date".into() => d::naive_from_str(author_1_date.borrow_tagged()).unwrap().into_untagged_value() - }); - - let other_table_author_row = v::row(indexmap! { - "name".into() => v::string("YK").into_untagged_value(), - "country".into() => v::string("US").into_untagged_value(), - "date".into() => d::naive_from_str(author_2_date.borrow_tagged()).unwrap().into_untagged_value() - }); - - assert_eq!( - other_table_author_row, - merge_values(&table_author_row, &other_table_author_row).unwrap() - ); - } - - #[test] - fn pow_operator_negatives_and_decimals() { - // test 2 ** 2 - let result_one = compute_values( - Operator::Pow, - &UntaggedValue::Primitive(Primitive::Int(2)), - &UntaggedValue::Primitive(Primitive::Int(2)), - ); - - assert_eq!( - result_one.unwrap(), - UntaggedValue::Primitive(Primitive::Int(4)) - ); - - // test 2 ** 2.0 - let rhs_decimal = bigdecimal::FromPrimitive::from_f64(2.0).unwrap(); - - let result_two = compute_values( - Operator::Pow, - &UntaggedValue::Primitive(Primitive::Int(2)), - &UntaggedValue::Primitive(Primitive::Decimal(rhs_decimal)), - ); - - let should_equal_four_decimal = bigdecimal::FromPrimitive::from_f64(4.0).unwrap(); - - assert_eq!( - result_two.unwrap(), - UntaggedValue::Primitive(Primitive::Decimal(should_equal_four_decimal)) - ); - - // test 2.0 ** 2.0 - let rhs_decimal = bigdecimal::FromPrimitive::from_f64(2.0).unwrap(); - let lhs_decimal = bigdecimal::FromPrimitive::from_f64(2.0).unwrap(); - let should_equal_four_decimal = bigdecimal::FromPrimitive::from_f64(4.0).unwrap(); - - let result_three = compute_values( - Operator::Pow, - &UntaggedValue::Primitive(Primitive::Decimal(lhs_decimal)), - &UntaggedValue::Primitive(Primitive::Decimal(rhs_decimal)), - ); - - assert_eq!( - result_three.unwrap(), - UntaggedValue::Primitive(Primitive::Decimal(should_equal_four_decimal)) - ); - - // test 2 ** -2 - let result_four = compute_values( - Operator::Pow, - &UntaggedValue::Primitive(Primitive::Int(2)), - &UntaggedValue::Primitive(Primitive::Int(-2)), - ); - - let should_equal_zero_decimal = bigdecimal::FromPrimitive::from_f64(0.25).unwrap(); - - assert_eq!( - result_four.unwrap(), - UntaggedValue::Primitive(Primitive::Decimal(should_equal_zero_decimal)) - ); - - // test -2 ** -2 - let result_five = compute_values( - Operator::Pow, - &UntaggedValue::Primitive(Primitive::Int(-2)), - &UntaggedValue::Primitive(Primitive::Int(-2)), - ); - - let should_equal_neg_zero_decimal = bigdecimal::FromPrimitive::from_f64(-0.25).unwrap(); - - assert_eq!( - result_five.unwrap(), - UntaggedValue::Primitive(Primitive::Decimal(should_equal_neg_zero_decimal)) - ); - - // test -2 ** 2 - let result_six = compute_values( - Operator::Pow, - &UntaggedValue::Primitive(Primitive::Int(-2)), - &UntaggedValue::Primitive(Primitive::Int(2)), - ); - - assert_eq!( - result_six.unwrap(), - UntaggedValue::Primitive(Primitive::Int(-4)) - ); - - // test -2.0 ** 2 - let lhs_decimal = bigdecimal::FromPrimitive::from_f64(-2.0).unwrap(); - let should_equal_neg_four_decimal = bigdecimal::FromPrimitive::from_f64(-4.0).unwrap(); - - let result_seven = compute_values( - Operator::Pow, - &UntaggedValue::Primitive(Primitive::Decimal(lhs_decimal)), - &UntaggedValue::Primitive(Primitive::Int(2)), - ); - - // Need to validate - assert_eq!( - result_seven.unwrap(), - UntaggedValue::Primitive(Primitive::Decimal(should_equal_neg_four_decimal)) - ); - } -} diff --git a/old_nushell/crates/nu-engine/Cargo.toml b/old_nushell/crates/nu-engine/Cargo.toml deleted file mode 100644 index 29f0adcff..000000000 --- a/old_nushell/crates/nu-engine/Cargo.toml +++ /dev/null @@ -1,59 +0,0 @@ -[package] -authors = ["The Nu Project Contributors"] -description = "Core commands for nushell" -edition = "2018" -license = "MIT" -name = "nu-engine" -version = "0.43.0" - -[dependencies] -nu-data = { version = "0.43.0", path="../nu-data" } -nu-errors = { version = "0.43.0", path="../nu-errors" } -nu-parser = { version = "0.43.0", path="../nu-parser" } -nu-plugin = { version = "0.43.0", path="../nu-plugin" } -nu-protocol = { version = "0.43.0", path="../nu-protocol" } -nu-source = { version = "0.43.0", path="../nu-source" } -nu-stream = { version = "0.43.0", path="../nu-stream" } -nu-value-ext = { version = "0.43.0", path="../nu-value-ext" } -nu-ansi-term = { version = "0.43.0", path="../nu-ansi-term" } -nu-test-support = { version = "0.43.0", path="../nu-test-support" } -nu-path = { version = "0.43.0", path="../nu-path" } - -trash = { version = "2.0.2", optional = true } -which = { version="4.0.2", optional=true } -codespan-reporting = "0.11.0" -bigdecimal = { package = "bigdecimal", version = "0.3.0", features = ["serde"] } -bytes = "1.1.0" -chrono = { version="0.4.19", features=["serde"] } -derive-new = "0.5.8" -dirs-next = "2.0.0" -encoding_rs = "0.8.28" -filesize = "0.2.0" -fs_extra = "1.2.0" -getset = "0.1.1" -glob = "0.3.0" -indexmap = { version="1.6.1", features=["serde-1"] } -itertools = "0.10.0" -lazy_static = "1.*" -log = "0.4.14" -num-bigint = { version="0.4.3", features=["serde"] } -parking_lot = "0.11.1" -rayon = "1.5.0" -serde = { version="1.0.123", features=["derive"] } -serde_json = "1.0.61" -tempfile = "3.2.0" -term_size = "0.3.2" -termcolor = "1.1.2" - -[target.'cfg(unix)'.dependencies] -umask = "1.0.0" -users = "0.11.0" - -[dev-dependencies] -nu-test-support = { version = "0.43.0", path="../nu-test-support" } -hamcrest2 = "0.3.0" - -[features] -rustyline-support = [] -trash-support = ["trash"] -dataframe = ["nu-protocol/dataframe"] diff --git a/old_nushell/crates/nu-engine/README.md b/old_nushell/crates/nu-engine/README.md deleted file mode 100644 index 1d4fb0588..000000000 --- a/old_nushell/crates/nu-engine/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Nu-Engine - -Nu-engine handles most of the core logic of nushell. For example, engine handles: - -- Passing of data between commands -- Evaluating a commands return values -- Loading of user configurations - -## Top level introduction -The following topics shall give the reader a top level understanding how various topics are handled in nushell. - -### How are environment variables handled? -Environment variables (or short envs) are stored in the `Scope` of the `EvaluationContext`. That means that environment variables are scoped by default and we don't use `std::env` to store envs (but make exceptions where convenient). - -Nushell handles environment variables and their lifetime the following: -- At startup all existing environment variables are read and put into `Scope`. (Nushell reads existing environment variables platform independent by asking the `Host`. They will most likely come from `std::env::*`) -- Envs can also be loaded from config files. Each loaded config produces a new `ScopeFrame` with the envs of the loaded config. -- Nu-Script files and internal commands read and write env variables from / to the `Scope`. External scripts and binaries can't interact with the `Scope`. Therefore all env variables are read from the `Scope` and put into the external binaries environment-variables-memory area. diff --git a/old_nushell/crates/nu-engine/src/call_info.rs b/old_nushell/crates/nu-engine/src/call_info.rs deleted file mode 100644 index d6822017a..000000000 --- a/old_nushell/crates/nu-engine/src/call_info.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::evaluate::evaluate_args::evaluate_args; -use crate::evaluation_context::EvaluationContext; -use nu_errors::ShellError; -use nu_protocol::hir; -use nu_protocol::CallInfo; -use nu_source::Tag; - -#[derive(Debug, Clone)] -pub struct UnevaluatedCallInfo { - pub args: hir::Call, - pub name_tag: Tag, -} - -impl UnevaluatedCallInfo { - pub fn evaluate(self, ctx: &EvaluationContext) -> Result { - let args = evaluate_args(&self.args, ctx)?; - - Ok(CallInfo { - args, - name_tag: self.name_tag, - }) - } - - pub fn switch_present(&self, switch: &str) -> bool { - self.args.switch_preset(switch) - } -} diff --git a/old_nushell/crates/nu-engine/src/command_args.rs b/old_nushell/crates/nu-engine/src/command_args.rs deleted file mode 100644 index 124ef557e..000000000 --- a/old_nushell/crates/nu-engine/src/command_args.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::evaluate::scope::Scope; -use crate::evaluation_context::EvaluationContext; -use crate::shell::shell_manager::ShellManager; -use crate::FromValue; -use crate::{call_info::UnevaluatedCallInfo, config_holder::ConfigHolder}; -use crate::{env::host::Host, evaluate_baseline_expr}; -use getset::Getters; -use nu_errors::ShellError; -use nu_protocol::hir::SpannedExpression; -use nu_source::Tag; -use nu_stream::InputStream; -use parking_lot::Mutex; -use std::sync::atomic::AtomicBool; -use std::sync::Arc; - -#[derive(Getters)] -#[get = "pub"] -pub struct CommandArgs { - pub context: EvaluationContext, - pub call_info: UnevaluatedCallInfo, - pub input: InputStream, -} - -impl CommandArgs { - pub fn scope(&self) -> &Scope { - &self.context.scope - } - - pub fn host(&self) -> Arc>> { - self.context.host().clone() - } - - pub fn current_errors(&self) -> Arc>> { - self.context.current_errors().clone() - } - - pub fn ctrl_c(&self) -> Arc { - self.context.ctrl_c().clone() - } - - pub fn configs(&self) -> Arc> { - self.context.configs().clone() - } - - pub fn shell_manager(&self) -> ShellManager { - self.context.shell_manager().clone() - } - - pub fn nth(&self, pos: usize) -> Option<&SpannedExpression> { - if let Some(positional) = &self.call_info.args.positional { - positional.get(pos) - } else { - None - } - } - - pub fn req(&self, pos: usize) -> Result { - if let Some(expr) = self.nth(pos) { - let result = evaluate_baseline_expr(expr, &self.context)?; - FromValue::from_value(&result) - } else { - Err(ShellError::labeled_error( - "Position beyond end of command arguments", - "can't access beyond end of command arguments", - self.call_info.name_tag.span, - )) - } - } - - pub fn req_named(&self, name: &str) -> Result { - match self.get_flag(name)? { - Some(v) => Ok(v), - None => Err(ShellError::labeled_error( - "Missing flag", - format!("expected {} flag", name), - &self.call_info.name_tag, - )), - } - } - - pub fn has_flag(&self, name: &str) -> bool { - self.call_info.args.switch_preset(name) - } - - pub fn get_flag(&self, name: &str) -> Result, ShellError> { - if let Some(expr) = self.call_info.args.get_flag(name) { - let result = evaluate_baseline_expr(expr, &self.context)?; - FromValue::from_value(&result).map(Some) - } else { - Ok(None) - } - } - - pub fn opt(&self, pos: usize) -> Result, ShellError> { - if let Some(expr) = self.nth(pos) { - let result = evaluate_baseline_expr(expr, &self.context)?; - FromValue::from_value(&result).map(Some) - } else { - Ok(None) - } - } - - pub fn rest(&self, starting_pos: usize) -> Result, ShellError> { - let mut output = vec![]; - - if let Some(positional) = &self.call_info.args.positional { - for expr in positional.iter().skip(starting_pos) { - let result = evaluate_baseline_expr(expr, &self.context)?; - output.push(FromValue::from_value(&result)?); - } - } - - Ok(output) - } - - pub fn rest_with_minimum( - &self, - pos: usize, - count: usize, - ) -> Result, ShellError> { - let mut output = vec![]; - for i in pos..pos + count { - output.push(self.req(i)?); - } - output.extend(self.rest(pos + count)?); - - Ok(output) - } - - pub fn name_tag(&self) -> Tag { - self.call_info.name_tag.clone() - } -} - -pub type RunnableContext = CommandArgs; - -impl std::fmt::Debug for CommandArgs { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.call_info.fmt(f) - } -} diff --git a/old_nushell/crates/nu-engine/src/config_holder.rs b/old_nushell/crates/nu-engine/src/config_holder.rs deleted file mode 100644 index 388460859..000000000 --- a/old_nushell/crates/nu-engine/src/config_holder.rs +++ /dev/null @@ -1,73 +0,0 @@ -use crate::shell::palette::ThemedPalette; -use nu_data::config::NuConfig; -use nu_protocol::ConfigPath; -use std::path::Path; - -/// ConfigHolder holds information which configs have been loaded. -#[derive(Clone)] -pub struct ConfigHolder { - pub global_config: Option, - pub local_configs: Vec, - pub syntax_config: Option, -} - -impl Default for ConfigHolder { - fn default() -> Self { - Self::new() - } -} - -impl ConfigHolder { - pub fn new() -> ConfigHolder { - ConfigHolder { - global_config: None, - local_configs: vec![], - syntax_config: None, - } - } - - pub fn global_config(&self) -> NuConfig { - match &self.global_config { - Some(config) => config.clone(), - None => NuConfig::default(), - } - } - - pub fn syntax_colors(&self) -> ThemedPalette { - match &self.syntax_config { - Some(cfg) => cfg.clone(), - None => ThemedPalette::default(), - } - } - - pub fn add_local_cfg(&mut self, cfg: NuConfig) { - self.local_configs.push(cfg); - } - - pub fn set_global_cfg(&mut self, cfg: NuConfig) { - self.global_config = Some(cfg); - } - - pub fn set_syntax_colors(&mut self, cfg: ThemedPalette) { - self.syntax_config = Some(cfg); - } - - pub fn remove_cfg(&mut self, cfg_path: &ConfigPath) { - match cfg_path { - ConfigPath::Global(_) => self.global_config = None, - ConfigPath::Local(p) => self.remove_local_cfg(p), - } - } - - fn remove_local_cfg>(&mut self, cfg_path: P) { - // Remove the first loaded local config with specified cfg_path - if let Some(index) = self - .local_configs - .iter() - .rev() - .position(|cfg| cfg.file_path == cfg_path.as_ref()) - { - self.local_configs.remove(index); - } - } -} diff --git a/old_nushell/crates/nu-engine/src/documentation.rs b/old_nushell/crates/nu-engine/src/documentation.rs deleted file mode 100644 index bd8f1df74..000000000 --- a/old_nushell/crates/nu-engine/src/documentation.rs +++ /dev/null @@ -1,313 +0,0 @@ -use crate::evaluate::scope::Scope; -use crate::whole_stream_command::WholeStreamCommand; -use indexmap::IndexMap; -use itertools::Itertools; -use nu_protocol::{NamedType, PositionalType, Signature, UntaggedValue, Value}; -use nu_source::PrettyDebug; -use std::collections::HashMap; - -const COMMANDS_DOCS_DIR: &str = "docs/commands"; - -#[derive(Default)] -pub struct DocumentationConfig { - no_subcommands: bool, - no_color: bool, - brief: bool, -} - -fn generate_doc(name: &str, scope: &Scope) -> IndexMap { - let mut row_entries = IndexMap::new(); - let command = scope - .get_command(name) - .unwrap_or_else(|| panic!("Expected command '{}' from names to be in registry", name)); - row_entries.insert( - "name".to_owned(), - UntaggedValue::string(name).into_untagged_value(), - ); - row_entries.insert( - "usage".to_owned(), - UntaggedValue::string(command.usage()).into_untagged_value(), - ); - retrieve_doc_link(name).and_then(|link| { - row_entries.insert( - "doc_link".to_owned(), - UntaggedValue::string(link).into_untagged_value(), - ) - }); - row_entries.insert( - "documentation".to_owned(), - UntaggedValue::string(get_documentation( - command.stream_command(), - scope, - &DocumentationConfig { - no_subcommands: true, - no_color: true, - brief: false, - }, - )) - .into_untagged_value(), - ); - row_entries -} - -// generate_docs gets the documentation from each command and returns a Table as output -pub fn generate_docs(scope: &Scope) -> Value { - let mut sorted_names = scope.get_command_names(); - sorted_names.sort(); - - // cmap will map parent commands to it's subcommands e.g. to -> [to csv, to yaml, to bson] - let mut cmap: HashMap> = HashMap::new(); - for name in &sorted_names { - if name.contains(' ') { - let split_name = name.split_whitespace().collect_vec(); - let parent_name = split_name.first().expect("Expected a parent command name"); - if cmap.contains_key(*parent_name) { - let sub_names = cmap - .get_mut(*parent_name) - .expect("Expected an entry for parent"); - sub_names.push(name.to_owned()); - } - } else { - cmap.insert(name.to_owned(), Vec::new()); - }; - } - // Return documentation for each command - // Sub-commands are nested under their respective parent commands - let mut table = Vec::new(); - for name in &sorted_names { - // Must be a sub-command, skip since it's being handled underneath when we hit the parent command - if !cmap.contains_key(name) { - continue; - } - let mut row_entries = generate_doc(name, scope); - // Iterate over all the subcommands of the parent command - let mut sub_table = Vec::new(); - for sub_name in cmap.get(name).unwrap_or(&Vec::new()) { - let sub_row = generate_doc(sub_name, scope); - sub_table.push(UntaggedValue::row(sub_row).into_untagged_value()); - } - - if !sub_table.is_empty() { - row_entries.insert( - "subcommands".to_owned(), - UntaggedValue::table(&sub_table).into_untagged_value(), - ); - } - table.push(UntaggedValue::row(row_entries).into_untagged_value()); - } - UntaggedValue::table(&table).into_untagged_value() -} - -fn retrieve_doc_link(name: &str) -> Option { - let doc_name = name.split_whitespace().join("_"); // Because .replace(" ", "_") didn't work - let mut entries = - std::fs::read_dir(COMMANDS_DOCS_DIR).expect("Directory for command docs are missing!"); - entries.find_map(|r| { - r.map_or(None, |de| { - if de.file_name().to_string_lossy() == format!("{}.{}", &doc_name, "md") { - Some(format!("/commands/{}.{}", &doc_name, "html")) - } else { - None - } - }) - }) -} - -#[allow(clippy::cognitive_complexity)] -pub fn get_documentation( - cmd: &dyn WholeStreamCommand, - scope: &Scope, - config: &DocumentationConfig, -) -> String { - let cmd_name = cmd.name(); - let signature = cmd.signature(); - let mut long_desc = String::new(); - - let usage = &cmd.usage(); - if !usage.is_empty() { - long_desc.push_str(usage); - long_desc.push_str("\n\n"); - } - - let extra_usage = if config.brief { "" } else { &cmd.extra_usage() }; - if !extra_usage.is_empty() { - long_desc.push_str(extra_usage); - long_desc.push_str("\n\n"); - } - - let mut subcommands = vec![]; - if !config.no_subcommands { - for name in scope.get_command_names() { - if name.starts_with(&format!("{} ", cmd_name)) { - let subcommand = scope.get_command(&name).expect("This shouldn't happen"); - - subcommands.push(format!(" {} - {}", name, subcommand.usage())); - } - } - } - - let mut one_liner = String::new(); - one_liner.push_str(&signature.name); - one_liner.push(' '); - - for positional in &signature.positional { - match &positional.0 { - PositionalType::Mandatory(name, _m) => { - one_liner.push_str(&format!("<{}> ", name)); - } - PositionalType::Optional(name, _o) => { - one_liner.push_str(&format!("({}) ", name)); - } - } - } - - if signature.rest_positional.is_some() { - one_liner.push_str("...args "); - } - - if !subcommands.is_empty() { - one_liner.push_str(" "); - } - - if !signature.named.is_empty() { - one_liner.push_str("{flags} "); - } - - long_desc.push_str(&format!("Usage:\n > {}\n", one_liner)); - - if !subcommands.is_empty() { - long_desc.push_str("\nSubcommands:\n"); - subcommands.sort(); - long_desc.push_str(&subcommands.join("\n")); - long_desc.push('\n'); - } - - if !signature.positional.is_empty() || signature.rest_positional.is_some() { - long_desc.push_str("\nParameters:\n"); - for positional in &signature.positional { - match &positional.0 { - PositionalType::Mandatory(name, _m) => { - long_desc.push_str(&format!(" <{}> {}\n", name, positional.1)); - } - PositionalType::Optional(name, _o) => { - long_desc.push_str(&format!(" ({}) {}\n", name, positional.1)); - } - } - } - - if let Some(rest_positional) = &signature.rest_positional { - long_desc.push_str(&format!(" ...args: {}\n", rest_positional.2)); - } - } - if !signature.named.is_empty() { - long_desc.push_str(&get_flags_section(&signature)) - } - - let palette = crate::shell::palette::DefaultPalette {}; - let examples = cmd.examples(); - if !examples.is_empty() { - long_desc.push_str("\nExamples:"); - } - for example in examples { - long_desc.push('\n'); - long_desc.push_str(" "); - long_desc.push_str(example.description); - - if config.no_color { - long_desc.push_str(&format!("\n > {}\n", example.example)); - } else { - let colored_example = - crate::shell::painter::Painter::paint_string(example.example, scope, &palette); - long_desc.push_str(&format!("\n > {}\n", colored_example)); - } - } - - long_desc.push('\n'); - - long_desc -} - -fn get_flags_section(signature: &Signature) -> String { - let mut long_desc = String::new(); - long_desc.push_str("\nFlags:\n"); - for (flag, ty) in &signature.named { - let msg = match ty.0 { - NamedType::Switch(s) => { - if let Some(c) = s { - format!( - " -{}, --{}{} {}\n", - c, - flag, - if !ty.1.is_empty() { ":" } else { "" }, - ty.1 - ) - } else { - format!( - " --{}{} {}\n", - flag, - if !ty.1.is_empty() { ":" } else { "" }, - ty.1 - ) - } - } - NamedType::Mandatory(s, m) => { - if let Some(c) = s { - format!( - " -{}, --{} <{}> (required parameter){} {}\n", - c, - flag, - m.display(), - if !ty.1.is_empty() { ":" } else { "" }, - ty.1 - ) - } else { - format!( - " --{} <{}> (required parameter){} {}\n", - flag, - m.display(), - if !ty.1.is_empty() { ":" } else { "" }, - ty.1 - ) - } - } - NamedType::Optional(s, o) => { - if let Some(c) = s { - format!( - " -{}, --{} <{}>{} {}\n", - c, - flag, - o.display(), - if !ty.1.is_empty() { ":" } else { "" }, - ty.1 - ) - } else { - format!( - " --{} <{}>{} {}\n", - flag, - o.display(), - if !ty.1.is_empty() { ":" } else { "" }, - ty.1 - ) - } - } - }; - long_desc.push_str(&msg); - } - long_desc -} - -pub fn get_brief_help(cmd: &dyn WholeStreamCommand, scope: &Scope) -> String { - get_documentation( - cmd, - scope, - &DocumentationConfig { - no_subcommands: false, - no_color: false, - brief: true, - }, - ) -} - -pub fn get_full_help(cmd: &dyn WholeStreamCommand, scope: &Scope) -> String { - get_documentation(cmd, scope, &DocumentationConfig::default()) -} diff --git a/old_nushell/crates/nu-engine/src/env/basic_host.rs b/old_nushell/crates/nu-engine/src/env/basic_host.rs deleted file mode 100644 index 177558d34..000000000 --- a/old_nushell/crates/nu-engine/src/env/basic_host.rs +++ /dev/null @@ -1,119 +0,0 @@ -use crate::Host; -use nu_errors::ShellError; -use nu_protocol::{errln, outln}; -use nu_source::Text; -use std::ffi::OsString; - -#[derive(Debug)] -pub struct BasicHost; - -impl Host for BasicHost { - fn stdout(&mut self, out: &str) { - match out { - "\n" => outln!(""), - other => outln!("{}", other), - } - } - - fn stderr(&mut self, out: &str) { - match out { - "\n" => errln!(""), - other => errln!("{}", other), - } - } - - fn print_err(&mut self, err: ShellError, source: &Text) { - let diag = err.into_diagnostic(); - let source = source.to_string(); - let mut files = codespan_reporting::files::SimpleFiles::new(); - files.add("shell", source); - - let writer = termcolor::StandardStream::stderr(termcolor::ColorChoice::Auto); - let config = codespan_reporting::term::Config::default(); - - let _ = std::panic::catch_unwind(move || { - let _ = codespan_reporting::term::emit(&mut writer.lock(), &config, &files, &diag); - }); - } - - #[allow(unused_variables)] - fn vars(&self) -> Vec<(String, String)> { - #[cfg(not(target_arch = "wasm32"))] - { - std::env::vars().collect::>() - } - - #[cfg(target_arch = "wasm32")] - { - vec![] - } - } - - #[allow(unused_variables)] - fn env_get(&mut self, key: OsString) -> Option { - #[cfg(not(target_arch = "wasm32"))] - { - std::env::var_os(key) - } - #[cfg(target_arch = "wasm32")] - { - None - } - } - - #[allow(unused_variables)] - fn env_set(&mut self, key: OsString, value: OsString) { - #[cfg(not(target_arch = "wasm32"))] - { - std::env::set_var(key, value); - } - } - - #[allow(unused_variables)] - fn env_rm(&mut self, key: OsString) { - #[cfg(not(target_arch = "wasm32"))] - { - std::env::remove_var(key); - } - } - - fn width(&self) -> usize { - let (mut term_width, _) = term_size::dimensions().unwrap_or((80, 20)); - term_width -= 1; - term_width - } - - fn height(&self) -> usize { - let (_, term_height) = term_size::dimensions().unwrap_or((80, 20)); - term_height - } - - fn is_external_cmd(&self, #[allow(unused)] cmd_name: &str) -> bool { - #[cfg(any(target_arch = "wasm32", not(feature = "which")))] - { - true - } - - #[cfg(all(unix, feature = "which"))] - { - which::which(cmd_name).is_ok() - } - - #[cfg(all(windows, feature = "which"))] - { - if which::which(cmd_name).is_ok() { - true - } else { - // Reference: https://ss64.com/nt/syntax-internal.html - let cmd_builtins = [ - "assoc", "break", "color", "copy", "date", "del", "dir", "dpath", "echo", - "erase", "for", "ftype", "md", "mkdir", "mklink", "move", "path", "ren", - "rename", "rd", "rmdir", "start", "time", "title", "type", "ver", "verify", - "vol", - ]; - - cmd_builtins.contains(&cmd_name) - } - } - } -} diff --git a/old_nushell/crates/nu-engine/src/env/host.rs b/old_nushell/crates/nu-engine/src/env/host.rs deleted file mode 100644 index 0bc4ba710..000000000 --- a/old_nushell/crates/nu-engine/src/env/host.rs +++ /dev/null @@ -1,143 +0,0 @@ -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_source::Text; -use std::ffi::OsString; -use std::fmt::Debug; - -use super::basic_host::BasicHost; - -pub trait Host: Debug + Send { - fn stdout(&mut self, out: &str); - fn stderr(&mut self, out: &str); - fn print_err(&mut self, err: ShellError, source: &Text); - - fn vars(&self) -> Vec<(String, String)>; - fn env_get(&mut self, key: OsString) -> Option; - fn env_set(&mut self, k: OsString, v: OsString); - fn env_rm(&mut self, k: OsString); - - fn width(&self) -> usize; - fn height(&self) -> usize; - - fn is_external_cmd(&self, cmd_name: &str) -> bool; -} - -impl Default for Box { - fn default() -> Self { - Box::new(BasicHost) - } -} - -impl Host for Box { - fn stdout(&mut self, out: &str) { - (**self).stdout(out) - } - - fn stderr(&mut self, out: &str) { - (**self).stderr(out) - } - - fn print_err(&mut self, err: ShellError, source: &Text) { - (**self).print_err(err, source) - } - - fn vars(&self) -> Vec<(String, String)> { - (**self).vars() - } - - fn env_get(&mut self, key: OsString) -> Option { - (**self).env_get(key) - } - - fn env_set(&mut self, key: OsString, value: OsString) { - (**self).env_set(key, value); - } - - fn env_rm(&mut self, key: OsString) { - (**self).env_rm(key) - } - - fn width(&self) -> usize { - (**self).width() - } - - fn height(&self) -> usize { - (**self).height() - } - - fn is_external_cmd(&self, name: &str) -> bool { - (**self).is_external_cmd(name) - } -} - -#[derive(Debug)] -pub struct FakeHost { - line_written: String, - env_vars: IndexMap, -} - -impl FakeHost { - pub fn new() -> FakeHost { - FakeHost { - line_written: String::from(""), - env_vars: IndexMap::default(), - } - } -} - -impl Default for FakeHost { - fn default() -> Self { - FakeHost::new() - } -} - -impl Host for FakeHost { - fn stdout(&mut self, out: &str) { - self.line_written = out.to_string(); - } - - fn stderr(&mut self, out: &str) { - self.line_written = out.to_string(); - } - - fn print_err(&mut self, err: ShellError, source: &Text) { - BasicHost {}.print_err(err, source); - } - - fn vars(&self) -> Vec<(String, String)> { - self.env_vars - .iter() - .map(|(k, v)| (k.clone(), v.clone())) - .collect::>() - } - - fn env_get(&mut self, key: OsString) -> Option { - let key = key.into_string().expect("Couldn't convert to string."); - - self.env_vars.get(&key).map(OsString::from) - } - - fn env_set(&mut self, key: OsString, value: OsString) { - self.env_vars.insert( - key.into_string().expect("Couldn't convert to string."), - value.into_string().expect("Couldn't convert to string."), - ); - } - - fn env_rm(&mut self, key: OsString) { - self.env_vars - .shift_remove(&key.into_string().expect("Couldn't convert to string.")); - } - - fn width(&self) -> usize { - 1 - } - - fn height(&self) -> usize { - 1 - } - - fn is_external_cmd(&self, _: &str) -> bool { - true - } -} diff --git a/old_nushell/crates/nu-engine/src/env/mod.rs b/old_nushell/crates/nu-engine/src/env/mod.rs deleted file mode 100644 index 38a48cfe5..000000000 --- a/old_nushell/crates/nu-engine/src/env/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub(crate) mod basic_host; -pub(crate) mod host; diff --git a/old_nushell/crates/nu-engine/src/evaluate/block.rs b/old_nushell/crates/nu-engine/src/evaluate/block.rs deleted file mode 100644 index 7607a6af5..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/block.rs +++ /dev/null @@ -1,204 +0,0 @@ -use crate::evaluate::expr::run_expression_block; -use crate::evaluate::internal::run_internal_command; -use crate::evaluation_context::EvaluationContext; -use nu_errors::ShellError; -use nu_parser::ParserScope; -use nu_protocol::hir::{ - Block, Call, ClassifiedCommand, Expression, ExternalRedirection, Pipeline, SpannedExpression, - Synthetic, -}; -use nu_protocol::{UntaggedValue, Value}; -use nu_source::{Span, Tag}; -use nu_stream::{InputStream, OutputStream}; -use std::sync::atomic::Ordering; - -pub fn run_block( - block: &Block, - ctx: &EvaluationContext, - mut input: InputStream, - external_redirection: ExternalRedirection, -) -> Result { - let mut output: Result = Ok(OutputStream::empty()); - for definition in block.definitions.values() { - ctx.scope.add_definition(definition.clone()); - } - - let num_groups = block.block.len(); - for (group_num, group) in block.block.iter().enumerate() { - let num_pipelines = group.pipelines.len(); - for (pipeline_num, pipeline) in group.pipelines.iter().enumerate() { - match output { - Ok(inp) if inp.is_empty() => {} - Ok(inp) => { - // Run autoview on the values we've seen so far - // We may want to make this configurable for other kinds of hosting - if let Some(autoview) = ctx.get_command("autoview") { - let mut output_stream = match ctx.run_command( - autoview, - Tag::unknown(), - Call::new( - Box::new(SpannedExpression::new( - Expression::Synthetic(Synthetic::String("autoview".into())), - Span::unknown(), - )), - Span::unknown(), - ), - inp, - ) { - Ok(x) => x, - Err(e) => { - return Err(e); - } - }; - match output_stream.next() { - Some(Value { - value: UntaggedValue::Error(e), - .. - }) => { - return Err(e); - } - Some(_item) => { - if let Some(err) = ctx.get_errors().get(0) { - ctx.clear_errors(); - return Err(err.clone()); - } - if ctx.ctrl_c().load(Ordering::SeqCst) { - return Ok(InputStream::empty()); - } - } - None => { - if let Some(err) = ctx.get_errors().get(0) { - ctx.clear_errors(); - return Err(err.clone()); - } - } - } - } else { - let _: Vec<_> = inp.collect(); - } - } - Err(e) => { - return Err(e); - } - } - output = Ok(OutputStream::empty()); - - match output { - Ok(inp) if inp.is_empty() => {} - Ok(mut output_stream) => { - match output_stream.next() { - Some(Value { - value: UntaggedValue::Error(e), - .. - }) => { - return Err(e); - } - Some(_item) => { - if let Some(err) = ctx.get_errors().get(0) { - ctx.clear_errors(); - return Err(err.clone()); - } - if ctx.ctrl_c().load(Ordering::SeqCst) { - // This early return doesn't return the result - // we have so far, but breaking out of this loop - // causes lifetime issues. A future contribution - // could attempt to return the current output. - // https://github.com/nushell/nushell/pull/2830#discussion_r550319687 - return Ok(InputStream::empty()); - } - } - None => { - if let Some(err) = ctx.get_errors().get(0) { - ctx.clear_errors(); - return Err(err.clone()); - } - } - } - } - Err(e) => { - return Err(e); - } - } - output = if group_num == (num_groups - 1) && pipeline_num == (num_pipelines - 1) { - // we're at the end of the block, so use the given external redirection - run_pipeline(pipeline, ctx, input, external_redirection) - } else { - // otherwise, we're in the middle of the block, so use a default redirection - run_pipeline(pipeline, ctx, input, ExternalRedirection::None) - }; - - input = OutputStream::empty(); - } - } - - output -} - -fn run_pipeline( - commands: &Pipeline, - ctx: &EvaluationContext, - mut input: InputStream, - external_redirection: ExternalRedirection, -) -> Result { - let num_commands = commands.list.len(); - for (command_num, command) in commands.list.iter().enumerate() { - input = match command { - ClassifiedCommand::Dynamic(call) => { - let mut args = vec![]; - if let Some(positional) = &call.positional { - for pos in positional { - let result = run_expression_block(pos, ctx)?.into_vec(); - args.push(result); - } - } - - let block = run_expression_block(&call.head, ctx)?.into_vec(); - - if block.len() != 1 { - return Err(ShellError::labeled_error( - "Dynamic commands must start with a block", - "needs to be a block", - call.head.span, - )); - } - - match &block[0].value { - UntaggedValue::Block(captured_block) => { - ctx.scope.enter_scope(); - ctx.scope.add_vars(&captured_block.captured.entries); - for (param, value) in - captured_block.block.params.positional.iter().zip(&args) - { - ctx.scope.add_var(param.0.name(), value[0].clone()); - } - - let result = - run_block(&captured_block.block, ctx, input, external_redirection); - ctx.scope.exit_scope(); - - result? - } - _ => { - return Err(ShellError::labeled_error("Dynamic commands must start with a block (or variable pointing to a block)", "needs to be a block", call.head.span)); - } - } - } - - ClassifiedCommand::Expr(expr) => run_expression_block(expr, ctx)?, - - ClassifiedCommand::Error(err) => return Err(err.clone().into()), - - ClassifiedCommand::Internal(left) => { - if command_num == (num_commands - 1) { - let mut left = left.clone(); - left.args.external_redirection = external_redirection; - run_internal_command(&left, ctx, input)? - } else { - run_internal_command(left, ctx, input)? - } - } - }; - } - - Ok(input) -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/envvar.rs b/old_nushell/crates/nu-engine/src/evaluate/envvar.rs deleted file mode 100644 index 068f204b0..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/envvar.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::convert::TryFrom; - -use nu_errors::ShellError; -use nu_protocol::{SpannedTypeName, Value}; - -#[derive(Debug, Clone)] -pub enum EnvVar { - Proper(String), - Nothing, -} - -impl TryFrom for EnvVar { - type Error = ShellError; - - fn try_from(value: Value) -> Result { - if value.value.is_none() { - Ok(EnvVar::Nothing) - } else if value.is_primitive() { - Ok(EnvVar::Proper(value.convert_to_string())) - } else { - Err(ShellError::type_error( - "primitive", - value.spanned_type_name(), - )) - } - } -} - -impl TryFrom<&Value> for EnvVar { - type Error = ShellError; - - fn try_from(value: &Value) -> Result { - if value.value.is_none() { - Ok(EnvVar::Nothing) - } else if value.is_primitive() { - Ok(EnvVar::Proper(value.convert_to_string())) - } else { - Err(ShellError::type_error( - "primitive", - value.spanned_type_name(), - )) - } - } -} - -impl From for EnvVar { - fn from(string: String) -> Self { - EnvVar::Proper(string) - } -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/evaluate_args.rs b/old_nushell/crates/nu-engine/src/evaluate/evaluate_args.rs deleted file mode 100644 index ecf47e244..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/evaluate_args.rs +++ /dev/null @@ -1,50 +0,0 @@ -// TODO: Temporary redirect -use crate::evaluate::evaluator::evaluate_baseline_expr; -use crate::evaluation_context::EvaluationContext; -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_protocol::{hir, EvaluatedArgs, UntaggedValue, Value}; - -pub(crate) fn evaluate_args( - call: &hir::Call, - ctx: &EvaluationContext, -) -> Result { - let mut positional_args: Vec = vec![]; - - if let Some(positional) = &call.positional { - for pos in positional { - let result = evaluate_baseline_expr(pos, ctx)?; - positional_args.push(result); - } - } - - let positional = if !positional_args.is_empty() { - Some(positional_args) - } else { - None - }; - - let mut named_args = IndexMap::new(); - - if let Some(named) = &call.named { - for (name, value) in named { - match value { - hir::NamedValue::PresentSwitch(tag) => { - named_args.insert(name.clone(), UntaggedValue::boolean(true).into_value(tag)); - } - hir::NamedValue::Value(_, expr) => { - named_args.insert(name.clone(), evaluate_baseline_expr(expr, ctx)?); - } - _ => {} - }; - } - } - - let named = if !named_args.is_empty() { - Some(named_args) - } else { - None - }; - - Ok(EvaluatedArgs::new(positional, named)) -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/evaluator.rs b/old_nushell/crates/nu-engine/src/evaluate/evaluator.rs deleted file mode 100644 index 005f4d3dc..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/evaluator.rs +++ /dev/null @@ -1,328 +0,0 @@ -use crate::evaluate::block::run_block; -use crate::evaluate::operator::apply_operator; -use crate::evaluation_context::EvaluationContext; -use indexmap::IndexMap; -use log::trace; -use nu_errors::{ArgumentError, ShellError}; -use nu_protocol::did_you_mean; -use nu_protocol::{ - hir::{self, CapturedBlock, Expression, RangeOperator, SpannedExpression}, - Dictionary, -}; -use nu_protocol::{ - ColumnPath, Primitive, RangeInclusion, UnspannedPathMember, UntaggedValue, Value, -}; -use nu_source::{Span, SpannedItem, Tag}; -use nu_stream::InputStream; -use nu_value_ext::ValueExt; - -pub fn evaluate_baseline_expr( - expr: &SpannedExpression, - ctx: &EvaluationContext, -) -> Result { - let tag = Tag { - span: expr.span, - anchor: None, - }; - let span = expr.span; - match &expr.expr { - Expression::Literal(literal) => Ok(evaluate_literal(literal, span)), - Expression::ExternalWord => Err(ShellError::argument_error( - "Invalid external word".spanned(tag.span), - ArgumentError::InvalidExternalWord, - )), - Expression::FilePath(path) => Ok(UntaggedValue::filepath(path.clone()).into_value(tag)), - Expression::Synthetic(hir::Synthetic::String(s)) => { - Ok(UntaggedValue::string(s).into_untagged_value()) - } - expr @ Expression::Variable(_, _) => evaluate_reference(&Variable::from(expr), ctx, span), - Expression::Command => unimplemented!(), - Expression::Subexpression(block) => evaluate_subexpression(block, ctx), - Expression::ExternalCommand(_) => unimplemented!(), - Expression::Binary(binary) => { - // TODO: If we want to add short-circuiting, we'll need to move these down - let left = evaluate_baseline_expr(&binary.left, ctx)?; - let right = evaluate_baseline_expr(&binary.right, ctx)?; - - trace!("left={:?} right={:?}", left.value, right.value); - - match binary.op.expr { - Expression::Literal(hir::Literal::Operator(op)) => { - match apply_operator(op, &left, &right) { - Ok(result) => match result { - UntaggedValue::Error(shell_err) => Err(shell_err), - _ => Ok(result.into_value(tag)), - }, - Err((left_type, right_type)) => Err(ShellError::coerce_error( - left_type.spanned(binary.left.span), - right_type.spanned(binary.right.span), - )), - } - } - _ => Err(ShellError::labeled_error( - "Unknown operator", - "unknown operator", - binary.op.span, - )), - } - } - Expression::Range(range) => { - let left = if let Some(left) = &range.left { - evaluate_baseline_expr(left, ctx)? - } else { - Value::nothing() - }; - - let right = if let Some(right) = &range.right { - evaluate_baseline_expr(right, ctx)? - } else { - Value::nothing() - }; - - let left_span = left.tag.span; - let right_span = right.tag.span; - - let left = ( - left.as_primitive()?.spanned(left_span), - RangeInclusion::Inclusive, - ); - let right = ( - right.as_primitive()?.spanned(right_span), - match &range.operator.item { - RangeOperator::Inclusive => RangeInclusion::Inclusive, - RangeOperator::RightExclusive => RangeInclusion::Exclusive, - }, - ); - - Ok(UntaggedValue::range(left, right).into_value(tag)) - } - Expression::Table(headers, cells) => { - let mut output_headers = vec![]; - - for expr in headers { - let val = evaluate_baseline_expr(expr, ctx)?; - - let header = val.as_string()?; - output_headers.push(header); - } - - let mut output_table = vec![]; - - for row in cells { - if row.len() != headers.len() { - match (row.first(), row.last()) { - (Some(first), Some(last)) => { - return Err(ShellError::labeled_error( - "Cell count doesn't match header count", - format!("expected {} columns", headers.len()), - Span::new(first.span.start(), last.span.end()), - )); - } - _ => { - return Err(ShellError::untagged_runtime_error( - "Cell count doesn't match header count", - )); - } - } - } - - let mut row_output = IndexMap::new(); - for cell in output_headers.iter().zip(row) { - let val = evaluate_baseline_expr(cell.1, ctx)?; - row_output.insert(cell.0.clone(), val); - } - output_table.push(UntaggedValue::row(row_output).into_value(tag.clone())); - } - - Ok(UntaggedValue::Table(output_table).into_value(tag)) - } - Expression::List(list) => { - let mut exprs = vec![]; - - for expr in list { - let expr = evaluate_baseline_expr(expr, ctx)?; - exprs.push(expr); - } - - Ok(UntaggedValue::Table(exprs).into_value(tag)) - } - Expression::Block(block) => { - // Capture the current values of all free variables - let mut known_variables = vec![]; - let free_variables = block.get_free_variables(&mut known_variables); - - let mut captured = Dictionary::new(IndexMap::new()); - for free_variable in &free_variables { - if let Some(v) = ctx.scope.get_var(free_variable) { - captured.insert(free_variable.into(), v.clone()); - } - } - - Ok( - UntaggedValue::Block(Box::new(CapturedBlock::new(block.clone(), captured))) - .into_value(&tag), - ) - } - Expression::FullColumnPath(path) => { - let value = evaluate_baseline_expr(&path.head, ctx)?; - let mut item = value; - - for member in &path.tail { - let next = item.get_data_by_member(member); - - match next { - Err(err) => match &member.unspanned { - UnspannedPathMember::String(_name) => { - let possible_matches = did_you_mean(&item, member.as_string()); - - match possible_matches { - Some(p) => { - return Err(ShellError::labeled_error( - "Unknown column", - format!("did you mean '{}'?", p[0]), - &member.span, - )); - } - None => return Err(err), - } - } - UnspannedPathMember::Int(_row) => { - return Err(ShellError::labeled_error( - "Unknown row", - "unknown row", - &member.span, - )); - } - }, - Ok(next) => { - item = next.clone().value.into_value(&tag); - } - }; - } - - if path.tail.is_empty() { - Ok(item) - } else { - Ok(item.value.into_value(tag)) - } - } - Expression::Boolean(_boolean) => Ok(UntaggedValue::boolean(*_boolean).into_value(tag)), - Expression::Garbage => unimplemented!(), - } -} - -fn evaluate_literal(literal: &hir::Literal, span: Span) -> Value { - match &literal { - hir::Literal::ColumnPath(path) => { - let members = path.iter().map(|member| member.to_path_member()).collect(); - - UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::new(members))) - .into_value(span) - } - hir::Literal::Number(int) => match int { - nu_protocol::hir::Number::BigInt(i) => { - UntaggedValue::big_int(i.clone()).into_value(span) - } - nu_protocol::hir::Number::Int(i) => UntaggedValue::int(*i).into_value(span), - nu_protocol::hir::Number::Decimal(d) => { - UntaggedValue::decimal(d.clone()).into_value(span) - } - }, - hir::Literal::Size(int, unit) => unit.compute(int).into_value(span), - hir::Literal::String(string) => UntaggedValue::string(string).into_value(span), - hir::Literal::GlobPattern(pattern) => UntaggedValue::glob_pattern(pattern).into_value(span), - hir::Literal::Bare(bare) => UntaggedValue::string(bare.clone()).into_value(span), - hir::Literal::Operator(_) => unimplemented!("Not sure what to do with operator yet"), - } -} - -pub enum Variable<'a> { - Nu, - Scope, - True, - False, - Nothing, - Other(&'a str), -} - -impl<'a> Variable<'a> { - pub fn list() -> Vec { - vec![ - String::from("$nu"), - String::from("$scope"), - String::from("$true"), - String::from("$false"), - String::from("$nothing"), - ] - } -} - -impl<'a> From<&'a Expression> for Variable<'a> { - fn from(expr: &'a Expression) -> Self { - match &expr { - Expression::Variable(name, _) => match name.as_str() { - "$nu" => Self::Nu, - "$scope" => Self::Scope, - "$true" => Self::True, - "$false" => Self::False, - "$nothing" => Self::Nothing, - _ => Self::Other(name), - }, - _ => unreachable!(), - } - } -} - -pub fn evaluate_reference( - variable: &Variable, - ctx: &EvaluationContext, - tag: impl Into, -) -> Result { - match variable { - Variable::Nu => crate::evaluate::variables::nu(&ctx.scope, ctx), - Variable::Scope => crate::evaluate::variables::scope( - &ctx.scope.get_aliases(), - &ctx.scope.get_commands(), - &ctx.scope.get_vars(), - ), - Variable::True => Ok(UntaggedValue::boolean(true).into_untagged_value()), - Variable::False => Ok(UntaggedValue::boolean(false).into_untagged_value()), - Variable::Nothing => Ok(UntaggedValue::nothing().into_untagged_value()), - Variable::Other(name) => match ctx.scope.get_var(name) { - Some(v) => Ok(v), - None => Err(ShellError::labeled_error( - "Variable not in scope", - format!("unknown variable: {}", name), - tag.into(), - )), - }, - } -} - -fn evaluate_subexpression( - block: &hir::Block, - ctx: &EvaluationContext, -) -> Result { - // FIXME: we should use a real context here - let input = match ctx.scope.get_var("$it") { - Some(it) => InputStream::one(it), - None => InputStream::empty(), - }; - - let result = run_block(block, ctx, input, hir::ExternalRedirection::Stdout)?; - - let output = result.into_vec(); - - if let Some(e) = ctx.get_errors().get(0) { - return Err(e.clone()); - } - - match output.len() { - x if x > 1 => { - let tag = output[0].tag.clone(); - Ok(UntaggedValue::Table(output).into_value(tag)) - } - 1 => Ok(output[0].clone()), - _ => Ok(UntaggedValue::nothing().into_value(Tag::unknown())), - } -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/expr.rs b/old_nushell/crates/nu-engine/src/evaluate/expr.rs deleted file mode 100644 index 5fee9088a..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/expr.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::evaluate_baseline_expr; - -use log::{log_enabled, trace}; - -use crate::evaluation_context::EvaluationContext; -use nu_errors::ShellError; -use nu_protocol::hir::SpannedExpression; -use nu_protocol::{UntaggedValue, Value}; -use nu_stream::{InputStream, IntoInputStream}; - -pub(crate) fn run_expression_block( - expr: &SpannedExpression, - ctx: &EvaluationContext, -) -> Result { - if log_enabled!(log::Level::Trace) { - trace!(target: "nu::run::expr", "->"); - trace!(target: "nu::run::expr", "{:?}", expr); - } - - let output = evaluate_baseline_expr(expr, ctx)?; - - match output { - Value { - value: UntaggedValue::Table(x), - .. - } => Ok(InputStream::from_stream(x.into_iter())), - output => Ok(std::iter::once(Ok(output)).into_input_stream()), - } -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/internal.rs b/old_nushell/crates/nu-engine/src/evaluate/internal.rs deleted file mode 100644 index 7ec897805..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/internal.rs +++ /dev/null @@ -1,231 +0,0 @@ -use crate::call_info::UnevaluatedCallInfo; -use crate::evaluation_context::EvaluationContext; -use crate::filesystem::filesystem_shell::{FilesystemShell, FilesystemShellMode}; -use crate::shell::value_shell::ValueShell; -use crate::CommandArgs; -use log::{log_enabled, trace}; -use nu_errors::ShellError; -use nu_protocol::hir::{ - Expression, ExternalRedirection, InternalCommand, SpannedExpression, Synthetic, -}; -use nu_protocol::{CommandAction, ReturnSuccess, UntaggedValue, Value}; -use nu_source::{PrettyDebug, Span, Tag}; -use nu_stream::{ActionStream, InputStream}; - -pub(crate) fn run_internal_command( - command: &InternalCommand, - context: &EvaluationContext, - input: InputStream, -) -> Result { - if log_enabled!(log::Level::Trace) { - trace!(target: "nu::run::internal", "->"); - trace!(target: "nu::run::internal", "{}", command.name); - } - - let objects: InputStream = input; - - let internal_command = context.scope.expect_command(&command.name); - let internal_command = internal_command?; - - let result = context.run_command( - internal_command, - Tag::unknown_anchor(command.name_span), - command.args.clone(), // FIXME: this is inefficient - objects, - )?; - Ok(InputStream::from_stream(InternalIteratorSimple { - context: context.clone(), - input: result, - })) -} - -struct InternalIteratorSimple { - context: EvaluationContext, - input: InputStream, -} - -impl Iterator for InternalIteratorSimple { - type Item = Value; - - fn next(&mut self) -> Option { - match self.input.next() { - Some(Value { - value: UntaggedValue::Error(err), - .. - }) => { - self.context.error(err); - None - } - x => x, - } - } -} - -pub struct InternalIterator { - pub context: EvaluationContext, - pub leftovers: InputStream, - pub input: ActionStream, -} - -impl Iterator for InternalIterator { - type Item = Value; - - fn next(&mut self) -> Option { - if let Some(output) = self.leftovers.next() { - return Some(output); - } - - while let Some(item) = self.input.next() { - match item { - Ok(ReturnSuccess::Action(action)) => match action { - CommandAction::ChangePath(path) => { - self.context.shell_manager().set_path(path); - } - CommandAction::Exit(code) => std::process::exit(code), // TODO: save history.txt - CommandAction::Error(err) => { - self.context.error(err); - return None; - } - CommandAction::AutoConvert(tagged_contents, extension) => { - let contents_tag = tagged_contents.tag.clone(); - let command_name = format!("from {}", extension); - if let Some(converter) = self.context.scope.get_command(&command_name) { - let new_args = CommandArgs { - context: self.context.clone(), - call_info: UnevaluatedCallInfo { - args: nu_protocol::hir::Call { - head: Box::new(SpannedExpression { - expr: Expression::Synthetic(Synthetic::String( - command_name.clone(), - )), - span: tagged_contents.tag().span, - }), - positional: None, - named: None, - span: Span::unknown(), - external_redirection: ExternalRedirection::Stdout, - }, - name_tag: tagged_contents.tag(), - }, - input: InputStream::one(tagged_contents), - }; - let result = converter.run(new_args); - - match result { - Ok(mut result) => { - if let Some(x) = result.next() { - self.leftovers = - InputStream::from_stream(result.map(move |x| Value { - value: x.value, - tag: contents_tag.clone(), - })); - return Some(x); - } else { - return None; - } - } - Err(err) => { - self.leftovers = InputStream::empty(); - return Some(Value::error(err)); - } - } - } else { - return Some(tagged_contents); - } - } - CommandAction::EnterValueShell(value) => { - self.context - .shell_manager() - .insert_at_current(Box::new(ValueShell::new(value))); - } - CommandAction::EnterShell(location) => { - let mode = if self.context.shell_manager().is_interactive() { - FilesystemShellMode::Cli - } else { - FilesystemShellMode::Script - }; - self.context.shell_manager().insert_at_current(Box::new( - match FilesystemShell::with_location(location, mode) { - Ok(v) => v, - Err(err) => { - self.context.error(err.into()); - break; - } - }, - )); - } - CommandAction::AddPlugins(path) => { - match crate::plugin::build_plugin::scan(vec![std::path::PathBuf::from( - path, - )]) { - Ok(plugins) => { - self.context.add_commands( - plugins - .into_iter() - .filter(|p| !self.context.is_command_registered(p.name())) - .collect(), - ); - } - Err(reason) => { - self.context.error(reason); - } - } - } - CommandAction::PreviousShell => { - self.context.shell_manager().prev(); - } - CommandAction::NextShell => { - self.context.shell_manager().next(); - } - CommandAction::GotoShell(i) => { - self.context.shell_manager().goto(i); - } - CommandAction::LeaveShell(code) => { - self.context.shell_manager().remove_at_current(); - if self.context.shell_manager().is_empty() { - std::process::exit(code); // TODO: save history.txt - } - } - CommandAction::UnloadConfig(cfg_path) => { - self.context.unload_config(&cfg_path); - } - CommandAction::LoadConfig(cfg_path) => { - if let Err(e) = self.context.load_config(&cfg_path) { - return Some(UntaggedValue::Error(e).into_untagged_value()); - } - } - }, - - Ok(ReturnSuccess::Value(Value { - value: UntaggedValue::Error(err), - .. - })) => { - self.context.error(err); - return None; - } - - Ok(ReturnSuccess::Value(v)) => return Some(v), - - Ok(ReturnSuccess::DebugValue(v)) => { - let doc = PrettyDebug::pretty_doc(&v); - let mut buffer = termcolor::Buffer::ansi(); - - let _ = doc.render_raw( - self.context.with_host(|host| host.width() - 5), - &mut nu_source::TermColored::new(&mut buffer), - ); - - let value = String::from_utf8_lossy(buffer.as_slice()); - - return Some(UntaggedValue::string(value).into_untagged_value()); - } - - Err(err) => { - self.context.error(err); - } - } - } - - None - } -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/lang.rs b/old_nushell/crates/nu-engine/src/evaluate/lang.rs deleted file mode 100644 index 8afe7ac1b..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/lang.rs +++ /dev/null @@ -1,209 +0,0 @@ -use crate::Scope; -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, Signature, UntaggedValue, Value}; -use nu_source::Tag; - -pub struct Lang; - -impl Lang { - pub fn query_commands(scope: &Scope) -> Result, ShellError> { - let tag = Tag::unknown(); - let full_commands = scope.get_commands_info(); - let mut cmd_vec = Vec::new(); - for (key, cmd) in full_commands { - let mut indexmap = IndexMap::new(); - let mut sig = cmd.signature(); - // eprintln!("{}", get_signature(&sig)); - indexmap.insert( - "name".to_string(), - UntaggedValue::string(key).into_value(&tag), - ); - indexmap.insert( - "usage".to_string(), - UntaggedValue::string(cmd.usage().to_string()).into_value(&tag), - ); - // let sig_deser = serde_json::to_string(&sig).unwrap(); - // indexmap.insert( - // "signature".to_string(), - // UntaggedValue::string(sig_deser).into_value(&tag), - // ); - let signature_table = get_signature(&mut sig, tag.clone()); - indexmap.insert( - "signature".to_string(), - UntaggedValue::Table(signature_table).into_value(&tag), - ); - indexmap.insert( - "is_filter".to_string(), - UntaggedValue::boolean(sig.is_filter).into_value(&tag), - ); - indexmap.insert( - "is_builtin".to_string(), - UntaggedValue::boolean(cmd.is_builtin()).into_value(&tag), - ); - indexmap.insert( - "is_sub".to_string(), - UntaggedValue::boolean(cmd.is_sub()).into_value(&tag), - ); - indexmap.insert( - "is_plugin".to_string(), - UntaggedValue::boolean(cmd.is_plugin()).into_value(&tag), - ); - indexmap.insert( - "is_custom".to_string(), - UntaggedValue::boolean(cmd.is_custom()).into_value(&tag), - ); - indexmap.insert( - "is_private".to_string(), - UntaggedValue::boolean(cmd.is_private()).into_value(&tag), - ); - indexmap.insert( - "is_binary".to_string(), - UntaggedValue::boolean(cmd.is_binary()).into_value(&tag), - ); - indexmap.insert( - "extra_usage".to_string(), - UntaggedValue::string(cmd.extra_usage().to_string()).into_value(&tag), - ); - - cmd_vec.push(UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)); - } - - Ok(cmd_vec) - } -} - -fn get_signature(sig: &mut Signature, tag: Tag) -> Vec { - sig.remove_named("help"); - let p = &sig.positional; - let r = &sig.rest_positional; - let n = &sig.named; - let name = &sig.name; - let mut sig_vec: Vec = Vec::new(); - - for item in p { - let mut indexmap = IndexMap::new(); - - let (parameter, syntax_shape) = item.0.get_type_description(); - let description = &item.1; - // let output = format!( - // "Positional|{}|{}|{}|{}\n", - // name, parameter, syntax_shape, description - // ); - // eprintln!("{}", output); - - indexmap.insert( - "cmd_name".to_string(), - UntaggedValue::string(name).into_value(&tag), - ); - indexmap.insert( - "parameter_name".to_string(), - UntaggedValue::string(parameter).into_value(&tag), - ); - indexmap.insert( - "parameter_type".to_string(), - UntaggedValue::string("positional".to_string()).into_value(&tag), - ); - indexmap.insert( - "syntax_shape".to_string(), - UntaggedValue::string(syntax_shape).into_value(&tag), - ); - indexmap.insert( - "description".to_string(), - UntaggedValue::string(description).into_value(&tag), - ); - indexmap.insert( - "flag_name".to_string(), - UntaggedValue::string("".to_string()).into_value(&tag), - ); - indexmap.insert( - "flag_type".to_string(), - UntaggedValue::string("".to_string()).into_value(&tag), - ); - - sig_vec.push(UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)); - } - - match r { - Some((rest_name, shape, desc)) => { - let mut indexmap = IndexMap::new(); - // let output = format!("Rest|{}|{}|{}\n", name, shape.syntax_shape_name(), desc); - // eprintln!("{}", output); - - indexmap.insert( - "cmd_name".to_string(), - UntaggedValue::string(name).into_value(&tag), - ); - indexmap.insert( - "parameter_name".to_string(), - UntaggedValue::string(rest_name.to_string()).into_value(&tag), - ); - indexmap.insert( - "parameter_type".to_string(), - UntaggedValue::string("rest".to_string()).into_value(&tag), - ); - indexmap.insert( - "syntax_shape".to_string(), - UntaggedValue::string(shape.syntax_shape_name()).into_value(&tag), - ); - indexmap.insert( - "description".to_string(), - UntaggedValue::string(desc).into_value(&tag), - ); - indexmap.insert( - "flag_name".to_string(), - UntaggedValue::string("".to_string()).into_value(&tag), - ); - indexmap.insert( - "flag_type".to_string(), - UntaggedValue::string("".to_string()).into_value(&tag), - ); - - sig_vec.push(UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)); - } - None => {} - } - - for (parameter, (b, description)) in n { - let mut indexmap = IndexMap::new(); - - let (named_type, flag_name, shape) = b.get_type_description(); - // let output = format!( - // "Named|{}|{}|{}|{}|{}|{}\n", - // name, parameter, named_type, flag_name, shape, description - // ); - // eprint!("{}", output); - - indexmap.insert( - "cmd_name".to_string(), - UntaggedValue::string(name).into_value(&tag), - ); - indexmap.insert( - "parameter_name".to_string(), - UntaggedValue::string(parameter).into_value(&tag), - ); - indexmap.insert( - "parameter_type".to_string(), - UntaggedValue::string("named".to_string()).into_value(&tag), - ); - indexmap.insert( - "syntax_shape".to_string(), - UntaggedValue::string(shape).into_value(&tag), - ); - indexmap.insert( - "description".to_string(), - UntaggedValue::string(description).into_value(&tag), - ); - indexmap.insert( - "flag_name".to_string(), - UntaggedValue::string(flag_name).into_value(&tag), - ); - indexmap.insert( - "flag_type".to_string(), - UntaggedValue::string(named_type).into_value(&tag), - ); - sig_vec.push(UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)); - } - - sig_vec -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/mod.rs b/old_nushell/crates/nu-engine/src/evaluate/mod.rs deleted file mode 100644 index 5bfc7fded..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub(crate) mod block; -pub(crate) mod envvar; -pub(crate) mod evaluate_args; -pub mod evaluator; -pub(crate) mod expr; -pub mod internal; -pub(crate) mod lang; -pub(crate) mod operator; -pub(crate) mod scope; -pub(crate) mod variables; diff --git a/old_nushell/crates/nu-engine/src/evaluate/operator.rs b/old_nushell/crates/nu-engine/src/evaluate/operator.rs deleted file mode 100644 index c6318382d..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/operator.rs +++ /dev/null @@ -1,111 +0,0 @@ -use nu_data::{value, value::compare_values}; -use nu_errors::ShellError; -use nu_protocol::hir::Operator; -use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value}; -use std::ops::Not; - -#[cfg(feature = "dataframe")] -use nu_protocol::dataframe::{compute_between_dataframes, compute_series_single_value}; - -pub fn apply_operator( - op: Operator, - left: &Value, - right: &Value, -) -> Result { - #[cfg(feature = "dataframe")] - if let (UntaggedValue::DataFrame(_), UntaggedValue::DataFrame(_)) = (&left.value, &right.value) - { - return compute_between_dataframes(op, left, right); - } else if let (UntaggedValue::DataFrame(_), UntaggedValue::Primitive(_)) = - (&left.value, &right.value) - { - return compute_series_single_value(op, left, right); - } - - match op { - Operator::Equal - | Operator::NotEqual - | Operator::LessThan - | Operator::GreaterThan - | Operator::LessThanOrEqual - | Operator::GreaterThanOrEqual => { - value::compare_values(op, left, right).map(UntaggedValue::boolean) - } - Operator::Contains => string_contains(left, right).map(UntaggedValue::boolean), - Operator::NotContains => string_contains(left, right) - .map(Not::not) - .map(UntaggedValue::boolean), - Operator::Plus => value::compute_values(op, left, right), - Operator::Minus => value::compute_values(op, left, right), - Operator::Multiply => value::compute_values(op, left, right), - Operator::Pow => value::compute_values(op, left, right), - Operator::Divide => value::compute_values(op, left, right).map(|res| match res { - UntaggedValue::Error(_) => UntaggedValue::Error(ShellError::labeled_error( - "Evaluation error", - "division by zero", - &right.tag.span, - )), - _ => res, - }), - Operator::Modulo => value::compute_values(op, left, right).map(|res| match res { - UntaggedValue::Error(_) => UntaggedValue::Error(ShellError::labeled_error( - "Evaluation error", - "division by zero", - &right.tag.span, - )), - _ => res, - }), - Operator::In => inside_of(left, right).map(UntaggedValue::boolean), - Operator::NotIn => inside_of(left, right).map(|x| UntaggedValue::boolean(!x)), - Operator::And => match (left.as_bool(), right.as_bool()) { - (Ok(left), Ok(right)) => Ok(UntaggedValue::boolean(left && right)), - _ => Err((left.type_name(), right.type_name())), - }, - Operator::Or => match (left.as_bool(), right.as_bool()) { - (Ok(left), Ok(right)) => Ok(UntaggedValue::boolean(left || right)), - _ => Err((left.type_name(), right.type_name())), - }, - } -} - -fn string_contains( - left: &UntaggedValue, - right: &UntaggedValue, -) -> Result { - match (left, right) { - ( - UntaggedValue::Primitive(Primitive::String(l)), - UntaggedValue::Primitive(Primitive::String(r)), - ) => Ok(l.contains(r)), - ( - UntaggedValue::Primitive(Primitive::FilePath(l)), - UntaggedValue::Primitive(Primitive::String(r)), - ) => Ok(l.as_path().display().to_string().contains(r)), - ( - UntaggedValue::Primitive(Primitive::String(l)), - UntaggedValue::Primitive(Primitive::FilePath(r)), - ) => Ok(l.contains(&r.as_path().display().to_string())), - _ => Err((left.type_name(), right.type_name())), - } -} - -fn inside_of( - left: &UntaggedValue, - right: &UntaggedValue, -) -> Result { - match (left, right) { - (_, UntaggedValue::Table(values)) => { - Ok(values - .iter() - .any(|x| match compare_values(Operator::Equal, left, &x.value) { - Ok(coerced) => coerced, - _ => false, - })) - } - ( - UntaggedValue::Primitive(Primitive::String(lhs)), - UntaggedValue::Primitive(Primitive::String(rhs)), - ) => Ok(rhs.contains(lhs)), - _ => Err((left.type_name(), right.type_name())), - } -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/scope.rs b/old_nushell/crates/nu-engine/src/evaluate/scope.rs deleted file mode 100644 index 32b6dc472..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/scope.rs +++ /dev/null @@ -1,508 +0,0 @@ -use crate::{ - evaluate::envvar::EnvVar, - whole_stream_command::{whole_stream_command, Command}, -}; -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_parser::ParserScope; -use nu_protocol::{hir::Block, Signature, SignatureRegistry, Value}; -use nu_source::Spanned; -use std::sync::Arc; - -#[derive(Debug, Clone)] -pub struct Scope { - frames: Arc>>, -} - -impl Default for Scope { - fn default() -> Self { - Self::new() - } -} - -impl Scope { - pub fn new() -> Scope { - Scope { - frames: Arc::new(parking_lot::Mutex::new(vec![ScopeFrame::new()])), - } - } - - pub fn get_command(&self, name: &str) -> Option { - for frame in self.frames.lock().iter().rev() { - if let Some(command) = frame.get_command(name) { - return Some(command); - } - } - - None - } - - pub fn get_aliases(&self) -> IndexMap>> { - let mut output: IndexMap>> = IndexMap::new(); - - for frame in self.frames.lock().iter().rev() { - for v in &frame.aliases { - if !output.contains_key(v.0) { - output.insert(v.0.clone(), v.1.clone()); - } - } - } - - output.sorted_by(|k1, _v1, k2, _v2| k1.cmp(k2)).collect() - } - - pub fn get_commands(&self) -> IndexMap { - let mut output: IndexMap = IndexMap::new(); - - for frame in self.frames.lock().iter().rev() { - for (name, command) in &frame.commands { - if !output.contains_key(name) { - let mut sig = command.signature(); - // don't show --help and -h in the command arguments for $scope.commands - sig.remove_named("help"); - output.insert(name.clone(), sig); - } - } - } - - output.sorted_by(|k1, _v1, k2, _v2| k1.cmp(k2)).collect() - } - - pub fn get_commands_info(&self) -> IndexMap { - let mut output: IndexMap = IndexMap::new(); - - for frame in self.frames.lock().iter().rev() { - for (name, command) in &frame.commands { - if !output.contains_key(name) { - output.insert(name.clone(), command.clone()); - } - } - } - - output.sorted_by(|k1, _v1, k2, _v2| k1.cmp(k2)).collect() - } - - pub fn get_variable_names(&self) -> Vec { - self.get_vars().iter().map(|(k, _)| k.to_string()).collect() - } - - pub fn get_vars(&self) -> IndexMap { - //FIXME: should this be an iterator? - let mut output: IndexMap = IndexMap::new(); - - for frame in self.frames.lock().iter().rev() { - for v in &frame.vars { - if !output.contains_key(v.0) { - output.insert(v.0.clone(), v.1.clone()); - } - } - } - - output.sorted_by(|k1, _v1, k2, _v2| k1.cmp(k2)).collect() - } - - pub fn get_aliases_with_name(&self, name: &str) -> Option>>> { - let aliases: Vec<_> = self - .frames - .lock() - .iter() - .rev() - .filter_map(|frame| frame.aliases.get(name).cloned()) - .collect(); - if aliases.is_empty() { - None - } else { - Some(aliases) - } - } - - pub fn get_custom_commands_with_name(&self, name: &str) -> Option>> { - let custom_commands: Vec<_> = self - .frames - .lock() - .iter() - .rev() - .filter_map(|frame| frame.custom_commands.get(name).cloned()) - .collect(); - - if custom_commands.is_empty() { - None - } else { - Some(custom_commands) - } - } - - pub fn add_command(&self, name: String, command: Command) { - // Note: this is assumed to always be true, as there is always a global top frame - if let Some(frame) = self.frames.lock().last_mut() { - frame.add_command(name, command) - } - } - - pub fn get_alias_names(&self) -> Vec { - let mut names = vec![]; - - for frame in self.frames.lock().iter() { - let mut frame_command_names = frame.get_alias_names(); - names.append(&mut frame_command_names); - } - - // Sort needs to happen first because dedup works on consecutive dupes only - names.sort(); - names.dedup(); - - names - } - - pub fn get_command_names(&self) -> Vec { - let mut names = vec![]; - - for frame in self.frames.lock().iter() { - let mut frame_command_names = frame.get_command_names(); - frame_command_names.extend(frame.get_alias_names()); - frame_command_names.extend(frame.get_custom_command_names()); - names.append(&mut frame_command_names); - } - - // Sort needs to happen first because dedup works on consecutive dupes only - names.sort(); - names.dedup(); - - names - } - - pub fn len(&self) -> usize { - self.frames.lock().len() - } - - pub fn is_empty(&self) -> bool { - self.frames.lock().is_empty() - } - - fn has_cmd_helper(&self, name: &str, f: fn(&ScopeFrame, &str) -> bool) -> bool { - self.frames.lock().iter().any(|frame| f(frame, name)) - } - - pub fn has_command(&self, name: &str) -> bool { - self.has_cmd_helper(name, ScopeFrame::has_command) - } - - pub fn has_custom_command(&self, name: &str) -> bool { - self.has_cmd_helper(name, ScopeFrame::has_custom_command) - } - - pub fn has_alias(&self, name: &str) -> bool { - self.has_cmd_helper(name, ScopeFrame::has_alias) - } - - pub fn expect_command(&self, name: &str) -> Result { - if let Some(c) = self.get_command(name) { - Ok(c) - } else { - Err(ShellError::untagged_runtime_error(format!( - "Missing command '{}'", - name - ))) - } - } - - // This is used for starting processes, keep it string -> string - pub fn get_env_vars(&self) -> IndexMap { - //FIXME: should this be an iterator? - let mut output = IndexMap::new(); - - for frame in self.frames.lock().iter().rev() { - for v in &frame.env { - if !output.contains_key(v.0) { - output.insert(v.0.clone(), v.1.clone()); - } - } - } - - output - .into_iter() - .filter_map(|(k, v)| match v { - EnvVar::Proper(s) => Some((k, s)), - EnvVar::Nothing => None, - }) - .collect() - } - - pub fn get_env(&self, name: &str) -> Option { - for frame in self.frames.lock().iter().rev() { - if let Some(v) = frame.env.get(name) { - return match v { - EnvVar::Proper(string) => Some(string.clone()), - EnvVar::Nothing => None, - }; - } - } - - None - } - - pub fn get_var(&self, name: &str) -> Option { - for frame in self.frames.lock().iter().rev() { - if let Some(v) = frame.vars.get(name) { - return Some(v.clone()); - } - } - - None - } - - pub fn add_var(&self, name: impl Into, value: Value) { - if let Some(frame) = self.frames.lock().last_mut() { - frame.vars.insert(name.into(), value); - } - } - - pub fn add_vars(&self, vars: &IndexMap) { - if let Some(frame) = self.frames.lock().last_mut() { - frame - .vars - .extend(vars.iter().map(|(s, v)| (s.clone(), v.clone()))) - } - } - - pub fn add_env_var(&self, name: impl Into, value: impl Into) { - if let Some(frame) = self.frames.lock().last_mut() { - frame.env.insert(name.into(), value.into()); - } - } - - pub fn remove_env_var(&self, name: impl Into) -> Option { - if let Some(frame) = self.frames.lock().last_mut() { - if let Some(val) = frame.env.remove_entry(&name.into()) { - return Some(val.0); - } - } - None - } - - pub fn add_env(&self, env_vars: IndexMap) { - if let Some(frame) = self.frames.lock().last_mut() { - frame.env.extend(env_vars) - } - } - - pub fn add_env_to_base(&self, env_vars: IndexMap) { - if let Some(frame) = self.frames.lock().first_mut() { - frame.env.extend(env_vars) - } - } - - pub fn add_env_var_to_base(&self, name: impl Into, value: impl Into) { - if let Some(frame) = self.frames.lock().first_mut() { - frame.env.insert(name.into(), value.into()); - } - } - - pub fn set_exit_scripts(&self, scripts: Vec) { - if let Some(frame) = self.frames.lock().last_mut() { - frame.exitscripts = scripts - } - } - - pub fn enter_scope_with_tag(&self, tag: String) { - self.frames.lock().push(ScopeFrame::with_tag(tag)); - } - - //Removes the scopeframe with tag. - pub fn exit_scope_with_tag(&self, tag: &str) { - let mut frames = self.frames.lock(); - let tag = Some(tag); - if let Some(i) = frames.iter().rposition(|f| f.tag.as_deref() == tag) { - frames.remove(i); - } - } - - pub fn get_exitscripts_of_frame_with_tag(&self, tag: &str) -> Option> { - let frames = self.frames.lock(); - let tag = Some(tag); - frames.iter().find_map(|f| { - if f.tag.as_deref() == tag { - Some(f.exitscripts.clone()) - } else { - None - } - }) - } - - pub fn get_frame_with_tag(&self, tag: &str) -> Option { - let frames = self.frames.lock(); - let tag = Some(tag); - frames.iter().rev().find_map(|f| { - if f.tag.as_deref() == tag { - Some(f.clone()) - } else { - None - } - }) - } - - pub fn update_frame_with_tag(&self, frame: ScopeFrame, tag: &str) -> Result<(), ShellError> { - let mut frames = self.frames.lock(); - let tag = Some(tag); - for f in frames.iter_mut().rev() { - if f.tag.as_deref() == tag { - *f = frame; - return Ok(()); - } - } - - // Frame not found, return err - Err(ShellError::untagged_runtime_error(format!( - "Can't update frame with tag {:?}. No such frame present!", - tag - ))) - } -} - -impl SignatureRegistry for Scope { - fn names(&self) -> Vec { - self.get_command_names() - } - - fn has(&self, name: &str) -> bool { - self.get_signature(name).is_some() - } - - fn get(&self, name: &str) -> Option { - self.get_signature(name) - } - - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } -} - -impl ParserScope for Scope { - fn get_signature(&self, name: &str) -> Option { - self.get_command(name).map(|x| x.signature()) - } - - fn has_signature(&self, name: &str) -> bool { - self.get_command(name).is_some() - } - - fn add_definition(&self, block: Arc) { - if let Some(frame) = self.frames.lock().last_mut() { - let name = block.params.name.clone(); - frame.custom_commands.insert(name.clone(), block.clone()); - frame.commands.insert(name, whole_stream_command(block)); - } - } - - fn get_definitions(&self) -> Vec> { - let mut blocks = vec![]; - if let Some(frame) = self.frames.lock().last() { - for (_, custom_command) in &frame.custom_commands { - blocks.push(custom_command.clone()); - } - } - blocks - } - - fn get_alias(&self, name: &str) -> Option>> { - for frame in self.frames.lock().iter().rev() { - if let Some(x) = frame.aliases.get(name) { - return Some(x.clone()); - } - } - None - } - - fn add_alias(&self, name: &str, replacement: Vec>) { - // Note: this is assumed to always be true, as there is always a global top frame - if let Some(frame) = self.frames.lock().last_mut() { - frame.aliases.insert(name.to_string(), replacement); - } - } - - fn remove_alias(&self, name: &str) { - if let Some(frame) = self.frames.lock().last_mut() { - frame.aliases.remove(name); - } - } - - fn enter_scope(&self) { - self.frames.lock().push(ScopeFrame::new()); - } - - fn exit_scope(&self) { - self.frames.lock().pop(); - } -} - -/// An evaluation scope. Scopes map variable names to Values and aid in evaluating blocks and expressions. -#[derive(Debug, Clone)] -pub struct ScopeFrame { - pub vars: IndexMap, - pub env: IndexMap, - pub commands: IndexMap, - pub custom_commands: IndexMap>, - pub aliases: IndexMap>>, - ///Optional tag to better identify this scope frame later - pub tag: Option, - pub exitscripts: Vec, -} - -impl Default for ScopeFrame { - fn default() -> Self { - ScopeFrame::new() - } -} - -impl ScopeFrame { - pub fn has_command(&self, name: &str) -> bool { - self.commands.contains_key(name) - } - - pub fn has_custom_command(&self, name: &str) -> bool { - self.custom_commands.contains_key(name) - } - - pub fn has_alias(&self, name: &str) -> bool { - self.aliases.contains_key(name) - } - - pub fn get_alias_names(&self) -> Vec { - self.aliases.keys().map(|x| x.to_string()).collect() - } - - pub fn get_command_names(&self) -> Vec { - self.commands.keys().map(|x| x.to_string()).collect() - } - - pub fn get_custom_command_names(&self) -> Vec { - self.custom_commands.keys().map(|x| x.to_string()).collect() - } - - pub fn add_command(&mut self, name: String, command: Command) { - self.commands.insert(name, command); - } - - pub fn get_command(&self, name: &str) -> Option { - self.commands.get(name).cloned() - } - - pub fn new() -> ScopeFrame { - ScopeFrame { - vars: IndexMap::new(), - env: IndexMap::new(), - commands: IndexMap::new(), - custom_commands: IndexMap::new(), - aliases: IndexMap::new(), - tag: None, - exitscripts: Vec::new(), - } - } - - pub fn with_tag(tag: String) -> ScopeFrame { - let mut scope = ScopeFrame::new(); - scope.tag = Some(tag); - - scope - } -} diff --git a/old_nushell/crates/nu-engine/src/evaluate/variables.rs b/old_nushell/crates/nu-engine/src/evaluate/variables.rs deleted file mode 100644 index 492b4afd9..000000000 --- a/old_nushell/crates/nu-engine/src/evaluate/variables.rs +++ /dev/null @@ -1,159 +0,0 @@ -use crate::{ - evaluate::{lang, scope::Scope}, - EvaluationContext, -}; -use indexmap::IndexMap; -use nu_data::config::path::{default_history_path, history_path}; -use nu_errors::ShellError; -use nu_protocol::{Dictionary, ShellTypeName, Signature, TaggedDictBuilder, UntaggedValue, Value}; -use nu_source::{Spanned, Tag}; - -pub fn nu(scope: &Scope, ctx: &EvaluationContext) -> Result { - let env = &scope.get_env_vars(); - let tag = Tag::unknown(); - - let mut nu_dict = TaggedDictBuilder::new(&tag); - - let mut dict = TaggedDictBuilder::new(&tag); - - for v in env { - if v.0 != "PATH" && v.0 != "Path" { - dict.insert_untagged(v.0, UntaggedValue::string(v.1)); - } - } - - nu_dict.insert_value("env", dict.into_value()); - - nu_dict.insert_value( - "history-path", - UntaggedValue::filepath(default_history_path()).into_value(&tag), - ); - - if let Some(global_cfg) = &ctx.configs().lock().global_config { - nu_dict.insert_value( - "config", - UntaggedValue::row(global_cfg.vars.clone()).into_value(&tag), - ); - - nu_dict.insert_value( - "config-path", - UntaggedValue::filepath(global_cfg.file_path.clone()).into_value(&tag), - ); - - // overwrite hist-path if present - if let Some(hist_path) = history_path(global_cfg) { - nu_dict.insert_value( - "history-path", - UntaggedValue::filepath(hist_path).into_value(&tag), - ); - } - } - - // A note about environment variables: - // - // Environment variables in Unix platforms are case-sensitive. On Windows, case-sensitivity is context-dependent. - // In cmd.exe, running `SET` will show you the list of environment variables and their names will be mixed case. - // In PowerShell, running `Get-ChildItem Env:` will show you a list of environment variables, and they will match - // the case in the environment variable section of the user configuration - // - // Rust currently returns the DOS-style, all-uppercase environment variables on Windows (as of 1.52) when running - // std::env::vars(), rather than the case-sensitive Environment.GetEnvironmentVariables() of .NET that PowerShell - // uses. - // - // For now, we work around the discrepancy as best we can by merging the two into what is shown to the user as the - // 'path' column of `$nu` - let mut table = vec![]; - for v in env { - if v.0 == "PATH" || v.0 == "Path" { - for path in std::env::split_paths(&v.1) { - table.push(UntaggedValue::filepath(path).into_value(&tag)); - } - } - } - nu_dict.insert_value("path", UntaggedValue::table(&table).into_value(&tag)); - - let path = std::env::current_dir()?; - nu_dict.insert_value("cwd", UntaggedValue::filepath(path).into_value(&tag)); - - if let Some(home) = crate::filesystem::filesystem_shell::homedir_if_possible() { - nu_dict.insert_value("home-dir", UntaggedValue::filepath(home).into_value(&tag)); - } - - let temp = std::env::temp_dir(); - nu_dict.insert_value("temp-dir", UntaggedValue::filepath(temp).into_value(&tag)); - - #[cfg(feature = "rustyline-support")] - { - let keybinding_path = nu_data::keybinding::keybinding_path()?; - nu_dict.insert_value( - "keybinding-path", - UntaggedValue::filepath(keybinding_path).into_value(&tag), - ); - } - - let cmd_info = lang::Lang::query_commands(scope); - match cmd_info { - Ok(cmds) => nu_dict.insert_value("lang", UntaggedValue::table(&cmds).into_value(&tag)), - Err(_) => nu_dict.insert_value("lang", UntaggedValue::string("no commands found")), - } - - Ok(nu_dict.into_value()) -} - -pub fn scope( - aliases: &IndexMap>>, - commands: &IndexMap, - variables: &IndexMap, -) -> Result { - let tag = Tag::unknown(); - - let mut scope_dict = TaggedDictBuilder::new(&tag); - - let mut aliases_dict = TaggedDictBuilder::new(&tag); - for v in aliases { - let values = v.1.clone(); - let mut vec = Vec::new(); - - for k in &values { - vec.push(k.to_string()); - } - - let alias = vec.join(" "); - - aliases_dict.insert_untagged(v.0, UntaggedValue::string(alias)); - } - - let mut commands_dict = TaggedDictBuilder::new(&tag); - for (name, signature) in commands { - commands_dict.insert_untagged(name, UntaggedValue::string(&signature.allowed().join(" "))) - } - - let var_list: Vec = variables - .iter() - .map(|var| { - let mut entries: IndexMap = IndexMap::new(); - let name = var.0.trim_start_matches('$'); - entries.insert( - "name".to_string(), - UntaggedValue::string(name).into_value(&tag), - ); - entries.insert( - "value".to_string(), - UntaggedValue::string(var.1.convert_to_string()).into_value(&tag), - ); - entries.insert( - "type".to_string(), - UntaggedValue::string(ShellTypeName::type_name(&var.1)).into_value(&tag), - ); - UntaggedValue::Row(Dictionary { entries }).into_value(&tag) - }) - .collect(); - - scope_dict.insert_value("aliases", aliases_dict.into_value()); - - scope_dict.insert_value("commands", commands_dict.into_value()); - - scope_dict.insert_value("variables", UntaggedValue::Table(var_list).into_value(&tag)); - - Ok(scope_dict.into_value()) -} diff --git a/old_nushell/crates/nu-engine/src/evaluation_context.rs b/old_nushell/crates/nu-engine/src/evaluation_context.rs deleted file mode 100644 index cab85f129..000000000 --- a/old_nushell/crates/nu-engine/src/evaluation_context.rs +++ /dev/null @@ -1,440 +0,0 @@ -use crate::evaluate::envvar::EnvVar; -use crate::evaluate::evaluator::Variable; -use crate::evaluate::scope::{Scope, ScopeFrame}; -use crate::shell::palette::ThemedPalette; -use crate::shell::shell_manager::ShellManager; -use crate::whole_stream_command::Command; -use crate::{call_info::UnevaluatedCallInfo, config_holder::ConfigHolder}; -use crate::{command_args::CommandArgs, script}; -use crate::{env::basic_host::BasicHost, Host}; - -use nu_data::config::{self, Conf, NuConfig}; -use nu_errors::ShellError; -use nu_path::expand_path; -use nu_protocol::{hir, ConfigPath, VariableRegistry}; -use nu_source::Spanned; -use nu_source::{Span, Tag}; -use nu_stream::InputStream; -use nu_test_support::NATIVE_PATH_ENV_VAR; - -use indexmap::IndexMap; -use log::trace; -use parking_lot::Mutex; -use std::fs::File; -use std::io::BufReader; -use std::sync::atomic::AtomicBool; -use std::{path::Path, sync::Arc}; - -#[derive(Clone, Default)] -pub struct EngineState { - pub host: Arc>>, - pub current_errors: Arc>>, - pub ctrl_c: Arc, - pub configs: Arc>, - pub shell_manager: ShellManager, - - /// Windows-specific: keep track of previous cwd on each drive - pub windows_drives_previous_cwd: Arc>>, -} -#[derive(Clone, Default)] -pub struct EvaluationContext { - pub scope: Scope, - pub engine_state: Arc, -} - -impl EvaluationContext { - pub fn new( - scope: Scope, - host: Arc>>, - current_errors: Arc>>, - ctrl_c: Arc, - configs: Arc>, - shell_manager: ShellManager, - windows_drives_previous_cwd: Arc>>, - ) -> Self { - Self { - scope, - engine_state: Arc::new(EngineState { - host, - current_errors, - ctrl_c, - configs, - shell_manager, - windows_drives_previous_cwd, - }), - } - } - - pub fn basic() -> EvaluationContext { - let scope = Scope::new(); - let host = BasicHost {}; - let env_vars: IndexMap = host - .vars() - .iter() - .cloned() - .map(|(k, v)| (k, v.into())) - .collect(); - scope.add_env(env_vars); - - EvaluationContext { - scope, - engine_state: Arc::new(EngineState { - host: Arc::new(parking_lot::Mutex::new(Box::new(host))), - current_errors: Arc::new(Mutex::new(vec![])), - ctrl_c: Arc::new(AtomicBool::new(false)), - configs: Arc::new(Mutex::new(ConfigHolder::new())), - shell_manager: ShellManager::basic(), - windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())), - }), - } - } - - pub fn error(&self, error: ShellError) { - self.with_errors(|errors| errors.push(error)) - } - - pub fn host(&self) -> &Arc>> { - &self.engine_state.host - } - - pub fn current_errors(&self) -> &Arc>> { - &self.engine_state.current_errors - } - - pub fn ctrl_c(&self) -> &Arc { - &self.engine_state.ctrl_c - } - - pub fn configs(&self) -> &Arc> { - &self.engine_state.configs - } - - pub fn shell_manager(&self) -> &ShellManager { - &self.engine_state.shell_manager - } - - pub fn windows_drives_previous_cwd( - &self, - ) -> &Arc>> { - &self.engine_state.windows_drives_previous_cwd - } - - pub fn clear_errors(&self) { - self.engine_state.current_errors.lock().clear() - } - - pub fn get_errors(&self) -> Vec { - self.engine_state.current_errors.lock().clone() - } - - pub fn configure( - &mut self, - config: &dyn nu_data::config::Conf, - block: impl FnOnce(&dyn nu_data::config::Conf, &mut Self) -> T, - ) { - block(config, &mut *self); - } - - pub fn with_host(&self, block: impl FnOnce(&mut dyn Host) -> T) -> T { - let mut host = self.engine_state.host.lock(); - - block(&mut *host) - } - - pub fn with_errors(&self, block: impl FnOnce(&mut Vec) -> T) -> T { - let mut errors = self.engine_state.current_errors.lock(); - - block(&mut *errors) - } - - pub fn add_commands(&self, commands: Vec) { - for command in commands { - self.scope.add_command(command.name().to_string(), command); - } - } - - pub fn sync_path_to_env(&self) { - let env_vars = self.scope.get_env_vars(); - - for (var, val) in env_vars { - if var == NATIVE_PATH_ENV_VAR { - std::env::set_var(var, expand_path(val)); - break; - } - } - } - - pub fn get_command(&self, name: &str) -> Option { - self.scope.get_command(name) - } - - pub fn is_command_registered(&self, name: &str) -> bool { - self.scope.has_command(name) - } - - pub fn run_command( - &self, - command: Command, - name_tag: Tag, - args: hir::Call, - input: InputStream, - ) -> Result { - let command_args = self.command_args(args, input, name_tag); - command.run(command_args) - } - - fn call_info(&self, args: hir::Call, name_tag: Tag) -> UnevaluatedCallInfo { - UnevaluatedCallInfo { args, name_tag } - } - - fn command_args(&self, args: hir::Call, input: InputStream, name_tag: Tag) -> CommandArgs { - CommandArgs { - context: self.clone(), - call_info: self.call_info(args, name_tag), - input, - } - } - - /// Loads config under cfg_path. - /// If an error occurs while loading the config: - /// The config is not loaded - /// The error is returned - /// After successful loading of the config the startup scripts are run - /// as normal scripts (Errors are printed out, ...) - /// After executing the startup scripts, true is returned to indicate successful loading - /// of the config - // - // The rational here is that, we should not partially load any config - // that might be damaged. However, startup scripts might fail for various reasons. - // A failure there is not as crucial as wrong config files. - pub fn load_config(&self, cfg_path: &ConfigPath) -> Result<(), ShellError> { - trace!("Loading cfg {:?}", cfg_path); - - let cfg = NuConfig::load(Some(cfg_path.get_path().clone()))?; - let exit_scripts = cfg.exit_scripts()?; - let startup_scripts = cfg.startup_scripts()?; - let cfg_paths = cfg.path()?; - - let joined_paths = cfg_paths - .map(|mut cfg_paths| { - //existing paths are prepended to path - let env_paths = self.scope.get_env(NATIVE_PATH_ENV_VAR); - - if let Some(env_paths) = env_paths { - let mut env_paths = std::env::split_paths(&env_paths).collect::>(); - //No duplicates! Remove env_paths already existing in cfg_paths - env_paths.retain(|env_path| !cfg_paths.contains(env_path)); - //env_paths entries are appended at the end - //nu config paths have a higher priority - cfg_paths.extend(env_paths); - } - cfg_paths - }) - .map(|paths| { - std::env::join_paths(paths) - .map(|s| s.to_string_lossy().to_string()) - .map_err(|e| { - ShellError::labeled_error( - &format!("Error while joining paths from config: {:?}", e), - "Config path error", - Span::unknown(), - ) - }) - }) - .transpose()?; - - let tag = config::cfg_path_to_scope_tag(cfg_path.get_path()); - - self.scope.enter_scope_with_tag(tag); - let config_env = cfg.env_map(); - let env_vars = config_env - .into_iter() - .map(|(k, v)| (k, EnvVar::from(v))) - .collect(); - self.scope.add_env(env_vars); - if let Some(path) = joined_paths { - self.scope.add_env_var(NATIVE_PATH_ENV_VAR, path); - } - self.scope.set_exit_scripts(exit_scripts); - - match cfg_path { - ConfigPath::Global(_) => self.engine_state.configs.lock().set_global_cfg(cfg), - ConfigPath::Local(_) => { - self.engine_state.configs.lock().add_local_cfg(cfg); - } - } - - // The syntax_theme is really the file stem of a json file i.e. - // grape.json is the theme file and grape is the file stem and - // the syntax_theme and grape.json would be located in the same - // folder as the config.toml - - // Let's open the config - let global_config = self.engine_state.configs.lock().global_config(); - // Get the root syntax_theme value - let syntax_theme = global_config.var("syntax_theme"); - // If we have a syntax_theme let's process it - if let Some(theme_value) = syntax_theme { - // Append the .json to the syntax_theme to form the file name - let syntax_theme_filename = format!("{}.json", theme_value.convert_to_string()); - // Load the syntax config json - let config_file_path = cfg_path.get_path(); - // The syntax file should be in the same location as the config.toml - let syntax_file_path = if config_file_path.ends_with("config.toml") { - config_file_path - .display() - .to_string() - .replace("config.toml", &syntax_theme_filename) - } else { - "".to_string() - }; - // if we have a syntax_file_path use it otherwise default - if Path::new(&syntax_file_path).exists() { - // eprintln!("Loading syntax file: [{:?}]", syntax_file_path); - let syntax_theme_file = File::open(syntax_file_path)?; - let mut reader = BufReader::new(syntax_theme_file); - let theme = ThemedPalette::new(&mut reader).unwrap_or_default(); - // eprintln!("Theme: [{:?}]", theme); - self.engine_state.configs.lock().set_syntax_colors(theme); - } else { - // If the file was missing, use the default - self.engine_state - .configs - .lock() - .set_syntax_colors(ThemedPalette::default()) - } - } else { - // if there's no syntax_theme, use the default - self.engine_state - .configs - .lock() - .set_syntax_colors(ThemedPalette::default()) - }; - - if !startup_scripts.is_empty() { - self.run_scripts(startup_scripts, cfg_path.get_path().parent()); - } - - Ok(()) - } - - /// Reloads config with a path of cfg_path. - /// If an error occurs while reloading the config: - /// The config is not reloaded - /// The error is returned - pub fn reload_config(&self, cfg: &mut NuConfig) -> Result<(), ShellError> { - trace!("Reloading cfg {:?}", cfg.file_path); - - cfg.reload(); - - let exit_scripts = cfg.exit_scripts()?; - let cfg_paths = cfg.path()?; - - let joined_paths = cfg_paths - .map(|mut cfg_paths| { - //existing paths are prepended to path - let env_paths = self.scope.get_env(NATIVE_PATH_ENV_VAR); - - if let Some(env_paths) = env_paths { - let mut env_paths = std::env::split_paths(&env_paths).collect::>(); - //No duplicates! Remove env_paths already existing in cfg_paths - env_paths.retain(|env_path| !cfg_paths.contains(env_path)); - //env_paths entries are appended at the end - //nu config paths have a higher priority - cfg_paths.extend(env_paths); - } - cfg_paths - }) - .map(|paths| { - std::env::join_paths(paths) - .map(|s| s.to_string_lossy().to_string()) - .map_err(|e| { - ShellError::labeled_error( - &format!("Error while joining paths from config: {:?}", e), - "Config path error", - Span::unknown(), - ) - }) - }) - .transpose()?; - - let tag = config::cfg_path_to_scope_tag(&cfg.file_path); - let mut frame = ScopeFrame::with_tag(tag.clone()); - let config_env = cfg.env_map(); - let env_vars = config_env - .into_iter() - .map(|(k, v)| (k, EnvVar::from(v))) - .collect(); - frame.env = env_vars; - if let Some(path) = joined_paths { - frame - .env - .insert(NATIVE_PATH_ENV_VAR.to_string(), path.into()); - } - frame.exitscripts = exit_scripts; - - self.scope.update_frame_with_tag(frame, &tag)?; - - Ok(()) - } - - /// Runs all exit_scripts before unloading the config with path of cfg_path - /// If an error occurs while running exit scripts: - /// The error is added to `self.current_errors` - /// If no config with path of `cfg_path` is present, this method does nothing - pub fn unload_config(&self, cfg_path: &ConfigPath) { - trace!("UnLoading cfg {:?}", cfg_path); - - let tag = config::cfg_path_to_scope_tag(cfg_path.get_path()); - - //Run exitscripts with scope frame and cfg still applied - if let Some(scripts) = self.scope.get_exitscripts_of_frame_with_tag(&tag) { - self.run_scripts(scripts, cfg_path.get_path().parent()); - } - - //Unload config - self.engine_state.configs.lock().remove_cfg(cfg_path); - self.scope.exit_scope_with_tag(&tag); - } - - /// Runs scripts with cwd of dir. If dir is None, this method does nothing. - /// Each error is added to `self.current_errors` - pub fn run_scripts(&self, scripts: Vec, dir: Option<&Path>) { - if let Some(dir) = dir { - for script in scripts { - match script::run_script_in_dir(script.clone(), dir, self) { - Ok(_) => {} - Err(e) => { - let err = ShellError::untagged_runtime_error(format!( - "Err while executing exitscript. Err was\n{:?}", - e - )); - let text = script.into(); - self.engine_state.host.lock().print_err(err, &text); - } - } - } - } - } -} - -use itertools::Itertools; - -impl VariableRegistry for EvaluationContext { - fn get_variable(&self, name: &Spanned<&str>) -> Option { - let span = name.span; - let name = nu_protocol::hir::Expression::variable(name.item.to_string(), name.span); - - let var = Variable::from(&name); - - crate::evaluate::evaluator::evaluate_reference(&var, self, span).ok() - } - - fn variables(&self) -> Vec { - Variable::list() - .into_iter() - .chain(self.scope.get_variable_names()) - .unique() - .collect() - } -} diff --git a/old_nushell/crates/nu-engine/src/example.rs b/old_nushell/crates/nu-engine/src/example.rs deleted file mode 100644 index 41a93ea5a..000000000 --- a/old_nushell/crates/nu-engine/src/example.rs +++ /dev/null @@ -1,7 +0,0 @@ -use nu_protocol::Value; - -pub struct Example { - pub example: &'static str, - pub description: &'static str, - pub result: Option>, -} diff --git a/old_nushell/crates/nu-engine/src/filesystem/dir_info.rs b/old_nushell/crates/nu-engine/src/filesystem/dir_info.rs deleted file mode 100644 index da661b88f..000000000 --- a/old_nushell/crates/nu-engine/src/filesystem/dir_info.rs +++ /dev/null @@ -1,275 +0,0 @@ -use filesize::file_real_size_fast; -use glob::Pattern; -use indexmap::IndexMap; -use nu_errors::ShellError; -use nu_protocol::{UntaggedValue, Value}; -use nu_source::Tag; -use std::path::PathBuf; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; - -pub struct DirBuilder { - pub tag: Tag, - pub min: Option, - pub deref: bool, - pub exclude: Option, - pub all: bool, -} - -impl DirBuilder { - pub fn new( - tag: Tag, - min: Option, - deref: bool, - exclude: Option, - all: bool, - ) -> DirBuilder { - DirBuilder { - tag, - min, - deref, - exclude, - all, - } - } -} - -pub struct DirInfo { - dirs: Vec, - files: Vec, - errors: Vec, - size: u64, - blocks: u64, - path: PathBuf, - tag: Tag, -} - -pub struct FileInfo { - path: PathBuf, - size: u64, - blocks: Option, - tag: Tag, -} - -impl FileInfo { - pub fn new(path: impl Into, deref: bool, tag: Tag) -> Result { - let path = path.into(); - let m = if deref { - std::fs::metadata(&path) - } else { - std::fs::symlink_metadata(&path) - }; - - match m { - Ok(d) => { - let block_size = file_real_size_fast(&path, &d).ok(); - - Ok(FileInfo { - path, - blocks: block_size, - size: d.len(), - tag, - }) - } - Err(e) => Err(e.into()), - } - } -} - -impl DirInfo { - pub fn new( - path: impl Into, - params: &DirBuilder, - depth: Option, - ctrl_c: Arc, - ) -> Self { - let path = path.into(); - - let mut s = Self { - dirs: Vec::new(), - errors: Vec::new(), - files: Vec::new(), - size: 0, - blocks: 0, - tag: params.tag.clone(), - path, - }; - - match std::fs::metadata(&s.path) { - Ok(d) => { - s.size = d.len(); // dir entry size - s.blocks = file_real_size_fast(&s.path, &d).ok().unwrap_or(0); - } - Err(e) => s = s.add_error(e.into()), - }; - - match std::fs::read_dir(&s.path) { - Ok(d) => { - for f in d { - if ctrl_c.load(Ordering::SeqCst) { - break; - } - - match f { - Ok(i) => match i.file_type() { - Ok(t) if t.is_dir() => { - s = s.add_dir(i.path(), depth, params, ctrl_c.clone()) - } - Ok(_t) => s = s.add_file(i.path(), params), - Err(e) => s = s.add_error(e.into()), - }, - Err(e) => s = s.add_error(e.into()), - } - } - } - Err(e) => s = s.add_error(e.into()), - } - s - } - - fn add_dir( - mut self, - path: impl Into, - mut depth: Option, - params: &DirBuilder, - ctrl_c: Arc, - ) -> Self { - if let Some(current) = depth { - if let Some(new) = current.checked_sub(1) { - depth = Some(new); - } else { - return self; - } - } - - let d = DirInfo::new(path, params, depth, ctrl_c); - self.size += d.size; - self.blocks += d.blocks; - self.dirs.push(d); - self - } - - fn add_file(mut self, f: impl Into, params: &DirBuilder) -> Self { - let f = f.into(); - let include = params - .exclude - .as_ref() - .map_or(true, |x| !x.matches_path(&f)); - if include { - match FileInfo::new(f, params.deref, self.tag.clone()) { - Ok(file) => { - let inc = params.min.map_or(true, |s| file.size >= s); - if inc { - self.size += file.size; - self.blocks += file.blocks.unwrap_or(0); - if params.all { - self.files.push(file); - } - } - } - Err(e) => self = self.add_error(e), - } - } - self - } - - fn add_error(mut self, e: ShellError) -> Self { - self.errors.push(e); - self - } - - pub fn get_size(&self) -> u64 { - self.size - } -} - -impl From for Value { - fn from(d: DirInfo) -> Self { - let mut r: IndexMap = IndexMap::new(); - - r.insert( - "path".to_string(), - UntaggedValue::filepath(d.path).into_value(&d.tag), - ); - - r.insert( - "apparent".to_string(), - UntaggedValue::filesize(d.size).into_value(&d.tag), - ); - - r.insert( - "physical".to_string(), - UntaggedValue::filesize(d.blocks).into_value(&d.tag), - ); - - r.insert("directories".to_string(), value_from_vec(d.dirs, &d.tag)); - - r.insert("files".to_string(), value_from_vec(d.files, &d.tag)); - - if !d.errors.is_empty() { - let v = UntaggedValue::Table( - d.errors - .into_iter() - .map(move |e| UntaggedValue::Error(e).into_untagged_value()) - .collect::>(), - ) - .into_value(&d.tag); - - r.insert("errors".to_string(), v); - } - - Value { - value: UntaggedValue::row(r), - tag: d.tag, - } - } -} - -impl From for Value { - fn from(f: FileInfo) -> Self { - let mut r: IndexMap = IndexMap::new(); - - r.insert( - "path".to_string(), - UntaggedValue::filepath(f.path).into_value(&f.tag), - ); - - r.insert( - "apparent".to_string(), - UntaggedValue::filesize(f.size).into_value(&f.tag), - ); - - let b = f - .blocks - .map(UntaggedValue::filesize) - .unwrap_or_else(UntaggedValue::nothing) - .into_value(&f.tag); - - r.insert("physical".to_string(), b); - - r.insert( - "directories".to_string(), - UntaggedValue::nothing().into_value(&f.tag), - ); - - r.insert( - "files".to_string(), - UntaggedValue::nothing().into_value(&f.tag), - ); - - UntaggedValue::row(r).into_value(&f.tag) - } -} - -fn value_from_vec(vec: Vec, tag: &Tag) -> Value -where - V: Into, -{ - if vec.is_empty() { - UntaggedValue::nothing() - } else { - let values = vec.into_iter().map(Into::into).collect::>(); - UntaggedValue::Table(values) - } - .into_value(tag) -} diff --git a/old_nushell/crates/nu-engine/src/filesystem/filesystem_shell.rs b/old_nushell/crates/nu-engine/src/filesystem/filesystem_shell.rs deleted file mode 100644 index f221553ae..000000000 --- a/old_nushell/crates/nu-engine/src/filesystem/filesystem_shell.rs +++ /dev/null @@ -1,1234 +0,0 @@ -use crate::filesystem::utils::FileStructure; -use crate::maybe_text_codec::{MaybeTextCodec, StringOrBinary}; -use crate::shell::shell_args::{CdArgs, CopyArgs, LsArgs, MkdirArgs, MvArgs, RemoveArgs}; -use crate::shell::Shell; -use crate::BufCodecReader; -use crate::{ - filesystem::dir_info::{DirBuilder, DirInfo}, - CommandArgs, -}; -use encoding_rs::Encoding; -use nu_data::config::LocalConfigDiff; -use nu_path::{canonicalize, canonicalize_with, expand_path_with}; -use nu_protocol::{CommandAction, ConfigPath, TaggedDictBuilder, Value}; -use nu_source::{Span, Tag}; -use nu_stream::{ActionStream, Interruptible, IntoActionStream, OutputStream}; -use std::collections::VecDeque; -use std::fs::OpenOptions; -use std::io::{ErrorKind, Write}; -use std::path::{Path, PathBuf}; -use std::sync::atomic::AtomicBool; -use std::sync::Arc; -use std::{collections::HashMap, io::BufReader}; - -#[cfg(unix)] -use std::os::unix::fs::PermissionsExt; - -use nu_errors::ShellError; -use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue}; -use nu_source::Tagged; - -const GLOB_PARAMS: glob::MatchOptions = glob::MatchOptions { - case_sensitive: true, - require_literal_separator: false, - require_literal_leading_dot: false, -}; - -#[derive(Eq, PartialEq, Clone, Copy)] -pub enum FilesystemShellMode { - Cli, - Script, -} - -pub struct FilesystemShell { - pub(crate) path: String, - pub(crate) last_path: String, - pub(crate) mode: FilesystemShellMode, -} - -impl std::fmt::Debug for FilesystemShell { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "FilesystemShell @ {}", self.path) - } -} - -impl Clone for FilesystemShell { - fn clone(&self) -> Self { - FilesystemShell { - path: self.path.clone(), - last_path: self.path.clone(), - mode: self.mode, - } - } -} - -impl FilesystemShell { - fn is_cli(&self) -> bool { - matches!(&self.mode, FilesystemShellMode::Cli) - } - - pub fn basic(mode: FilesystemShellMode) -> FilesystemShell { - let path = match std::env::current_dir() { - Ok(path) => path, - Err(_) => PathBuf::from("/"), - }; - - FilesystemShell { - path: path.to_string_lossy().to_string(), - last_path: path.to_string_lossy().to_string(), - mode, - } - } - - pub fn with_location( - path: String, - mode: FilesystemShellMode, - ) -> Result { - let path = canonicalize_with(&path, std::env::current_dir()?)?; - let path = path.display().to_string(); - let last_path = path.clone(); - - Ok(FilesystemShell { - path, - last_path, - mode, - }) - } -} - -pub fn homedir_if_possible() -> Option { - dirs_next::home_dir() -} - -impl Shell for FilesystemShell { - fn name(&self) -> String { - "filesystem".to_string() - } - - fn homedir(&self) -> Option { - homedir_if_possible() - } - - fn ls( - &self, - LsArgs { - path, - all, - long, - short_names, - du, - }: LsArgs, - name_tag: Tag, - ctrl_c: Arc, - ) -> Result { - let ctrl_c_copy = ctrl_c.clone(); - let (path, p_tag) = match path { - Some(p) => { - let p_tag = p.tag; - let mut p = p.item; - if p.is_dir() { - if permission_denied(&p) { - #[cfg(unix)] - let error_msg = format!( - "The permissions of {:o} do not allow access for this user", - p.metadata() - .expect( - "this shouldn't be called since we already know there is a dir" - ) - .permissions() - .mode() - & 0o0777 - ); - #[cfg(not(unix))] - let error_msg = String::from("Permission denied"); - return Err(ShellError::labeled_error( - "Permission denied", - error_msg, - &p_tag, - )); - } - if is_empty_dir(&p) { - return Ok(ActionStream::empty()); - } - p.push("*"); - } - (p, p_tag) - } - None => { - if is_empty_dir(&self.path()) { - return Ok(ActionStream::empty()); - } else { - (PathBuf::from("./*"), name_tag.clone()) - } - } - }; - - let hidden_dir_specified = is_hidden_dir(&path); - - let mut paths = glob::glob_with(&path.to_string_lossy(), GLOB_PARAMS) - .map_err(|e| ShellError::labeled_error(e.to_string(), "invalid pattern", &p_tag))? - .peekable(); - - if paths.peek().is_none() { - return Err(ShellError::labeled_error( - "No matches found", - "no matches found", - &p_tag, - )); - } - - let mut hidden_dirs = vec![]; - - // Generated stream: impl Stream - - Ok(paths - .filter_map(move |path| { - let path = match path.map_err(|e| ShellError::from(e.into_error())) { - Ok(path) => path, - Err(err) => return Some(Err(err)), - }; - - if path_contains_hidden_folder(&path, &hidden_dirs) { - return None; - } - - if !all && !hidden_dir_specified && is_hidden_dir(&path) { - if path.is_dir() { - hidden_dirs.push(path); - } - return None; - } - - let metadata = match std::fs::symlink_metadata(&path) { - Ok(metadata) => Some(metadata), - Err(e) => { - if e.kind() == ErrorKind::PermissionDenied || e.kind() == ErrorKind::Other { - None - } else { - return Some(Err(e.into())); - } - } - }; - - let entry = dir_entry_dict( - &path, - metadata.as_ref(), - name_tag.clone(), - long, - short_names, - du, - ctrl_c.clone(), - ) - .map(ReturnSuccess::Value); - - Some(entry) - }) - .interruptible(ctrl_c_copy) - .into_action_stream()) - } - - fn cd(&self, args: CdArgs, name: Tag) -> Result { - let path = match args.path { - None => match homedir_if_possible() { - Some(o) => o, - _ => { - return Err(ShellError::labeled_error( - "Cannot change to home directory", - "cannot go to home", - &name, - )) - } - }, - Some(v) => { - let Tagged { item: target, tag } = v; - if target == Path::new("-") { - PathBuf::from(&self.last_path) - } else { - // Extra expand attempt allows cd from /home/user/non-existent-dir/.. - // to /home/user - let path = match canonicalize_with(&target, self.path()) { - Ok(p) => p, - _ => expand_path_with(&target, self.path()), - }; - - if !path.exists() { - return Err(ShellError::labeled_error( - "Cannot change to directory", - "directory not found", - &tag, - )); - } - - if !path.is_dir() { - return Err(ShellError::labeled_error( - "Cannot change to directory", - "is not a directory", - &tag, - )); - } - - #[cfg(unix)] - { - let has_exec = path - .metadata() - .map(|m| { - umask::Mode::from(m.permissions().mode()).has(umask::USER_READ) - }) - .map_err(|e| { - ShellError::labeled_error( - "Cannot change to directory", - format!("cannot stat ({})", e), - &tag, - ) - })?; - - if !has_exec { - return Err(ShellError::labeled_error( - "Cannot change to directory", - "permission denied", - &tag, - )); - } - } - - path - } - } - }; - - let mut stream = VecDeque::new(); - - stream.push_back(ReturnSuccess::change_cwd( - path.to_string_lossy().to_string(), - )); - - //Loading local configs in script mode, makes scripts behave different on different - //filesystems and might therefore surprise users. That's why we only load them in cli mode. - if self.is_cli() { - match canonicalize(self.path()) { - Err(e) => { - let err = ShellError::untagged_runtime_error(format!( - "Could not get absolute path from current fs shell. The error was: {:?}", - e - )); - stream.push_back(ReturnSuccess::value( - UntaggedValue::Error(err).into_value(Tag::unknown()), - )); - } - Ok(current_pwd) => { - let (changes, errs) = LocalConfigDiff::between(current_pwd, path); - - for err in errs { - stream.push_back(ReturnSuccess::value( - UntaggedValue::Error(err).into_value(Tag::unknown()), - )); - } - - for unload_cfg in changes.cfgs_to_unload { - stream.push_back(ReturnSuccess::action(CommandAction::UnloadConfig( - ConfigPath::Local(unload_cfg), - ))); - } - - for load_cfg in changes.cfgs_to_load { - stream.push_back(ReturnSuccess::action(CommandAction::LoadConfig( - ConfigPath::Local(load_cfg), - ))); - } - } - }; - } - - Ok(stream.into()) - } - - fn cp( - &self, - CopyArgs { - src, - dst, - recursive, - }: CopyArgs, - name: Tag, - path: &str, - ) -> Result { - let name_tag = name; - - let path = Path::new(path); - let source = path.join(&src.item); - let destination = path.join(&dst.item); - - let sources: Vec<_> = match glob::glob_with(&source.to_string_lossy(), GLOB_PARAMS) { - Ok(files) => files.collect(), - Err(e) => { - return Err(ShellError::labeled_error( - e.to_string(), - "invalid pattern", - src.tag, - )) - } - }; - - if sources.is_empty() { - return Err(ShellError::labeled_error( - "No matches found", - "no matches found", - src.tag, - )); - } - - if sources.len() > 1 && !destination.is_dir() { - return Err(ShellError::labeled_error( - "Destination must be a directory when copying multiple files", - "is not a directory", - dst.tag, - )); - } - - let any_source_is_dir = sources.iter().any(|f| matches!(f, Ok(f) if f.is_dir())); - - if any_source_is_dir && !recursive { - return Err(ShellError::labeled_error( - "Directories must be copied using \"--recursive\"", - "resolves to a directory (not copied)", - src.tag, - )); - } - - for entry in sources.into_iter().flatten() { - let mut sources = FileStructure::new(); - sources.walk_decorate(&entry)?; - - if entry.is_file() { - let sources = sources.paths_applying_with(|(source_file, _depth_level)| { - if destination.is_dir() { - let mut dest = canonicalize_with(&dst.item, &path)?; - if let Some(name) = entry.file_name() { - dest.push(name); - } - Ok((source_file, dest)) - } else { - Ok((source_file, destination.clone())) - } - })?; - - for (src, dst) in sources { - if src.is_file() { - std::fs::copy(src, dst).map_err(|e| { - ShellError::labeled_error(e.to_string(), e.to_string(), &name_tag) - })?; - } - } - } else if entry.is_dir() { - let destination = if !destination.exists() { - destination.clone() - } else { - match entry.file_name() { - Some(name) => destination.join(name), - None => { - return Err(ShellError::labeled_error( - "Copy aborted. Not a valid path", - "not a valid path", - dst.tag, - )) - } - } - }; - - std::fs::create_dir_all(&destination).map_err(|e| { - ShellError::labeled_error(e.to_string(), e.to_string(), &dst.tag) - })?; - - let sources = sources.paths_applying_with(|(source_file, depth_level)| { - let mut dest = destination.clone(); - let path = canonicalize_with(&source_file, &path)?; - - let comps: Vec<_> = path - .components() - .map(|fragment| fragment.as_os_str()) - .rev() - .take(1 + depth_level) - .collect(); - - for fragment in comps.into_iter().rev() { - dest.push(fragment); - } - - Ok((PathBuf::from(&source_file), dest)) - })?; - - let dst_tag = &dst.tag; - for (src, dst) in sources { - if src.is_dir() && !dst.exists() { - std::fs::create_dir_all(&dst).map_err(|e| { - ShellError::labeled_error(e.to_string(), e.to_string(), dst_tag) - })?; - } - - if src.is_file() { - std::fs::copy(&src, &dst).map_err(|e| { - ShellError::labeled_error(e.to_string(), e.to_string(), &name_tag) - })?; - } - } - } - } - - Ok(ActionStream::empty()) - } - - fn mkdir( - &self, - MkdirArgs { - rest: directories, - show_created_paths, - }: MkdirArgs, - name: Tag, - path: &str, - ) -> Result { - let path = Path::new(path); - let mut stream = VecDeque::new(); - - if directories.is_empty() { - return Err(ShellError::labeled_error( - "mkdir requires directory paths", - "needs parameter", - name, - )); - } - - for dir in &directories { - let create_at = path.join(&dir.item); - - let dir_res = std::fs::create_dir_all(&create_at); - if let Err(reason) = dir_res { - return Err(ShellError::labeled_error( - reason.to_string(), - reason.to_string(), - dir.tag(), - )); - } - if show_created_paths { - let val = format!("{:}", create_at.to_string_lossy()).into(); - stream.push_back(val); - } - } - - Ok(stream.into()) - } - - fn mv( - &self, - MvArgs { src, dst }: MvArgs, - _name: Tag, - path: &str, - ) -> Result { - let path = Path::new(path); - let source = path.join(&src.item); - let destination = path.join(&dst.item); - - let mut sources = glob::glob_with(&source.to_string_lossy(), GLOB_PARAMS) - .map_or_else(|_| Vec::new(), Iterator::collect); - - if sources.is_empty() { - return Err(ShellError::labeled_error( - "Invalid file or pattern", - "invalid file or pattern", - src.tag, - )); - } - - // We have two possibilities. - // - // First, the destination exists. - // - If a directory, move everything into that directory, otherwise - // - if only a single source, overwrite the file, otherwise - // - error. - // - // Second, the destination doesn't exist, so we can only rename a single source. Otherwise - // it's an error. - - if (destination.exists() && !destination.is_dir() && sources.len() > 1) - || (!destination.exists() && sources.len() > 1) - { - return Err(ShellError::labeled_error( - "Can only move multiple sources if destination is a directory", - "destination must be a directory when multiple sources", - dst.tag, - )); - } - - let some_if_source_is_destination = sources - .iter() - .find(|f| matches!(f, Ok(f) if destination.starts_with(f))); - if destination.exists() && destination.is_dir() && sources.len() == 1 { - if let Some(Ok(filename)) = some_if_source_is_destination { - return Err(ShellError::labeled_error( - format!( - "Not possible to move {:?} to itself", - filename.file_name().expect("Invalid file name") - ), - "cannot move to itself", - dst.tag, - )); - } - } - - if let Some(Ok(_filename)) = some_if_source_is_destination { - sources = sources - .into_iter() - .filter(|f| matches!(f, Ok(f) if !destination.starts_with(f))) - .collect(); - } - - for entry in sources.into_iter().flatten() { - move_file( - TaggedPathBuf(&entry, &src.tag), - TaggedPathBuf(&destination, &dst.tag), - )? - } - - Ok(ActionStream::empty()) - } - - fn rm( - &self, - RemoveArgs { - rest: targets, - recursive, - trash: _trash, - permanent: _permanent, - force: _force, - }: RemoveArgs, - name: Tag, - path: &str, - ) -> Result { - let rm_always_trash = nu_data::config::config(Tag::unknown())? - .get("rm_always_trash") - .map(|val| val.is_true()) - .unwrap_or(false); - - #[cfg(not(feature = "trash-support"))] - { - if rm_always_trash { - return Err(ShellError::untagged_runtime_error( - "Cannot execute `rm`; the current configuration specifies \ - `rm_always_trash = true`, but the current nu executable was not \ - built with feature `trash_support`.", - )); - } else if _trash { - return Err(ShellError::labeled_error( - "Cannot execute `rm` with option `--trash`; feature `trash-support` not enabled", - "this option is only available if nu is built with the `trash-support` feature", - name - )); - } - } - - let name_tag = name; - - if targets.is_empty() { - return Err(ShellError::labeled_error( - "rm requires target paths", - "needs parameter", - name_tag, - )); - } - - let path = Path::new(path); - let mut all_targets: HashMap = HashMap::new(); - for target in targets { - let all_dots = target - .item - .to_str() - .map_or(false, |v| v.chars().all(|c| c == '.')); - - if all_dots { - return Err(ShellError::labeled_error( - "Cannot remove any parent directory", - "cannot remove any parent directory", - target.tag, - )); - } - - let path = path.join(&target.item); - match glob::glob_with( - &path.to_string_lossy(), - glob::MatchOptions { - require_literal_leading_dot: true, - ..GLOB_PARAMS - }, - ) { - Ok(files) => { - for file in files { - match file { - Ok(ref f) => { - // It is not appropriate to try and remove the - // current directory or its parent when using - // glob patterns. - let name = f.display().to_string(); - if name.ends_with("/.") || name.ends_with("/..") { - continue; - } - - all_targets - .entry(f.clone()) - .or_insert_with(|| target.tag.clone()); - } - Err(e) => { - return Err(ShellError::labeled_error( - format!("Could not remove {:}", path.to_string_lossy()), - e.to_string(), - &target.tag, - )); - } - } - } - } - Err(e) => { - return Err(ShellError::labeled_error( - e.to_string(), - e.to_string(), - &name_tag, - )) - } - }; - } - - if all_targets.is_empty() && !_force { - return Err(ShellError::labeled_error( - "No valid paths", - "no valid paths", - name_tag, - )); - } - - Ok(all_targets - .into_iter() - .map(move |(f, tag)| { - let is_empty = || match f.read_dir() { - Ok(mut p) => p.next().is_none(), - Err(_) => false, - }; - - if let Ok(metadata) = f.symlink_metadata() { - #[cfg(unix)] - let is_socket = metadata.file_type().is_socket(); - #[cfg(unix)] - let is_fifo = metadata.file_type().is_fifo(); - - #[cfg(not(unix))] - let is_socket = false; - #[cfg(not(unix))] - let is_fifo = false; - - if metadata.is_file() - || metadata.file_type().is_symlink() - || recursive - || is_socket - || is_fifo - || is_empty() - { - let result; - #[cfg(feature = "trash-support")] - { - use std::io::Error; - result = if _trash || (rm_always_trash && !_permanent) { - trash::delete(&f).map_err(|e: trash::Error| { - Error::new(ErrorKind::Other, format!("{:?}", e)) - }) - } else if metadata.is_file() { - std::fs::remove_file(&f) - } else { - std::fs::remove_dir_all(&f) - }; - } - #[cfg(not(feature = "trash-support"))] - { - result = if metadata.is_file() || is_socket || is_fifo { - std::fs::remove_file(&f) - } else { - std::fs::remove_dir_all(&f) - }; - } - - if let Err(e) = result { - let msg = - format!("Could not delete because: {:}\nTry '--trash' flag", e); - Err(ShellError::labeled_error(msg, e.to_string(), tag)) - } else { - let val = format!("deleted {:}", f.to_string_lossy()).into(); - Ok(ReturnSuccess::Value(val)) - } - } else { - let msg = - format!("Cannot remove {:}. try --recursive", f.to_string_lossy()); - Err(ShellError::labeled_error( - msg, - "cannot remove non-empty directory", - tag, - )) - } - } else { - let msg = format!("no such file or directory: {:}", f.to_string_lossy()); - Err(ShellError::labeled_error( - msg, - "no such file or directory", - tag, - )) - } - }) - .into_action_stream()) - } - - fn path(&self) -> String { - self.path.clone() - } - - fn pwd(&self, args: CommandArgs) -> Result { - let path = PathBuf::from(self.path()); - let p = match canonicalize(path.as_path()) { - Ok(p) => p, - Err(_) => { - return Err(ShellError::labeled_error( - "unable to show current directory", - "pwd command failed", - &args.call_info.name_tag, - )); - } - }; - - Ok(ActionStream::one(ReturnSuccess::value( - UntaggedValue::Primitive(Primitive::String(p.to_string_lossy().to_string())) - .into_value(&args.call_info.name_tag), - ))) - } - - fn set_path(&mut self, path: String) { - let pathbuf = PathBuf::from(&path); - let path = match canonicalize_with(pathbuf.as_path(), self.path()) { - Ok(path) => { - let _ = std::env::set_current_dir(&path); - std::env::set_var("PWD", &path); - path - } - _ => { - // TODO: handle the case where the path cannot be canonicalized - pathbuf - } - }; - self.last_path = self.path.clone(); - self.path = path.to_string_lossy().to_string(); - } - - fn open( - &self, - path: &Path, - name: Span, - with_encoding: Option<&'static Encoding>, - ) -> Result< - Box> + Sync + Send>, - ShellError, - > { - let metadata = std::fs::metadata(&path); - - let read_full = if let Ok(metadata) = metadata { - // Arbitrarily capping the file at 32 megs, so we don't try to read large files in all at once - metadata.is_file() && metadata.len() < (1024 * 1024 * 32) - } else { - false - }; - - if read_full { - // We should, in theory, be able to read in the whole file as one chunk - let buffer = std::fs::read(&path).map_err(|e| { - ShellError::labeled_error( - format!("Error opening file: {:?}", e), - "Error opening file", - name, - ) - })?; - - let bytes_mut = bytes::BytesMut::from(&buffer[..]); - - let mut codec = MaybeTextCodec::new(with_encoding); - - match codec.decode(&bytes_mut).map_err(|_| { - ShellError::labeled_error("Error opening file", "error opening file", name) - })? { - Some(sb) => Ok(Box::new(vec![Ok(sb)].into_iter())), - None => Ok(Box::new(vec![].into_iter())), - } - } else { - // We don't know that this is a finite file, so treat it as a stream - let f = std::fs::File::open(&path).map_err(|e| { - ShellError::labeled_error( - format!("Error opening file: {:?}", e), - "Error opening file", - name, - ) - })?; - let buf_reader = BufReader::new(f); - let buf_codec = BufCodecReader::new(buf_reader, MaybeTextCodec::new(with_encoding)); - - Ok(Box::new(buf_codec)) - } - } - - fn save( - &mut self, - full_path: &Path, - save_data: &[u8], - name: Span, - append: bool, - ) -> Result { - let mut options = OpenOptions::new(); - if append { - options.append(true).create(true) - } else { - options.write(true).create(true).truncate(true) - }; - - match options - .open(full_path) - .and_then(|ref mut file| file.write_all(save_data)) - { - Ok(_) => Ok(OutputStream::empty()), - Err(e) => Err(ShellError::labeled_error( - e.to_string(), - "IO error while saving", - name, - )), - } - } - - fn is_interactive(&self) -> bool { - self.mode == FilesystemShellMode::Cli - } -} - -struct TaggedPathBuf<'a>(&'a PathBuf, &'a Tag); - -fn move_file(from: TaggedPathBuf, to: TaggedPathBuf) -> Result<(), ShellError> { - let TaggedPathBuf(from, from_tag) = from; - let TaggedPathBuf(to, to_tag) = to; - - if to.exists() && from.is_dir() && to.is_file() { - return Err(ShellError::labeled_error( - "Cannot rename a directory to a file", - "invalid destination", - to_tag, - )); - } - - let destination_dir_exists = if to.is_dir() { - true - } else { - to.parent().map(Path::exists).unwrap_or(true) - }; - - if !destination_dir_exists { - return Err(ShellError::labeled_error( - "Destination directory does not exist", - "destination does not exist", - to_tag, - )); - } - - let mut to = to.clone(); - if to.is_dir() { - let from_file_name = match from.file_name() { - Some(name) => name, - None => { - return Err(ShellError::labeled_error( - "Not a valid entry name", - "not a valid entry name", - from_tag, - )) - } - }; - - to.push(from_file_name); - } - - move_item(from, from_tag, &to) -} - -fn move_item(from: &Path, from_tag: &Tag, to: &Path) -> Result<(), ShellError> { - // We first try a rename, which is a quick operation. If that doesn't work, we'll try a copy - // and remove the old file/folder. This is necessary if we're moving across filesystems or devices. - std::fs::rename(&from, &to).or_else(|_| { - match if from.is_file() { - let mut options = fs_extra::file::CopyOptions::new(); - options.overwrite = true; - fs_extra::file::move_file(from, to, &options) - } else { - let mut options = fs_extra::dir::CopyOptions::new(); - options.overwrite = true; - options.copy_inside = true; - fs_extra::dir::move_dir(from, to, &options) - } { - Ok(_) => Ok(()), - Err(e) => Err(ShellError::labeled_error( - format!("Could not move {:?} to {:?}. {:}", from, to, e), - "could not move", - from_tag, - )), - } - }) -} - -fn is_empty_dir(dir: impl AsRef) -> bool { - match dir.as_ref().read_dir() { - Err(_) => true, - Ok(mut s) => s.next().is_none(), - } -} - -fn permission_denied(dir: impl AsRef) -> bool { - match dir.as_ref().read_dir() { - Err(e) => matches!(e.kind(), std::io::ErrorKind::PermissionDenied), - Ok(_) => false, - } -} - -fn is_hidden_dir(dir: impl AsRef) -> bool { - #[cfg(windows)] - { - use std::os::windows::fs::MetadataExt; - - if let Ok(metadata) = dir.as_ref().metadata() { - let attributes = metadata.file_attributes(); - // https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants - (attributes & 0x2) != 0 - } else { - false - } - } - - #[cfg(not(windows))] - { - dir.as_ref() - .file_name() - .map(|name| name.to_string_lossy().starts_with('.')) - .unwrap_or(false) - } -} - -#[cfg(unix)] -use std::os::unix::fs::FileTypeExt; - -pub fn get_file_type(md: &std::fs::Metadata) -> &str { - let ft = md.file_type(); - let mut file_type = "Unknown"; - if ft.is_dir() { - file_type = "Dir"; - } else if ft.is_file() { - file_type = "File"; - } else if ft.is_symlink() { - file_type = "Symlink"; - } else { - #[cfg(unix)] - { - if ft.is_block_device() { - file_type = "Block device"; - } else if ft.is_char_device() { - file_type = "Char device"; - } else if ft.is_fifo() { - file_type = "Pipe"; - } else if ft.is_socket() { - file_type = "Socket"; - } - } - } - file_type -} - -#[allow(clippy::too_many_arguments)] -pub(crate) fn dir_entry_dict( - filename: &std::path::Path, - metadata: Option<&std::fs::Metadata>, - tag: impl Into, - long: bool, - short_name: bool, - du: bool, - ctrl_c: Arc, -) -> Result { - let tag = tag.into(); - let mut dict = TaggedDictBuilder::new(&tag); - // Insert all columns first to maintain proper table alignment if we can't find (or are not allowed to view) any information - if long { - #[cfg(windows)] - { - for column in [ - "name", "type", "target", "readonly", "size", "created", "accessed", "modified", - ] { - dict.insert_untagged(column, UntaggedValue::nothing()); - } - } - - #[cfg(unix)] - { - for column in [ - "name", - "type", - "target", - "num_links", - "inode", - "readonly", - "mode", - "uid", - "group", - "size", - "created", - "accessed", - "modified", - ] { - dict.insert_untagged(column, UntaggedValue::nothing()); - } - } - } else { - for column in ["name", "type", "target", "size", "modified"] { - if column == "target" { - continue; - } - dict.insert_untagged(column, UntaggedValue::nothing()); - } - } - - let name = if short_name { - filename.file_name().and_then(|s| s.to_str()) - } else { - filename.to_str() - } - .ok_or_else(|| { - ShellError::labeled_error( - format!("Invalid file name: {:}", filename.to_string_lossy()), - "invalid file name", - tag, - ) - })?; - - dict.insert_untagged("name", UntaggedValue::filepath(name)); - - if let Some(md) = metadata { - dict.insert_untagged("type", get_file_type(md)); - } - - if long { - if let Some(md) = metadata { - if md.file_type().is_symlink() { - let symlink_target_untagged_value: UntaggedValue; - if let Ok(path_to_link) = filename.read_link() { - symlink_target_untagged_value = - UntaggedValue::string(path_to_link.to_string_lossy()); - } else { - symlink_target_untagged_value = - UntaggedValue::string("Could not obtain target file's path"); - } - dict.insert_untagged("target", symlink_target_untagged_value); - } - } - } - - if long { - if let Some(md) = metadata { - dict.insert_untagged( - "readonly", - UntaggedValue::boolean(md.permissions().readonly()), - ); - - #[cfg(unix)] - { - use std::os::unix::fs::MetadataExt; - let mode = md.permissions().mode(); - dict.insert_untagged( - "mode", - UntaggedValue::string(umask::Mode::from(mode).to_string()), - ); - - let nlinks = md.nlink(); - dict.insert_untagged("num_links", UntaggedValue::string(nlinks.to_string())); - - let inode = md.ino(); - dict.insert_untagged("inode", UntaggedValue::string(inode.to_string())); - - if let Some(user) = users::get_user_by_uid(md.uid()) { - dict.insert_untagged( - "uid", - UntaggedValue::string(user.name().to_string_lossy()), - ); - } - - if let Some(group) = users::get_group_by_gid(md.gid()) { - dict.insert_untagged( - "group", - UntaggedValue::string(group.name().to_string_lossy()), - ); - } - } - } - } - - if let Some(md) = metadata { - let mut size_untagged_value: UntaggedValue = UntaggedValue::nothing(); - - if md.is_dir() { - let dir_size: u64 = if du { - let params = DirBuilder::new( - Tag { - anchor: None, - span: Span::new(0, 2), - }, - None, - false, - None, - false, - ); - - DirInfo::new(filename, ¶ms, None, ctrl_c).get_size() - } else { - md.len() - }; - - size_untagged_value = UntaggedValue::filesize(dir_size); - } else if md.is_file() { - size_untagged_value = UntaggedValue::filesize(md.len()); - } else if md.file_type().is_symlink() { - if let Ok(symlink_md) = filename.symlink_metadata() { - size_untagged_value = UntaggedValue::filesize(symlink_md.len() as u64); - } - } - - dict.insert_untagged("size", size_untagged_value); - } - - if let Some(md) = metadata { - if long { - if let Ok(c) = md.created() { - dict.insert_untagged("created", UntaggedValue::system_date(c)); - } - - if let Ok(a) = md.accessed() { - dict.insert_untagged("accessed", UntaggedValue::system_date(a)); - } - } - - if let Ok(m) = md.modified() { - dict.insert_untagged("modified", UntaggedValue::system_date(m)); - } - } - - Ok(dict.into_value()) -} - -fn path_contains_hidden_folder(path: &Path, folders: &[PathBuf]) -> bool { - let path_str = path.to_str().expect("failed to read path"); - if folders - .iter() - .any(|p| path_str.starts_with(&p.to_str().expect("failed to read hidden paths"))) - { - return true; - } - false -} diff --git a/old_nushell/crates/nu-engine/src/filesystem/mod.rs b/old_nushell/crates/nu-engine/src/filesystem/mod.rs deleted file mode 100644 index 8c9b64452..000000000 --- a/old_nushell/crates/nu-engine/src/filesystem/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) mod dir_info; -pub mod filesystem_shell; -pub(crate) mod utils; diff --git a/old_nushell/crates/nu-engine/src/filesystem/utils.rs b/old_nushell/crates/nu-engine/src/filesystem/utils.rs deleted file mode 100644 index dbc823e28..000000000 --- a/old_nushell/crates/nu-engine/src/filesystem/utils.rs +++ /dev/null @@ -1,210 +0,0 @@ -use nu_errors::ShellError; -use nu_path::canonicalize_with; -use std::path::{Path, PathBuf}; - -#[derive(Default)] -pub struct FileStructure { - pub resources: Vec, -} - -impl FileStructure { - pub fn new() -> FileStructure { - FileStructure { - resources: Vec::::new(), - } - } - - #[allow(dead_code)] - pub fn contains_more_than_one_file(&self) -> bool { - self.resources.len() > 1 - } - - #[allow(dead_code)] - pub fn contains_files(&self) -> bool { - !self.resources.is_empty() - } - - pub fn paths_applying_with( - &mut self, - to: F, - ) -> Result, Box> - where - F: Fn((PathBuf, usize)) -> Result<(PathBuf, PathBuf), Box>, - { - self.resources - .iter() - .map(|f| (PathBuf::from(&f.loc), f.at)) - .map(to) - .collect() - } - - pub fn walk_decorate(&mut self, start_path: &Path) -> Result<(), ShellError> { - self.resources = Vec::::new(); - self.build(start_path, 0)?; - self.resources.sort(); - - Ok(()) - } - - fn build(&mut self, src: &Path, lvl: usize) -> Result<(), ShellError> { - let source = canonicalize_with(src, std::env::current_dir()?)?; - - if source.is_dir() { - for entry in std::fs::read_dir(src)? { - let entry = entry?; - let path = entry.path(); - - if path.is_dir() { - self.build(&path, lvl + 1)?; - } - - self.resources.push(Res { - loc: path.to_path_buf(), - at: lvl, - }); - } - } else { - self.resources.push(Res { - loc: source, - at: lvl, - }); - } - - Ok(()) - } -} - -#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct Res { - pub at: usize, - pub loc: PathBuf, -} - -impl Res {} - -#[cfg(test)] -mod tests { - use super::{FileStructure, Res}; - use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value, ValueResource, ValueStructure}; - use nu_source::Tag; - use nu_test_support::{fs::Stub::EmptyFile, playground::Playground}; - use std::path::PathBuf; - - fn structured_sample_record(key: &str, value: &str) -> Value { - let mut record = TaggedDictBuilder::new(Tag::unknown()); - record.insert_untagged(key, UntaggedValue::string(value)); - record.into_value() - } - - fn sample_nushell_source_code() -> Value { - /* - src - commands - plugins => "sys.rs" - tests - helpers => "mod.rs" - */ - - let mut src = TaggedDictBuilder::new(Tag::unknown()); - let mut record = TaggedDictBuilder::new(Tag::unknown()); - - record.insert_value("commands", structured_sample_record("plugins", "sys.rs")); - record.insert_value("tests", structured_sample_record("helpers", "mod.rs")); - src.insert_value("src", record.into_value()); - - src.into_value() - } - - #[test] - fn prepares_and_decorates_value_filesystemlike_sources() { - let mut res = ValueStructure::new(); - - res.walk_decorate(&sample_nushell_source_code()) - .expect("Can not decorate values traversal."); - - assert_eq!( - res.resources, - vec![ - ValueResource { - loc: PathBuf::from("src"), - at: 0, - }, - ValueResource { - loc: PathBuf::from("commands"), - at: 1, - }, - ValueResource { - loc: PathBuf::from("tests"), - at: 1, - }, - ValueResource { - loc: PathBuf::from("helpers"), - at: 2, - }, - ValueResource { - loc: PathBuf::from("plugins"), - at: 2, - }, - ] - ); - } - - #[test] - fn recognizes_if_path_exists_in_value_filesystemlike_sources() { - let mut res = ValueStructure::new(); - - res.walk_decorate(&sample_nushell_source_code()) - .expect("Can not decorate values traversal."); - - assert!(res.exists(&PathBuf::from("/"))); - - assert!(res.exists(&PathBuf::from("src/commands/plugins"))); - assert!(res.exists(&PathBuf::from("src/commands"))); - assert!(res.exists(&PathBuf::from("src/tests"))); - assert!(res.exists(&PathBuf::from("src/tests/helpers"))); - assert!(res.exists(&PathBuf::from("src"))); - - assert!(res.exists(&PathBuf::from("/src/commands/plugins"))); - assert!(res.exists(&PathBuf::from("/src/commands"))); - assert!(res.exists(&PathBuf::from("/src/tests"))); - assert!(res.exists(&PathBuf::from("/src/tests/helpers"))); - assert!(res.exists(&PathBuf::from("/src"))); - - assert!(!res.exists(&PathBuf::from("/not_valid"))); - assert!(!res.exists(&PathBuf::from("/src/not_valid"))); - } - - #[test] - fn prepares_and_decorates_filesystem_source_files() { - Playground::setup("file_structure_test", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("sample.ini"), - EmptyFile("sample.eml"), - EmptyFile("cargo_sample.toml"), - ]); - - let mut res = FileStructure::new(); - - res.walk_decorate(dirs.test()) - .expect("Can not decorate files traversal."); - - assert_eq!( - res.resources, - vec![ - Res { - loc: dirs.test().join("cargo_sample.toml"), - at: 0 - }, - Res { - loc: dirs.test().join("sample.eml"), - at: 0 - }, - Res { - loc: dirs.test().join("sample.ini"), - at: 0 - } - ] - ); - }) - } -} diff --git a/old_nushell/crates/nu-engine/src/from_value.rs b/old_nushell/crates/nu-engine/src/from_value.rs deleted file mode 100644 index 05c627bf3..000000000 --- a/old_nushell/crates/nu-engine/src/from_value.rs +++ /dev/null @@ -1,487 +0,0 @@ -use std::path::PathBuf; - -use bigdecimal::{BigDecimal, ToPrimitive}; -use chrono::{DateTime, FixedOffset}; -use nu_errors::ShellError; -use nu_path::expand_path; -use nu_protocol::{ - hir::CapturedBlock, ColumnPath, Dictionary, Primitive, Range, SpannedTypeName, UntaggedValue, - Value, -}; -use nu_source::{Tagged, TaggedItem}; -use num_bigint::BigInt; - -pub trait FromValue: Sized { - fn from_value(v: &Value) -> Result; -} - -impl FromValue for Value { - fn from_value(v: &Value) -> Result { - Ok(v.clone()) - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Int(i)), - .. - } => Ok(BigInt::from(*i).tagged(tag)), - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(i)), - .. - } => Ok(BigInt::from(*i).tagged(tag)), - Value { - value: UntaggedValue::Primitive(Primitive::Duration(i)), - .. - } => Ok(i.clone().tagged(tag)), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("integer", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("integer", v.spanned_type_name())), - } - } -} - -impl FromValue for num_bigint::BigInt { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Int(i)), - .. - } => Ok(BigInt::from(*i)), - Value { - value: UntaggedValue::Primitive(Primitive::Filesize(i)), - .. - } => Ok(BigInt::from(*i)), - Value { - value: UntaggedValue::Primitive(Primitive::Duration(i)), - .. - } => Ok(i.clone()), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("integer", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("integer", v.spanned_type_name())), - } - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - v.as_u64().map(|s| s.tagged(tag)) - } -} - -impl FromValue for u64 { - fn from_value(v: &Value) -> Result { - v.as_u64() - } -} - -impl FromValue for i64 { - fn from_value(v: &Value) -> Result { - v.as_i64() - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - v.as_i64().map(|s| s.tagged(tag)) - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - v.as_u32().map(|s| s.tagged(tag)) - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - v.as_i16().map(|s| s.tagged(tag)) - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - v.as_usize().map(|s| s.tagged(tag)) - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - v.as_char().map(|c| c.tagged(tag)) - } -} - -impl FromValue for usize { - fn from_value(v: &Value) -> Result { - v.as_usize() - } -} - -impl FromValue for i32 { - fn from_value(v: &Value) -> Result { - v.as_i32() - } -} - -impl FromValue for bigdecimal::BigDecimal { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Decimal(d)), - .. - } => Ok(d.clone()), - Value { - value: UntaggedValue::Primitive(Primitive::Int(i)), - .. - } => Ok(BigDecimal::from(*i)), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("decimal", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("decimal", v.spanned_type_name())), - } - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - match &v.value { - UntaggedValue::Primitive(Primitive::Decimal(d)) => Ok(d.clone().tagged(tag)), - UntaggedValue::Primitive(Primitive::Int(i)) => Ok(BigDecimal::from(*i).tagged(tag)), - _ => Err(ShellError::type_error("decimal", v.spanned_type_name())), - } - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - let decimal: bigdecimal::BigDecimal = FromValue::from_value(v)?; - - match decimal.to_f64() { - Some(d) => Ok(d.tagged(tag)), - _ => Err(ShellError::type_error("decimal", v.spanned_type_name())), - } - } -} - -impl FromValue for String { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - .. - } => Ok(s.clone()), - Value { - value: UntaggedValue::Primitive(Primitive::GlobPattern(s)), - .. - } => Ok(s.clone()), - Value { - value: UntaggedValue::Primitive(Primitive::FilePath(p)), - .. - } => Ok(p.to_string_lossy().to_string()), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("string", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("string", v.spanned_type_name())), - } - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - v.as_string().map(|s| s.tagged(tag)) - } -} - -impl FromValue for PathBuf { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - .. - } => Ok(expand_path(s)), - Value { - value: UntaggedValue::Primitive(Primitive::FilePath(p)), - .. - } => Ok(expand_path(p)), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("filepath", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("filepath", v.spanned_type_name())), - } - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - tag, - } => Ok(expand_path(s).tagged(tag)), - Value { - value: UntaggedValue::Primitive(Primitive::FilePath(p)), - tag, - } => Ok(expand_path(p).tagged(tag)), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("filepath", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("filepath", v.spanned_type_name())), - } - } -} - -impl FromValue for ColumnPath { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::ColumnPath(c)), - .. - } => Ok(c.clone()), - v => Err(ShellError::type_error("column path", v.spanned_type_name())), - } - } -} - -impl FromValue for bool { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Boolean(b)), - .. - } => Ok(*b), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("boolean", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("boolean", v.spanned_type_name())), - } - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Boolean(b)), - tag, - } => Ok((*b).tagged(tag)), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("boolean", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("boolean", v.spanned_type_name())), - } - } -} - -impl FromValue for DateTime { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Date(d)), - .. - } => Ok(*d), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("date", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("date", v.spanned_type_name())), - } - } -} - -impl FromValue for Range { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Range(r)), - .. - } => Ok((**r).clone()), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("range", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("range", v.spanned_type_name())), - } - } -} - -impl FromValue for Tagged { - fn from_value(v: &Value) -> Result { - let tag = v.tag.clone(); - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Range(ref range)), - .. - } => Ok((*range.clone()).tagged(tag)), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("range", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("range", v.spanned_type_name())), - } - } -} - -impl FromValue for Vec { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Primitive(Primitive::Binary(b)), - .. - } => Ok(b.clone()), - Value { - value: UntaggedValue::Primitive(Primitive::String(s)), - .. - } => Ok(s.bytes().collect()), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("binary data", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("binary data", v.spanned_type_name())), - } - } -} - -impl FromValue for Dictionary { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Row(r), - .. - } => Ok(r.clone()), - v => Err(ShellError::type_error("row", v.spanned_type_name())), - } - } -} - -impl FromValue for CapturedBlock { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Block(b), - .. - } => Ok((**b).clone()), - Value { - value: UntaggedValue::Row(_), - .. - } => { - let mut shell_error = ShellError::type_error("block", v.spanned_type_name()); - shell_error.notes.push( - "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), - ); - Err(shell_error) - } - v => Err(ShellError::type_error("block", v.spanned_type_name())), - } - } -} - -impl FromValue for Vec { - fn from_value(v: &Value) -> Result { - match v { - Value { - value: UntaggedValue::Table(t), - .. - } => Ok(t.clone()), - Value { - value: UntaggedValue::Row(_), - .. - } => Ok(vec![v.clone()]), - v => Err(ShellError::type_error("table", v.spanned_type_name())), - } - } -} diff --git a/old_nushell/crates/nu-engine/src/lib.rs b/old_nushell/crates/nu-engine/src/lib.rs deleted file mode 100644 index 607ab63e1..000000000 --- a/old_nushell/crates/nu-engine/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod call_info; -mod command_args; -mod config_holder; -pub mod documentation; -mod env; -pub mod evaluate; -pub mod evaluation_context; -mod example; -pub mod filesystem; -mod from_value; -mod maybe_text_codec; -pub mod plugin; -mod print; -pub mod script; -pub mod shell; -mod types; -mod whole_stream_command; - -pub use crate::call_info::UnevaluatedCallInfo; -pub use crate::command_args::{CommandArgs, RunnableContext}; -pub use crate::config_holder::ConfigHolder; -pub use crate::documentation::{generate_docs, get_brief_help, get_documentation, get_full_help}; -pub use crate::env::host::FakeHost; -pub use crate::env::host::Host; -pub use crate::evaluate::block::run_block; -pub use crate::evaluate::envvar::EnvVar; -pub use crate::evaluate::scope::Scope; -pub use crate::evaluate::{evaluator, evaluator::evaluate_baseline_expr}; -pub use crate::evaluation_context::EvaluationContext; -pub use crate::example::Example; -pub use crate::filesystem::dir_info::{DirBuilder, DirInfo, FileInfo}; -pub use crate::filesystem::filesystem_shell::FilesystemShell; -pub use crate::from_value::FromValue; -pub use crate::maybe_text_codec::{BufCodecReader, MaybeTextCodec, StringOrBinary}; -pub use crate::print::maybe_print_errors; -pub use crate::shell::painter::Painter; -pub use crate::shell::palette::{DefaultPalette, Palette}; -pub use crate::shell::shell_manager::ShellManager; -pub use crate::shell::value_shell; -pub use crate::whole_stream_command::{whole_stream_command, Command, WholeStreamCommand}; diff --git a/old_nushell/crates/nu-engine/src/maybe_text_codec.rs b/old_nushell/crates/nu-engine/src/maybe_text_codec.rs deleted file mode 100644 index 60c011cf9..000000000 --- a/old_nushell/crates/nu-engine/src/maybe_text_codec.rs +++ /dev/null @@ -1,113 +0,0 @@ -use std::io::{BufRead, BufReader, Read}; - -use nu_errors::ShellError; - -use encoding_rs::{CoderResult, Decoder, Encoding, UTF_8}; - -#[cfg(not(test))] -const OUTPUT_BUFFER_SIZE: usize = 8192; -#[cfg(test)] -const OUTPUT_BUFFER_SIZE: usize = 4; - -#[derive(Debug, Eq, PartialEq)] -pub enum StringOrBinary { - String(String), - Binary(Vec), -} - -pub struct MaybeTextCodec { - decoder: Decoder, -} - -pub struct BufCodecReader { - maybe_text_codec: MaybeTextCodec, - input: BufReader, -} - -impl BufCodecReader { - pub fn new(input: BufReader, maybe_text_codec: MaybeTextCodec) -> Self { - BufCodecReader { - maybe_text_codec, - input, - } - } -} - -impl Iterator for BufCodecReader { - type Item = Result; - - fn next(&mut self) -> Option { - let buffer = self.input.fill_buf(); - match buffer { - Ok(s) => { - let result = self.maybe_text_codec.decode(s).transpose(); - - let buffer_len = s.len(); - self.input.consume(buffer_len); - - result - } - Err(e) => Some(Err(ShellError::untagged_runtime_error(e.to_string()))), - } - } -} - -impl MaybeTextCodec { - // The constructor takes an Option<&'static Encoding>, because an absence of an encoding indicates that we want BOM sniffing enabled - pub fn new(encoding: Option<&'static Encoding>) -> Self { - let decoder = match encoding { - Some(e) => e.new_decoder_with_bom_removal(), - None => UTF_8.new_decoder(), - }; - MaybeTextCodec { decoder } - } -} - -impl Default for MaybeTextCodec { - fn default() -> Self { - MaybeTextCodec { - decoder: UTF_8.new_decoder(), - } - } -} - -impl MaybeTextCodec { - pub fn decode(&mut self, src: &[u8]) -> Result, ShellError> { - if src.is_empty() { - return Ok(None); - } - - let mut s = String::with_capacity(OUTPUT_BUFFER_SIZE); - - let (res, _read, replacements) = self.decoder.decode_to_string(src, &mut s, false); - - let result = if replacements { - // If we had to make replacements when converting to utf8, fall back to binary - StringOrBinary::Binary(src.to_vec()) - } else { - // If original buffer size is too small, we continue to allocate new Strings and append - // them to the result until the input buffer is smaller than the allocated String - if let CoderResult::OutputFull = res { - let mut buffer = String::with_capacity(OUTPUT_BUFFER_SIZE); - loop { - let (res, _read, _replacements) = - self.decoder - .decode_to_string(&src[s.len()..], &mut buffer, false); - s.push_str(&buffer); - - if let CoderResult::InputEmpty = res { - break; - } - - buffer.clear(); - } - } - - StringOrBinary::String(s) - }; - - // src.clear(); - - Ok(Some(result)) - } -} diff --git a/old_nushell/crates/nu-engine/src/plugin/build_plugin.rs b/old_nushell/crates/nu-engine/src/plugin/build_plugin.rs deleted file mode 100644 index 7838ed9b1..000000000 --- a/old_nushell/crates/nu-engine/src/plugin/build_plugin.rs +++ /dev/null @@ -1,172 +0,0 @@ -use crate::plugin::run_plugin::PluginCommandBuilder; -use log::trace; -use nu_errors::ShellError; -use nu_path::canonicalize; -use nu_plugin::jsonrpc::JsonRpc; -use nu_protocol::{Signature, Value}; -use std::io::{BufRead, BufReader, Write}; -use std::process::{Child, Command, Stdio}; - -use rayon::prelude::*; - -pub fn build_plugin_command( - path: &std::path::Path, -) -> Result, ShellError> { - let ext = path.extension(); - let ps1_file = match ext { - Some(ext) => ext == "ps1", - None => false, - }; - - let mut child: Child = if ps1_file { - Command::new("pwsh") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .args([ - "-NoLogo", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-File", - &path.to_string_lossy(), - ]) - .spawn() - .expect("Failed to spawn PowerShell process") - } else { - Command::new(path) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Failed to spawn child process") - }; - - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - let stdout = child.stdout.as_mut().expect("Failed to open stdout"); - - let mut reader = BufReader::new(stdout); - - let request = JsonRpc::new("config", Vec::::new()); - let request_raw = serde_json::to_string(&request)?; - trace!(target: "nu::load", "plugin infrastructure config -> path {:#?}, request {:?}", &path, &request_raw); - stdin.write_all(format!("{}\n", request_raw).as_bytes())?; - let path = canonicalize(path)?; - - let mut input = String::new(); - let result = match reader.read_line(&mut input) { - Ok(count) => { - trace!(target: "nu::load", "plugin infrastructure -> config response for {:#?}", &path); - trace!(target: "nu::load", "plugin infrastructure -> processing response ({} bytes)", count); - trace!(target: "nu::load", "plugin infrastructure -> response: {}", input); - - let response = serde_json::from_str::>>(&input); - match response { - Ok(jrpc) => match jrpc.params { - Ok(params) => { - let fname = path.to_string_lossy(); - - trace!(target: "nu::load", "plugin infrastructure -> processing {:?}", params); - - let name = params.name.clone(); - - let fname = fname.to_string(); - - Ok(Some(PluginCommandBuilder::new(&name, &fname, params))) - } - Err(e) => Err(e), - }, - Err(e) => { - trace!(target: "nu::load", "plugin infrastructure -> incompatible {:?}", input); - Err(ShellError::untagged_runtime_error(format!( - "Error: {:?}", - e - ))) - } - } - } - Err(e) => Err(ShellError::untagged_runtime_error(format!( - "Error: {:?}", - e - ))), - }; - - let _ = child.wait(); - - result -} - -pub fn scan( - paths: Vec, -) -> Result, ShellError> { - let mut plugins = vec![]; - - let opts = glob::MatchOptions { - case_sensitive: false, - require_literal_separator: false, - require_literal_leading_dot: false, - }; - - for path in paths { - let mut pattern = path.to_path_buf(); - - pattern.push(std::path::Path::new("nu_plugin_[a-z0-9][a-z0-9]*")); - - let plugs: Vec<_> = glob::glob_with(&pattern.to_string_lossy(), opts)? - .filter_map(|x| x.ok()) - .collect(); - - let plugs: Vec<_> = plugs - .par_iter() - .filter_map(|path| { - let bin_name = { - if let Some(name) = path.file_name() { - name.to_str().unwrap_or("") - } else { - "" - } - }; - - // allow plugins with extensions on all platforms - let is_valid_name = { - bin_name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '.') - }; - - let is_executable = { - #[cfg(windows)] - { - bin_name.ends_with(".exe") - || bin_name.ends_with(".bat") - || bin_name.ends_with(".cmd") - || bin_name.ends_with(".py") - || bin_name.ends_with(".ps1") - } - - #[cfg(not(windows))] - { - !bin_name.contains('.') - || (bin_name.ends_with('.') - || bin_name.ends_with(".py") - || bin_name.ends_with(".rb") - || bin_name.ends_with(".sh") - || bin_name.ends_with(".bash") - || bin_name.ends_with(".zsh") - || bin_name.ends_with(".pl") - || bin_name.ends_with(".awk") - || bin_name.ends_with(".ps1")) - } - }; - - if is_valid_name && is_executable { - trace!(target: "nu::load", "plugin infrastructure -> Trying {:?}", path.display()); - build_plugin_command(path).unwrap_or(None) - } else { - None - } - }).map(|p| p.build()) - .collect::>(); - plugins.extend(plugs); - } - - Ok(plugins) -} diff --git a/old_nushell/crates/nu-engine/src/plugin/mod.rs b/old_nushell/crates/nu-engine/src/plugin/mod.rs deleted file mode 100644 index 1d1650c40..000000000 --- a/old_nushell/crates/nu-engine/src/plugin/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod build_plugin; -pub(crate) mod run_plugin; diff --git a/old_nushell/crates/nu-engine/src/plugin/run_plugin.rs b/old_nushell/crates/nu-engine/src/plugin/run_plugin.rs deleted file mode 100644 index 0372185cc..000000000 --- a/old_nushell/crates/nu-engine/src/plugin/run_plugin.rs +++ /dev/null @@ -1,549 +0,0 @@ -use crate::{command_args::CommandArgs, evaluate_baseline_expr, UnevaluatedCallInfo}; -use crate::{ - whole_stream_command::{whole_stream_command, WholeStreamCommand}, - EvaluationContext, -}; -use derive_new::new; - -use indexmap::IndexMap; -use log::trace; -use nu_errors::ShellError; -use nu_plugin::jsonrpc::JsonRpc; -use nu_protocol::{hir, Primitive, ReturnValue, Signature, UntaggedValue, Value}; -use nu_source::Tag; -use nu_stream::{ActionStream, InputStream, IntoActionStream}; -use serde::{self, Deserialize, Serialize}; -use std::collections::VecDeque; -use std::io::prelude::*; -use std::io::BufReader; -use std::io::Write; -use std::path::Path; -use std::process::{Child, Command, Stdio}; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "method")] -#[allow(non_camel_case_types)] -pub enum NuResult { - response { - params: Result, ShellError>, - }, -} - -enum PluginCommand { - Filter(PluginFilter), - Sink(PluginSink), -} - -impl PluginCommand { - fn command(self) -> crate::whole_stream_command::Command { - match self { - PluginCommand::Filter(cmd) => whole_stream_command(cmd), - PluginCommand::Sink(cmd) => whole_stream_command(cmd), - } - } -} - -enum PluginMode { - Filter, - Sink, -} - -pub struct PluginCommandBuilder { - mode: PluginMode, - name: String, - path: String, - config: Signature, -} - -impl PluginCommandBuilder { - pub fn new( - name: impl Into, - path: impl Into, - config: impl Into, - ) -> Self { - let config = config.into(); - - PluginCommandBuilder { - mode: if config.is_filter { - PluginMode::Filter - } else { - PluginMode::Sink - }, - name: name.into(), - path: path.into(), - config, - } - } - - pub fn build(&self) -> crate::whole_stream_command::Command { - let mode = &self.mode; - - let name = self.name.clone(); - let path = self.path.clone(); - let config = self.config.clone(); - - let cmd = match mode { - PluginMode::Filter => PluginCommand::Filter(PluginFilter { name, path, config }), - PluginMode::Sink => PluginCommand::Sink(PluginSink { name, path, config }), - }; - - cmd.command() - } -} - -#[derive(new)] -pub struct PluginFilter { - name: String, - path: String, - config: Signature, -} - -impl WholeStreamCommand for PluginFilter { - fn name(&self) -> &str { - &self.name - } - - fn signature(&self) -> Signature { - self.config.clone() - } - - fn usage(&self) -> &str { - &self.config.usage - } - - fn extra_usage(&self) -> &str { - &self.config.extra_usage - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - run_filter(self.path.clone(), args) - } - - fn is_plugin(&self) -> bool { - true - } - - fn is_builtin(&self) -> bool { - false - } -} - -fn run_filter(path: String, args: CommandArgs) -> Result { - trace!("filter_plugin :: {}", path); - - let bos = vec![UntaggedValue::Primitive(Primitive::BeginningOfStream).into_untagged_value()] - .into_iter(); - let eos = [UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()]; - - let (call_info, input) = evaluate_once(args)?; - - let real_path = Path::new(&path); - let ext = real_path.extension(); - let ps1_file = match ext { - Some(ext) => ext == "ps1", - None => false, - }; - - let mut child: Child = if ps1_file { - Command::new("pwsh") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .args([ - "-NoLogo", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-File", - &real_path.to_string_lossy(), - ]) - .spawn() - .expect("Failed to spawn PowerShell process") - } else { - Command::new(path) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Failed to spawn child process") - }; - - trace!("filtering :: {:?}", call_info); - - Ok(bos - .chain(input) - .chain(eos) - .flat_map(move |item| { - match item { - Value { - value: UntaggedValue::Primitive(Primitive::BeginningOfStream), - .. - } => { - // Beginning of the stream - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - let stdout = child.stdout.as_mut().expect("Failed to open stdout"); - - let mut reader = BufReader::new(stdout); - - let request = JsonRpc::new("begin_filter", call_info.clone()); - let request_raw = serde_json::to_string(&request); - trace!("begin_filter:request {:?}", &request_raw); - - match request_raw { - Err(_) => { - return ActionStream::one(Err(ShellError::labeled_error( - "Could not load json from plugin", - "could not load json from plugin", - &call_info.name_tag, - ))); - } - Ok(request_raw) => { - match stdin.write(format!("{}\n", request_raw).as_bytes()) { - Ok(_) => {} - Err(err) => { - return ActionStream::one(Err(ShellError::unexpected( - err.to_string(), - ))); - } - } - } - } - - let mut input = String::new(); - match reader.read_line(&mut input) { - Ok(_) => { - let response = serde_json::from_str::(&input); - trace!("begin_filter:response {:?}", &response); - - match response { - Ok(NuResult::response { params }) => match params { - Ok(params) => params.into_iter().into_action_stream(), - Err(e) => { - vec![ReturnValue::Err(e)].into_iter().into_action_stream() - } - }, - - Err(e) => ActionStream::one(Err( - ShellError::untagged_runtime_error(format!( - "Error while processing begin_filter response: {:?} {}", - e, input - )), - )), - } - } - Err(e) => ActionStream::one(Err(ShellError::untagged_runtime_error( - format!("Error while reading begin_filter response: {:?}", e), - ))), - } - } - Value { - value: UntaggedValue::Primitive(Primitive::EndOfStream), - .. - } => { - // post stream contents - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - let stdout = child.stdout.as_mut().expect("Failed to open stdout"); - - let mut reader = BufReader::new(stdout); - - let request: JsonRpc> = JsonRpc::new("end_filter", vec![]); - let request_raw = serde_json::to_string(&request); - trace!("end_filter:request {:?}", &request_raw); - - match request_raw { - Err(_) => { - return ActionStream::one(Err(ShellError::labeled_error( - "Could not load json from plugin", - "could not load json from plugin", - &call_info.name_tag, - ))); - } - Ok(request_raw) => { - match stdin.write(format!("{}\n", request_raw).as_bytes()) { - Ok(_) => {} - Err(err) => { - return ActionStream::one(Err(ShellError::unexpected( - err.to_string(), - ))); - } - } - } - } - - let mut input = String::new(); - let stream = match reader.read_line(&mut input) { - Ok(_) => { - let response = serde_json::from_str::(&input); - trace!("end_filter:response {:?}", &response); - - match response { - Ok(NuResult::response { params }) => match params { - Ok(params) => params.into_iter().into_action_stream(), - Err(e) => { - vec![ReturnValue::Err(e)].into_iter().into_action_stream() - } - }, - Err(e) => vec![Err(ShellError::untagged_runtime_error(format!( - "Error while processing end_filter response: {:?} {}", - e, input - )))] - .into_iter() - .into_action_stream(), - } - } - Err(e) => vec![Err(ShellError::untagged_runtime_error(format!( - "Error while reading end_filter response: {:?}", - e - )))] - .into_iter() - .into_action_stream(), - }; - - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - - let request: JsonRpc> = JsonRpc::new("quit", vec![]); - let request_raw = serde_json::to_string(&request); - trace!("quit:request {:?}", &request_raw); - - match request_raw { - Ok(request_raw) => { - let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); - // TODO: Handle error - } - Err(e) => { - return ActionStream::one(Err(ShellError::untagged_runtime_error( - format!("Error while processing quit response: {:?}", e), - ))); - } - } - let _ = child.wait(); - - stream - } - - v => { - // Stream contents - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - let stdout = child.stdout.as_mut().expect("Failed to open stdout"); - - let mut reader = BufReader::new(stdout); - - let request = JsonRpc::new("filter", v); - let request_raw = serde_json::to_string(&request); - trace!("filter:request {:?}", &request_raw); - - match request_raw { - Ok(request_raw) => { - let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); - // TODO: Handle error - } - Err(e) => { - return ActionStream::one(Err(ShellError::untagged_runtime_error( - format!("Error while processing filter response: {:?}", e), - ))); - } - } - - let mut input = String::new(); - match reader.read_line(&mut input) { - Ok(_) => { - let response = serde_json::from_str::(&input); - trace!("filter:response {:?}", &response); - - match response { - Ok(NuResult::response { params }) => match params { - Ok(params) => params.into_iter().into_action_stream(), - Err(e) => { - vec![ReturnValue::Err(e)].into_iter().into_action_stream() - } - }, - Err(e) => ActionStream::one(Err( - ShellError::untagged_runtime_error(format!( - "Error while processing filter response: {:?}\n== input ==\n{}", - e, input - )), - )), - } - } - Err(e) => ActionStream::one(Err(ShellError::untagged_runtime_error( - format!("Error while reading filter response: {:?}", e), - ))), - } - } - } - }) - .into_action_stream()) -} - -#[derive(new)] -pub struct PluginSink { - name: String, - path: String, - config: Signature, -} - -impl WholeStreamCommand for PluginSink { - fn name(&self) -> &str { - &self.name - } - - fn signature(&self) -> Signature { - self.config.clone() - } - - fn usage(&self) -> &str { - &self.config.usage - } - - fn extra_usage(&self) -> &str { - &self.config.extra_usage - } - - fn run_with_actions(&self, args: CommandArgs) -> Result { - run_sink(self.path.clone(), args) - } - - fn is_plugin(&self) -> bool { - true - } - - fn is_builtin(&self) -> bool { - false - } -} - -fn run_sink(path: String, args: CommandArgs) -> Result { - let (call_info, input) = evaluate_once(args)?; - - let input: Vec = input.into_vec(); - - let request = JsonRpc::new("sink", (call_info, input)); - let request_raw = serde_json::to_string(&request); - if let Ok(request_raw) = request_raw { - if let Ok(mut tmpfile) = tempfile::NamedTempFile::new() { - let _ = writeln!(tmpfile, "{}", request_raw); - let _ = tmpfile.flush(); - - let real_path = Path::new(&path); - let ext = real_path.extension(); - let ps1_file = match ext { - Some(ext) => ext == "ps1", - None => false, - }; - - // TODO: This sink may not work in powershell, trying to find - // an example of what CallInfo would look like in this temp file - let child = if ps1_file { - Command::new("pwsh") - .args([ - "-NoLogo", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-File", - &real_path.to_string_lossy(), - tmpfile - .path() - .to_str() - .expect("Failed getting tmpfile path"), - ]) - .spawn() - } else { - Command::new(path).arg(&tmpfile.path()).spawn() - }; - - if let Ok(mut child) = child { - let _ = child.wait(); - - Ok(ActionStream::empty()) - } else { - Err(ShellError::untagged_runtime_error( - "Could not create process for sink command", - )) - } - } else { - Err(ShellError::untagged_runtime_error( - "Could not open file to send sink command message", - )) - } - } else { - Err(ShellError::untagged_runtime_error( - "Could not create message to sink command", - )) - } -} - -/// Associated information for the call of a command, including the args passed to the command and a tag that spans the name of the command being called -#[derive(Deserialize, Serialize, Debug, Clone)] -pub struct CallInfo { - /// The arguments associated with this call - pub args: EvaluatedArgs, - /// The tag (underline-able position) of the name of the call itself - pub name_tag: Tag, -} - -/// The set of positional and named arguments, after their values have been evaluated. -/// -/// * Positional arguments are those who are given as values, without any associated flag. For example, in `foo arg1 arg2`, both `arg1` and `arg2` are positional arguments. -/// * Named arguments are those associated with a flag. For example, `foo --given bar` the named argument would be name `given` and the value `bar`. -#[derive(Debug, Default, new, Serialize, Deserialize, Clone)] -pub struct EvaluatedArgs { - pub positional: Option>, - pub named: Option>, -} - -fn evaluate_once(args: CommandArgs) -> Result<(CallInfo, InputStream), ShellError> { - let input = args.input; - let call_info = evaluate_command(args.call_info, args.context)?; - - Ok((call_info, input)) -} - -fn evaluate_command( - args: UnevaluatedCallInfo, - ctx: EvaluationContext, -) -> Result { - let name_tag = args.name_tag.clone(); - let args = evaluate_args(&args.args, &ctx)?; - - Ok(CallInfo { args, name_tag }) -} - -fn evaluate_args(call: &hir::Call, ctx: &EvaluationContext) -> Result { - let mut positional_args: Vec = vec![]; - - if let Some(positional) = &call.positional { - for pos in positional { - let result = evaluate_baseline_expr(pos, ctx)?; - positional_args.push(result); - } - } - - let positional = if !positional_args.is_empty() { - Some(positional_args) - } else { - None - }; - - let mut named_args = IndexMap::new(); - - if let Some(named) = &call.named { - for (name, value) in named { - match value { - hir::NamedValue::PresentSwitch(tag) => { - named_args.insert(name.clone(), UntaggedValue::boolean(true).into_value(tag)); - } - hir::NamedValue::Value(_, expr) => { - named_args.insert(name.clone(), evaluate_baseline_expr(expr, ctx)?); - } - _ => {} - }; - } - } - - let named = if !named_args.is_empty() { - Some(named_args) - } else { - None - }; - - Ok(EvaluatedArgs::new(positional, named)) -} diff --git a/old_nushell/crates/nu-engine/src/print.rs b/old_nushell/crates/nu-engine/src/print.rs deleted file mode 100644 index f1072a472..000000000 --- a/old_nushell/crates/nu-engine/src/print.rs +++ /dev/null @@ -1,18 +0,0 @@ -use nu_source::Text; - -use crate::EvaluationContext; - -pub fn maybe_print_errors(context: &EvaluationContext, source: Text) -> bool { - let errors = context.current_errors().clone(); - let mut errors = errors.lock(); - - if errors.len() > 0 { - let error = errors[0].clone(); - *errors = vec![]; - - context.host().lock().print_err(error, &source); - true - } else { - false - } -} diff --git a/old_nushell/crates/nu-engine/src/script.rs b/old_nushell/crates/nu-engine/src/script.rs deleted file mode 100644 index fd9c41f0c..000000000 --- a/old_nushell/crates/nu-engine/src/script.rs +++ /dev/null @@ -1,312 +0,0 @@ -use crate::{evaluate::internal::InternalIterator, maybe_print_errors, run_block, shell::CdArgs}; -use crate::{BufCodecReader, MaybeTextCodec, StringOrBinary}; -use nu_errors::ShellError; -use nu_path::{canonicalize_with, trim_trailing_slash}; -use nu_protocol::hir::{ - Call, ClassifiedCommand, Expression, ExternalRedirection, InternalCommand, Literal, - NamedArguments, SpannedExpression, -}; -use nu_protocol::{Primitive, UntaggedValue, Value}; -use nu_stream::{InputStream, IntoInputStream}; - -use crate::EvaluationContext; -use log::{debug, trace}; -use nu_source::{AnchorLocation, Span, Tag, Tagged, Text}; -use std::path::{Path, PathBuf}; -use std::{error::Error, sync::atomic::Ordering}; -use std::{io::BufReader, iter::Iterator}; - -#[derive(Debug)] -pub enum LineResult { - Success(String), - Error(String, ShellError), - Break, - CtrlC, - CtrlD, - ClearHistory, -} - -fn chomp_newline(s: &str) -> &str { - if let Some(s) = s.strip_suffix('\n') { - s - } else { - s - } -} - -pub fn run_script_in_dir( - script: String, - dir: &Path, - ctx: &EvaluationContext, -) -> Result<(), Box> { - //Save path before to switch back to it after executing script - let path_before = ctx.shell_manager().path(); - - ctx.shell_manager() - .set_path(dir.to_string_lossy().to_string()); - run_script_standalone(script, false, ctx, false)?; - ctx.shell_manager().set_path(path_before); - - Ok(()) -} - -/// Process the line by parsing the text to turn it into commands, classify those commands so that we understand what is being called in the pipeline, and then run this pipeline -pub fn process_script( - script_text: &str, - ctx: &EvaluationContext, - redirect_stdin: bool, - span_offset: usize, - cli_mode: bool, -) -> LineResult { - if script_text.trim() == "" { - LineResult::Success(script_text.to_string()) - } else { - let line = chomp_newline(script_text); - - let (block, err) = nu_parser::parse(line, span_offset, &ctx.scope); - - debug!("{:#?}", block); - - if let Some(failure) = err { - return LineResult::Error(line.to_string(), failure.into()); - } - - // There's a special case to check before we process the pipeline: - // If we're giving a path by itself - // ...and it's not a command in the path - // ...and it doesn't have any arguments - // ...and we're in the CLI - // ...then change to this directory - if cli_mode - && block.block.len() == 1 - && block.block[0].pipelines.len() == 1 - && block.block[0].pipelines[0].list.len() == 1 - { - if let ClassifiedCommand::Internal(InternalCommand { - ref name, - ref args, - name_span, - }) = block.block[0].pipelines[0].list[0] - { - let internal_name = name; - let name = args - .positional - .as_ref() - .and_then(|positionals| { - positionals.get(0).map(|e| { - if let Expression::Literal(Literal::String(ref s)) = e.expr { - &s - } else { - "" - } - }) - }) - .unwrap_or(""); - - ctx.sync_path_to_env(); - if internal_name == "run_external" - && args - .positional - .as_ref() - .map(|v| v.len() == 1) - .unwrap_or(true) - && args - .named - .as_ref() - .map(NamedArguments::is_empty) - .unwrap_or(true) - && canonicalize_with(name, ctx.shell_manager().path()).is_ok() - && Path::new(&name).is_dir() - && !ctx.host().lock().is_external_cmd(name) - { - let tag = Tag { - anchor: Some(AnchorLocation::Source(line.into())), - span: name_span, - }; - let path = { - // Here we work differently if we're in Windows because of the expected Windows behavior - #[cfg(windows)] - { - if name.ends_with(':') { - // This looks like a drive shortcut. We need to a) switch drives and b) go back to the previous directory we were viewing on that drive - // But first, we need to save where we are now - let current_path = ctx.shell_manager().path(); - - let split_path: Vec<_> = current_path.split(':').collect(); - if split_path.len() > 1 { - ctx.windows_drives_previous_cwd() - .lock() - .insert(split_path[0].to_string(), current_path); - } - - let name = name.to_uppercase(); - let new_drive: Vec<_> = name.split(':').collect(); - - if let Some(val) = - ctx.windows_drives_previous_cwd().lock().get(new_drive[0]) - { - val.to_string() - } else { - format!("{}\\", name) - } - } else { - name.to_string() - } - } - #[cfg(not(windows))] - { - name.to_string() - } - }; - - let path = trim_trailing_slash(&path); - - let cd_args = CdArgs { - path: Some(Tagged { - item: PathBuf::from(path), - tag: tag.clone(), - }), - }; - - return match ctx.shell_manager().cd(cd_args, tag) { - Err(e) => LineResult::Error(line.to_string(), e), - Ok(stream) => { - let iter = InternalIterator { - context: ctx.clone(), - leftovers: InputStream::empty(), - input: stream, - }; - for _ in iter { - //nullopt, commands are run by iterating over iter - } - LineResult::Success(line.to_string()) - } - }; - } - } - } - - let input_stream = if redirect_stdin { - let file = std::io::stdin(); - let buf_reader = BufReader::new(file); - let buf_codec = BufCodecReader::new(buf_reader, MaybeTextCodec::default()); - let stream = buf_codec.map(|line| { - if let Ok(line) = line { - let primitive = match line { - StringOrBinary::String(s) => Primitive::String(s), - StringOrBinary::Binary(b) => Primitive::Binary(b.into_iter().collect()), - }; - - Ok(Value { - value: UntaggedValue::Primitive(primitive), - tag: Tag::unknown(), - }) - } else { - panic!("Internal error: could not read lines of text from stdin") - } - }); - stream.into_input_stream() - } else { - InputStream::empty() - }; - - trace!("{:#?}", block); - - let result = run_block(&block, ctx, input_stream, ExternalRedirection::None); - - match result { - Ok(input) => { - // Running a pipeline gives us back a stream that we can then - // work through. At the top level, we just want to pull on the - // values to compute them. - - let autoview_cmd = ctx - .get_command("autoview") - .expect("Could not find autoview command"); - - if let Ok(mut output_stream) = ctx.run_command( - autoview_cmd, - Tag::unknown(), - Call::new( - Box::new(SpannedExpression::new( - Expression::string("autoview".to_string()), - Span::unknown(), - )), - Span::unknown(), - ), - input, - ) { - loop { - match output_stream.next() { - Some(Value { - value: UntaggedValue::Error(e), - .. - }) => return LineResult::Error(line.to_string(), e), - Some(_item) => { - if ctx.ctrl_c().load(Ordering::SeqCst) { - break; - } - } - None => break, - } - } - } - - LineResult::Success(line.to_string()) - } - Err(err) => LineResult::Error(line.to_string(), err), - } - } -} - -pub fn run_script_standalone( - script_text: String, - redirect_stdin: bool, - context: &EvaluationContext, - exit_on_error: bool, -) -> Result<(), ShellError> { - context - .shell_manager() - .enter_script_mode() - .map_err(ShellError::from)?; - let line = process_script(&script_text, context, redirect_stdin, 0, false); - - match line { - LineResult::Success(line) => { - let error_code = { - let errors = context.current_errors().clone(); - let errors = errors.lock(); - - if errors.len() > 0 { - 1 - } else { - 0 - } - }; - - maybe_print_errors(context, Text::from(line)); - if error_code != 0 && exit_on_error { - std::process::exit(error_code); - } - } - - LineResult::Error(line, err) => { - context - .host() - .lock() - .print_err(err, &Text::from(line.clone())); - - maybe_print_errors(context, Text::from(line)); - if exit_on_error { - std::process::exit(1); - } - } - - _ => {} - } - - //exit script mode shell - context.shell_manager().remove_at_current(); - - Ok(()) -} diff --git a/old_nushell/crates/nu-engine/src/shell/mod.rs b/old_nushell/crates/nu-engine/src/shell/mod.rs deleted file mode 100644 index fce62a7c8..000000000 --- a/old_nushell/crates/nu-engine/src/shell/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -use nu_stream::{ActionStream, OutputStream}; - -use crate::maybe_text_codec::StringOrBinary; -pub use crate::shell::shell_args::{CdArgs, CopyArgs, LsArgs, MkdirArgs, MvArgs, RemoveArgs}; -use crate::CommandArgs; -use encoding_rs::Encoding; -use nu_errors::ShellError; -use nu_source::{Span, Tag}; -use std::path::{Path, PathBuf}; -use std::sync::atomic::AtomicBool; -use std::sync::Arc; - -pub(crate) mod painter; -pub(crate) mod palette; -pub(crate) mod shell_args; -pub(crate) mod shell_manager; -pub mod value_shell; - -pub trait Shell: std::fmt::Debug { - fn is_interactive(&self) -> bool; - fn name(&self) -> String; - fn homedir(&self) -> Option; - - fn ls( - &self, - args: LsArgs, - name: Tag, - ctrl_c: Arc, - ) -> Result; - fn cd(&self, args: CdArgs, name: Tag) -> Result; - fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> Result; - fn mkdir(&self, args: MkdirArgs, name: Tag, path: &str) -> Result; - fn mv(&self, args: MvArgs, name: Tag, path: &str) -> Result; - fn rm(&self, args: RemoveArgs, name: Tag, path: &str) -> Result; - fn path(&self) -> String; - fn pwd(&self, args: CommandArgs) -> Result; - fn set_path(&mut self, path: String); - fn open( - &self, - path: &Path, - name: Span, - with_encoding: Option<&'static Encoding>, - ) -> Result< - Box> + Send + Sync>, - ShellError, - >; - fn save( - &mut self, - path: &Path, - contents: &[u8], - name: Span, - append: bool, - ) -> Result; -} diff --git a/old_nushell/crates/nu-engine/src/shell/painter.rs b/old_nushell/crates/nu-engine/src/shell/painter.rs deleted file mode 100644 index bf1bcf908..000000000 --- a/old_nushell/crates/nu-engine/src/shell/painter.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::evaluate::scope::Scope; -use crate::shell::palette::Palette; -use nu_ansi_term::{Color, Style}; -use nu_parser::ParserScope; -use nu_protocol::hir::FlatShape; -use nu_source::Spanned; -use std::borrow::Cow; - -// FIXME: find a good home, as nu-engine may be too core for styling -pub struct Painter { - original: Vec, - styles: Vec