diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..a3e737a85f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +history.txt diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..bbec05e95a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,721 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "assert_cmd" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c98233c6673d8601ab23e77eb38f999c51100d46c5703b17288c57fddf3a1ffe" +dependencies = [ + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bstr" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", +] + +[[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", + "time", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "crossterm" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "serde", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6966607622438301997d3dac0d2f6e9a90c68bb6bc1785ea98456ab93c0507" +dependencies = [ + "winapi", +] + +[[package]] +name = "ctor" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "deser-hjson" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f486ff51f3ecdf9364736375a4b358b6eb9f02555d5324fa4837c00b5aa23f5" +dependencies = [ + "serde", +] + +[[package]] +name = "diff" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "engine-q" +version = "0.1.0" +dependencies = [ + "assert_cmd", + "codespan-reporting", + "nu-cli", + "nu-engine", + "nu-parser", + "pretty_assertions", + "reedline", + "tempfile", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "instant" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mio" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172dcceddd4e017cf3239a69300c5e150f8f116f067af133d842cd95857be9b7" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-cli" +version = "0.1.0" +dependencies = [ + "codespan-reporting", + "nu-ansi-term", + "nu-engine", + "nu-parser", + "reedline", +] + +[[package]] +name = "nu-engine" +version = "0.1.0" +dependencies = [ + "nu-parser", +] + +[[package]] +name = "nu-json" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "638d1959b700068470bcf38e40899f53300ed88d3b1db07a4dcaeef04fd647c5" +dependencies = [ + "lazy_static", + "linked-hash-map", + "num-traits", + "regex", + "serde", +] + +[[package]] +name = "nu-parser" +version = "0.1.0" +dependencies = [ + "codespan-reporting", +] + +[[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-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "output_vt100" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" +dependencies = [ + "winapi", +] + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "predicates" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c143348f141cc87aab5b950021bac6145d0e5ae754b0591de23244cee42c9308" +dependencies = [ + "difflib", + "itertools", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" + +[[package]] +name = "predicates-tree" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7dd0fd014130206c9352efbdc92be592751b2b9274dff685348341082c6ea3d" +dependencies = [ + "predicates-core", + "treeline", +] + +[[package]] +name = "pretty_assertions" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cab0e7c02cf376875e9335e0ba1da535775beb5450d21e1dffca068818ed98b" +dependencies = [ + "ansi_term", + "ctor", + "diff", + "output_vt100", +] + +[[package]] +name = "proc-macro2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[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", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reedline" +version = "0.1.0" +source = "git+https://github.com/jntrnr/reedline?branch=main#12ba36f8bed307b3daa3093d0b6c36bae90a7900" +dependencies = [ + "chrono", + "crossterm", + "deser-hjson", + "nu-ansi-term", + "nu-json", + "serde", + "unicode-segmentation", + "unicode-width", +] + +[[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", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_test" +version = "1.0.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca4ebf9d3eff2c70e4092a70a9d759e01b675f8daf1442703a18e57898847830" +dependencies = [ + "serde", +] + +[[package]] +name = "signal-hook" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[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 = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "syn" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "treeline" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[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-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", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/crates/nu-parser/src/lex.rs b/crates/nu-parser/src/lex.rs index 46923d333b..5a33d87bb7 100644 --- a/crates/nu-parser/src/lex.rs +++ b/crates/nu-parser/src/lex.rs @@ -307,41 +307,4 @@ pub fn lex( } } (output, error) -} - -#[cfg(test)] -mod lex_tests { - use super::*; - - #[test] - fn lex_basic() { - let file = b"let x = 4"; - - let output = lex(file, 0, &[], &[]); - - assert!(output.1.is_none()); - } - - #[test] - fn lex_newline() { - let file = b"let x = 300\nlet y = 500;"; - - let output = lex(file, 0, &[], &[]); - - println!("{:#?}", output.0); - assert!(output.0.contains(&Token { - contents: TokenContents::Eol, - span: Span { start: 11, end: 12 } - })); - } - - #[test] - fn lex_empty() { - let file = b""; - - let output = lex(file, 0, &[], &[]); - - assert!(output.0.is_empty()); - assert!(output.1.is_none()); - } -} +} \ No newline at end of file diff --git a/crates/nu-parser/src/lite_parse.rs b/crates/nu-parser/src/lite_parse.rs index 7590b5eb19..f702701b36 100644 --- a/crates/nu-parser/src/lite_parse.rs +++ b/crates/nu-parser/src/lite_parse.rs @@ -80,13 +80,11 @@ impl LiteBlock { } pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { - let mut curr_token = 0; - let mut block = LiteBlock::new(); let mut curr_pipeline = LiteStatement::new(); let mut curr_command = LiteCommand::new(); - while let Some(token) = tokens.get(curr_token) { + for token in tokens.iter() { match &token.contents { TokenContents::Item => curr_command.push(token.span), TokenContents::Pipe => { @@ -110,8 +108,8 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { curr_command.comments.push(token.span); } } - curr_token += 1; } + if !curr_command.is_empty() { curr_pipeline.push(curr_command); } @@ -122,82 +120,3 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option) { (block, None) } - -#[cfg(test)] -mod tests { - use crate::{lex, lite_parse, LiteBlock, ParseError, Span}; - - fn lite_parse_helper(input: &[u8]) -> Result { - let (output, err) = lex(input, 0, &[], &[]); - if let Some(err) = err { - return Err(err); - } - - let (output, err) = lite_parse(&output); - if let Some(err) = err { - return Err(err); - } - - Ok(output) - } - - #[test] - fn comment_before() -> Result<(), ParseError> { - let input = b"# this is a comment\ndef foo bar"; - - let lite_block = lite_parse_helper(input)?; - - assert_eq!(lite_block.block.len(), 1); - assert_eq!(lite_block.block[0].commands.len(), 1); - assert_eq!(lite_block.block[0].commands[0].comments.len(), 1); - assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); - - Ok(()) - } - - #[test] - fn comment_beside() -> Result<(), ParseError> { - let input = b"def foo bar # this is a comment"; - - let lite_block = lite_parse_helper(input)?; - - assert_eq!(lite_block.block.len(), 1); - assert_eq!(lite_block.block[0].commands.len(), 1); - assert_eq!(lite_block.block[0].commands[0].comments.len(), 1); - assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); - - Ok(()) - } - - #[test] - fn comments_stack() -> Result<(), ParseError> { - let input = b"# this is a comment\n# another comment\ndef foo bar "; - - let lite_block = lite_parse_helper(input)?; - - assert_eq!(lite_block.block.len(), 1); - assert_eq!(lite_block.block[0].commands.len(), 1); - assert_eq!(lite_block.block[0].commands[0].comments.len(), 2); - assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); - - Ok(()) - } - - #[test] - fn separated_comments_dont_stack() -> Result<(), ParseError> { - let input = b"# this is a comment\n\n# another comment\ndef foo bar "; - - let lite_block = lite_parse_helper(input)?; - - assert_eq!(lite_block.block.len(), 1); - assert_eq!(lite_block.block[0].commands.len(), 1); - assert_eq!(lite_block.block[0].commands[0].comments.len(), 1); - assert_eq!( - lite_block.block[0].commands[0].comments[0], - Span { start: 21, end: 39 } - ); - assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); - - Ok(()) - } -} diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index fecf01060a..4e1a5281a3 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1959,7 +1959,7 @@ impl<'a> ParserWorkingSet<'a> { error = error.or(err); // Check to see if we have parameters - let params = if matches!( + let _params = if matches!( output.first(), Some(Token { contents: TokenContents::Pipe, @@ -2604,137 +2604,3 @@ impl<'a> ParserWorkingSet<'a> { (output, error) } } - -#[cfg(test)] -mod tests { - use crate::{ParseError, ParserState, Signature}; - - use super::*; - - #[test] - pub fn parse_int() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let (block, err) = working_set.parse_source(b"3", true); - - assert!(err.is_none()); - assert!(block.len() == 1); - assert!(matches!( - block[0], - Statement::Expression(Expression { - expr: Expr::Int(3), - .. - }) - )); - } - - #[test] - pub fn parse_call() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); - working_set.add_decl(sig.into()); - - let (block, err) = working_set.parse_source(b"foo", true); - - assert!(err.is_none()); - assert!(block.len() == 1); - - match &block[0] { - Statement::Expression(Expression { - expr: Expr::Call(call), - .. - }) => { - assert_eq!(call.decl_id, 0); - } - _ => panic!("not a call"), - } - } - - #[test] - pub fn parse_call_missing_flag_arg() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); - working_set.add_decl(sig.into()); - - let (_, err) = working_set.parse_source(b"foo --jazz", true); - assert!(matches!(err, Some(ParseError::MissingFlagParam(..)))); - } - - #[test] - pub fn parse_call_missing_short_flag_arg() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); - working_set.add_decl(sig.into()); - - let (_, err) = working_set.parse_source(b"foo -j", true); - assert!(matches!(err, Some(ParseError::MissingFlagParam(..)))); - } - - #[test] - pub fn parse_call_too_many_shortflag_args() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = Signature::build("foo") - .named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')) - .named("--math", SyntaxShape::Int, "math!!", Some('m')); - working_set.add_decl(sig.into()); - let (_, err) = working_set.parse_source(b"foo -mj", true); - assert!(matches!( - err, - Some(ParseError::ShortFlagBatchCantTakeArg(..)) - )); - } - - #[test] - pub fn parse_call_unknown_shorthand() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j')); - working_set.add_decl(sig.into()); - let (_, err) = working_set.parse_source(b"foo -mj", true); - assert!(matches!(err, Some(ParseError::UnknownFlag(..)))); - } - - #[test] - pub fn parse_call_extra_positional() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j')); - working_set.add_decl(sig.into()); - let (_, err) = working_set.parse_source(b"foo -j 100", true); - assert!(matches!(err, Some(ParseError::ExtraPositional(..)))); - } - - #[test] - pub fn parse_call_missing_req_positional() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!"); - working_set.add_decl(sig.into()); - let (_, err) = working_set.parse_source(b"foo", true); - assert!(matches!(err, Some(ParseError::MissingPositional(..)))); - } - - #[test] - pub fn parse_call_missing_req_flag() { - let parser_state = ParserState::new(); - let mut working_set = ParserWorkingSet::new(&parser_state); - - let sig = - Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None); - working_set.add_decl(sig.into()); - let (_, err) = working_set.parse_source(b"foo", true); - assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..)))); - } -} diff --git a/crates/nu-parser/tests/test_lex.rs b/crates/nu-parser/tests/test_lex.rs new file mode 100644 index 0000000000..7646db7c86 --- /dev/null +++ b/crates/nu-parser/tests/test_lex.rs @@ -0,0 +1,93 @@ +use nu_parser::{lex, ParseError, Span, Token, TokenContents}; + +#[test] +fn lex_basic() { + let file = b"let x = 4"; + + let output = lex(file, 0, &[], &[]); + + assert!(output.1.is_none()); +} + +#[test] +fn lex_newline() { + let file = b"let x = 300\nlet y = 500;"; + + let output = lex(file, 0, &[], &[]); + + assert!(output.0.contains(&Token { + contents: TokenContents::Eol, + span: Span { start: 11, end: 12 } + })); +} + +#[test] +fn lex_empty() { + let file = b""; + + let output = lex(file, 0, &[], &[]); + + assert!(output.0.is_empty()); + assert!(output.1.is_none()); +} + +#[test] +fn lex_parenthesis() { + // The whole parenthesis is an item for the lexer + let file = b"let x = (300 + (322 * 444));"; + + let output = lex(file, 0, &[], &[]); + + assert_eq!( + output.0.get(3).unwrap(), + &Token { + contents: TokenContents::Item, + span: Span { start: 8, end: 27 } + } + ); +} + +#[test] +fn lex_comment() { + let file = b"let x = 300 # a comment \n $x + 444"; + + let output = lex(file, 0, &[], &[]); + + assert_eq!( + output.0.get(4).unwrap(), + &Token { + contents: TokenContents::Comment, + span: Span { start: 12, end: 25 } + } + ); +} + +#[test] +fn lex_is_incomplete() { + let file = b"let x = 300 | ;"; + + let output = lex(file, 0, &[], &[]); + + let err = output.1.unwrap(); + assert!(matches!(err, ParseError::ExtraTokens(_))); +} + +#[test] +fn lex_incomplete_paren() { + let file = b"let x = (300 + ( 4 + 1)"; + + let output = lex(file, 0, &[], &[]); + + let err = output.1.unwrap(); + assert!(matches!(err, ParseError::UnexpectedEof(v, _) if v == ")")); +} + +#[test] +fn lex_incomplete_quote() { + let file = b"let x = '300 + 4 + 1"; + + let output = lex(file, 0, &[], &[]); + + let err = output.1.unwrap(); + assert!(matches!(err, ParseError::UnexpectedEof(v, _) if v == "'")); +} diff --git a/crates/nu-parser/tests/test_lite_parser.rs b/crates/nu-parser/tests/test_lite_parser.rs new file mode 100644 index 0000000000..81c415048f --- /dev/null +++ b/crates/nu-parser/tests/test_lite_parser.rs @@ -0,0 +1,125 @@ +use nu_parser::{lex, lite_parse, LiteBlock, ParseError, Span}; + +fn lite_parse_helper(input: &[u8]) -> Result { + let (output, err) = lex(input, 0, &[], &[]); + if let Some(err) = err { + return Err(err); + } + + let (output, err) = lite_parse(&output); + if let Some(err) = err { + return Err(err); + } + + Ok(output) +} + +#[test] +fn comment_before() -> Result<(), ParseError> { + let input = b"# this is a comment\ndef foo bar"; + + let lite_block = lite_parse_helper(input)?; + + assert_eq!(lite_block.block.len(), 1); + assert_eq!(lite_block.block[0].commands.len(), 1); + assert_eq!(lite_block.block[0].commands[0].comments.len(), 1); + assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); + + Ok(()) +} + +#[test] +fn comment_beside() -> Result<(), ParseError> { + let input = b"def foo bar # this is a comment"; + + let lite_block = lite_parse_helper(input)?; + + assert_eq!(lite_block.block.len(), 1); + assert_eq!(lite_block.block[0].commands.len(), 1); + assert_eq!(lite_block.block[0].commands[0].comments.len(), 1); + assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); + + Ok(()) +} + +#[test] +fn comments_stack() -> Result<(), ParseError> { + let input = b"# this is a comment\n# another comment\ndef foo bar "; + + let lite_block = lite_parse_helper(input)?; + + assert_eq!(lite_block.block.len(), 1); + assert_eq!(lite_block.block[0].commands.len(), 1); + assert_eq!(lite_block.block[0].commands[0].comments.len(), 2); + assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); + + Ok(()) +} + +#[test] +fn separated_comments_dont_stack() -> Result<(), ParseError> { + let input = b"# this is a comment\n\n# another comment\ndef foo bar "; + + let lite_block = lite_parse_helper(input)?; + + assert_eq!(lite_block.block.len(), 1); + assert_eq!(lite_block.block[0].commands.len(), 1); + assert_eq!(lite_block.block[0].commands[0].comments.len(), 1); + assert_eq!( + lite_block.block[0].commands[0].comments[0], + Span { start: 21, end: 39 } + ); + assert_eq!(lite_block.block[0].commands[0].parts.len(), 3); + + Ok(()) +} + +#[test] +fn multiple_statements() -> Result<(), ParseError> { + // Code : + // # A comment + // let a = ( 3 + ( + // 4 + + // 5 )) + // let b = 1 # comment + let input = b"# comment \n let a = ( 3 + (\n 4 + \n 5 )) \n let b = 1 # comment"; + + let lite_block = lite_parse_helper(input)?; + + assert_eq!(lite_block.block.len(), 2); + assert_eq!(lite_block.block[0].commands.len(), 1); + assert_eq!( + lite_block.block[0].commands[0].comments[0], + Span { start: 0, end: 11 } + ); + + assert_eq!(lite_block.block[1].commands.len(), 1); + assert_eq!( + lite_block.block[1].commands[0].comments[0], + Span { start: 52, end: 61 } + ); + + Ok(()) +} + +#[test] +fn multiple_commands() -> Result<(), ParseError> { + // Pipes add commands to the lite parser + // Code : + // let a = ls | where name == 1 + // let b = 1 # comment + let input = b"let a = ls | where name == 1 \n let b = 1 # comment"; + + let lite_block = lite_parse_helper(input)?; + + assert_eq!(lite_block.block.len(), 2); + assert_eq!(lite_block.block[0].commands.len(), 2); + assert_eq!(lite_block.block[1].commands.len(), 1); + + assert_eq!( + lite_block.block[1].commands[0].comments[0], + Span { start: 41, end: 50 } + ); + + Ok(()) +} diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs new file mode 100644 index 0000000000..d524d422e1 --- /dev/null +++ b/crates/nu-parser/tests/test_parser.rs @@ -0,0 +1,128 @@ +use nu_parser::*; +use nu_parser::{ParseError, ParserState, Signature}; + +#[test] +pub fn parse_int() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let (block, err) = working_set.parse_source(b"3", true); + + assert!(err.is_none()); + assert!(block.len() == 1); + assert!(matches!( + block[0], + Statement::Expression(Expression { + expr: Expr::Int(3), + .. + }) + )); +} + +#[test] +pub fn parse_call() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); + working_set.add_decl(sig.into()); + + let (block, err) = working_set.parse_source(b"foo", true); + + assert!(err.is_none()); + assert!(block.len() == 1); + + match &block[0] { + Statement::Expression(Expression { + expr: Expr::Call(call), + .. + }) => { + assert_eq!(call.decl_id, 0); + } + _ => panic!("not a call"), + } +} + +#[test] +pub fn parse_call_missing_flag_arg() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); + working_set.add_decl(sig.into()); + + let (_, err) = working_set.parse_source(b"foo --jazz", true); + assert!(matches!(err, Some(ParseError::MissingFlagParam(..)))); +} + +#[test] +pub fn parse_call_missing_short_flag_arg() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')); + working_set.add_decl(sig.into()); + + let (_, err) = working_set.parse_source(b"foo -j", true); + assert!(matches!(err, Some(ParseError::MissingFlagParam(..)))); +} + +#[test] +pub fn parse_call_too_many_shortflag_args() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo") + .named("--jazz", SyntaxShape::Int, "jazz!!", Some('j')) + .named("--math", SyntaxShape::Int, "math!!", Some('m')); + working_set.add_decl(sig.into()); + let (_, err) = working_set.parse_source(b"foo -mj", true); + assert!(matches!( + err, + Some(ParseError::ShortFlagBatchCantTakeArg(..)) + )); +} + +#[test] +pub fn parse_call_unknown_shorthand() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j')); + working_set.add_decl(sig.into()); + let (_, err) = working_set.parse_source(b"foo -mj", true); + assert!(matches!(err, Some(ParseError::UnknownFlag(..)))); +} + +#[test] +pub fn parse_call_extra_positional() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j')); + working_set.add_decl(sig.into()); + let (_, err) = working_set.parse_source(b"foo -j 100", true); + assert!(matches!(err, Some(ParseError::ExtraPositional(..)))); +} + +#[test] +pub fn parse_call_missing_req_positional() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!"); + working_set.add_decl(sig.into()); + let (_, err) = working_set.parse_source(b"foo", true); + assert!(matches!(err, Some(ParseError::MissingPositional(..)))); +} + +#[test] +pub fn parse_call_missing_req_flag() { + let parser_state = ParserState::new(); + let mut working_set = ParserWorkingSet::new(&parser_state); + + let sig = Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None); + working_set.add_decl(sig.into()); + let (_, err) = working_set.parse_source(b"foo", true); + assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..)))); +}