numbat-cli-1.11.0/.cargo_vcs_info.json0000644000000001500000000000100131430ustar { "git": { "sha1": "46f6b0e2943e3b2535eade9f7f277e88e7b10d08" }, "path_in_vcs": "numbat-cli" }numbat-cli-1.11.0/Cargo.lock0000644000001221130000000000100111220ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anstream" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", "windows-sys 0.52.0", ] [[package]] name = "anyhow" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "assert_cmd" version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00ad3f3a942eee60335ab4342358c161ee296829e0d16ff42fc1d6cb07815467" dependencies = [ "anstyle", "bstr", "doc-comment", "predicates", "predicates-core", "predicates-tree", "wait-timeout", ] [[package]] name = "attohttpc" version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "184f5e6cce583a9db6b6f8d772a42cfce5b78e7c3ef26118cec3ce4c8c14969b" dependencies = [ "http", "log", "rustls", "url", "webpki-roots", ] [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bstr" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "regex-automata", "serde", ] [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] [[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.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-targets 0.52.0", ] [[package]] name = "chrono-tz" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91d7b79e99bfaa0d47da0687c43aa3b7381938a62ad3a6498599039321f660b7" dependencies = [ "chrono", "chrono-tz-build", "phf", ] [[package]] name = "chrono-tz-build" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" dependencies = [ "parse-zoneinfo", "phf", "phf_codegen", ] [[package]] name = "clap" version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim 0.10.0", "terminal_size", ] [[package]] name = "clap_derive" version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "clap_lex" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clipboard-win" version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c57002a5d9be777c1ef967e33674dac9ebd310d8893e4e3437b14d5f0f6372cc" dependencies = [ "error-code", ] [[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 = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ "lazy_static", "windows-sys 0.48.0", ] [[package]] name = "core-foundation-sys" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", "redox_users", "windows-sys 0.48.0", ] [[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.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "endian-type" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "error-code" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "281e452d3bad4005426416cdba5ccfd4f5c1280e10099e21db27f7c1c28347fc" [[package]] name = "fd-lock" version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" dependencies = [ "cfg-if", "rustix", "windows-sys 0.52.0", ] [[package]] name = "float-cmp" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ "num-traits", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", "wasi", ] [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] [[package]] name = "home" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "http" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "iana-time-zone" version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "idna" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "itertools" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" 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 = "libc" version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libredox" version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ "bitflags 2.4.2", "libc", "redox_syscall", ] [[package]] name = "linux-raw-sys" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[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.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ "bitflags 2.4.2", "cfg-if", "libc", ] [[package]] name = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num-bigint" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-format" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ "arrayvec", "itoa", ] [[package]] name = "num-integer" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", ] [[package]] name = "num-rational" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-bigint", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] [[package]] name = "numbat" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a54ccd3e33759b0171c20adfa0d8b0d2709fe131067faabcfcc1c35621a30b4b" dependencies = [ "chrono", "chrono-tz", "codespan-reporting", "heck", "iana-time-zone", "itertools", "libc", "num-format", "num-integer", "num-rational", "num-traits", "numbat-exchange-rates", "pretty_dtoa", "rust-embed", "strsim 0.11.0", "thiserror", "unicode-ident", "unicode-width", "walkdir", ] [[package]] name = "numbat-cli" version = "1.11.0" dependencies = [ "anyhow", "assert_cmd", "chrono-tz", "clap", "colored", "dirs", "itertools", "numbat", "predicates", "rustyline", "serde", "terminal_size", "toml", ] [[package]] name = "numbat-exchange-rates" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd1e3c3e4f9f22d0d7cdcb413f01194f6506a302a9029d95deedcd1c25df7718" dependencies = [ "attohttpc", "quick-xml", ] [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "parse-zoneinfo" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" dependencies = [ "regex", ] [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" dependencies = [ "phf_generator", "phf_shared", ] [[package]] name = "phf_generator" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared", "rand", ] [[package]] name = "phf_shared" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ "siphasher", ] [[package]] name = "predicates" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" dependencies = [ "anstyle", "difflib", "float-cmp", "normalize-line-endings", "predicates-core", "regex", ] [[package]] name = "predicates-core" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" [[package]] name = "predicates-tree" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" dependencies = [ "predicates-core", "termtree", ] [[package]] name = "pretty_dtoa" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a239bcdfda2c685fda1add3b4695c06225f50075e3cfb5b954e91545587edff2" dependencies = [ "ryu_floating_decimal", ] [[package]] name = "proc-macro2" version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" dependencies = [ "memchr", ] [[package]] name = "quote" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 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.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "redox_syscall" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", "libredox", "thiserror", ] [[package]] name = "regex" version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "ring" version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", "getrandom", "libc", "spin", "untrusted", "windows-sys 0.48.0", ] [[package]] name = "rust-embed" version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f" dependencies = [ "rust-embed-impl", "rust-embed-utils", "walkdir", ] [[package]] name = "rust-embed-impl" version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", "shellexpand", "syn", "walkdir", ] [[package]] name = "rust-embed-utils" version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" dependencies = [ "sha2", "walkdir", ] [[package]] name = "rustix" version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] [[package]] name = "rustls" version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" dependencies = [ "log", "ring", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-pki-types" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e9d979b3ce68192e42760c7810125eb6cf2ea10efae545a156063e61f314e2a" [[package]] name = "rustls-webpki" version = "0.102.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef4ca26037c909dedb327b48c3327d0ba91d3dd3c4e05dad328f210ffb68e95b" dependencies = [ "ring", "rustls-pki-types", "untrusted", ] [[package]] name = "rustyline" version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" dependencies = [ "bitflags 2.4.2", "cfg-if", "clipboard-win", "fd-lock", "home", "libc", "log", "memchr", "nix", "radix_trie", "rustyline-derive", "unicode-segmentation", "unicode-width", "utf8parse", "winapi", ] [[package]] name = "rustyline-derive" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5af959c8bf6af1aff6d2b463a57f71aae53d1332da58419e30ad8dc7011d951" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "ryu_floating_decimal" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "700de91d5fd6091442d00fdd9ee790af6d4f0f480562b0f5a1e8f59e90aafe73" [[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 = "serde" version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_spanned" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "shellexpand" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" dependencies = [ "dirs", ] [[package]] name = "siphasher" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "smallvec" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "subtle" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", "windows-sys 0.48.0", ] [[package]] name = "termtree" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", "toml_edit", ] [[package]] name = "toml_datetime" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "winnow", ] [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wait-timeout" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ "libc", ] [[package]] name = "walkdir" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "webpki-roots" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de2cfda980f21be5a7ed2eadb3e6fe074d56022bea2cdeb1a62eb220fc04188" dependencies = [ "rustls-pki-types", ] [[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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" 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" [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets 0.52.0", ] [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.0", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ "windows_aarch64_gnullvm 0.52.0", "windows_aarch64_msvc 0.52.0", "windows_i686_gnu 0.52.0", "windows_i686_msvc 0.52.0", "windows_x86_64_gnu 0.52.0", "windows_x86_64_gnullvm 0.52.0", "windows_x86_64_msvc 0.52.0", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" version = "0.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" dependencies = [ "memchr", ] [[package]] name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" numbat-cli-1.11.0/Cargo.toml0000644000000034030000000000100111450ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.70" name = "numbat-cli" version = "1.11.0" authors = ["David Peter "] description = "A statically typed programming language for scientific computations with first class support for physical dimensions and units." homepage = "https://numbat.dev/" readme = "README.md" keywords = [ "language", "compiler", "physics", "units", "calculation", ] categories = [ "command-line-utilities", "science", "mathematics", "compilers", ] license = "MIT OR Apache-2.0" repository = "https://github.com/sharkdp/numbat" [[bin]] name = "numbat" path = "src/main.rs" [dependencies.anyhow] version = "1" [dependencies.chrono-tz] version = "0.8.5" [dependencies.clap] version = "4" features = [ "suggestions", "color", "wrap_help", "derive", ] [dependencies.colored] version = "2" [dependencies.dirs] version = "5" [dependencies.itertools] version = "0.12" [dependencies.numbat] version = "1.11.0" [dependencies.rustyline] version = "13" features = ["derive"] [dependencies.serde] version = "1.0.195" features = ["derive"] [dependencies.terminal_size] version = "0.3.0" [dependencies.toml] version = "0.8.8" features = ["parse"] [dev-dependencies.assert_cmd] version = "2" [dev-dependencies.predicates] version = "3" numbat-cli-1.11.0/Cargo.toml.orig000064400000000000000000000021011046102023000146200ustar 00000000000000[package] name = "numbat-cli" description = "A statically typed programming language for scientific computations with first class support for physical dimensions and units." authors = ["David Peter "] categories = ["command-line-utilities", "science", "mathematics", "compilers"] keywords = ["language", "compiler", "physics", "units", "calculation"] homepage = "https://numbat.dev/" repository = "https://github.com/sharkdp/numbat" version = "1.11.0" edition = "2021" license = "MIT OR Apache-2.0" readme = "../README.md" rust-version = "1.70" [dependencies] anyhow = "1" rustyline = { version = "13", features = ["derive"] } dirs = "5" numbat = { version = "1.11.0", path = "../numbat" } colored = "2" itertools = "0.12" toml = { version = "0.8.8", features = ["parse"] } serde = { version = "1.0.195", features = ["derive"] } terminal_size = "0.3.0" chrono-tz = "0.8.5" [dependencies.clap] version = "4" features = ["suggestions", "color", "wrap_help", "derive"] [dev-dependencies] assert_cmd = "2" predicates = "3" [[bin]] name = "numbat" path = "src/main.rs" numbat-cli-1.11.0/README.md000064400000000000000000000145061046102023000132240ustar 00000000000000
**[Try online!] • [Documentation] • [Tutorial] • [Syntax reference] • [Installation] • [Development]** [Try online!]: https://numbat.dev/ [Features]: #key-features [Documentation]: https://numbat.dev/doc/ [Tutorial]: https://numbat.dev/doc/tutorial.html [Syntax reference]: https://numbat.dev/doc/example-numbat_syntax.html [Installation]: https://numbat.dev/doc/cli-installation.html [Development]: #development *Numbat* is a statically typed programming language for scientific computations
with first class support for physical dimensions and units.
## Key Features *Click to learn more.*
Physical dimensions as types

Numbat has a static type system where physical dimensions like `Length` and `Time` act as types. Definitions of constants and functions can optionally contain type annotations that will be statically enforced. If the types are not specified, they will be inferred (`Speed`, `Money` and `Frequency` in the screenshot). See [this article](https://numbat.dev/doc/type-system.html) to learn more about Numbat's type system.
First-class physical units

Numbat is focused on computations with units. Units are therefore treated as first-class citizens. They can be [entered in various ways](https://numbat.dev/doc/unit-notation.html) (`km/h` or `kilometer/hour`, `GiB` or `gibibytes`, `°` or `degree`, `m²` or `m^2`). New units can be [introduced](https://numbat.dev/doc/unit-definitions.html) on the spot (`unit pixel`). Compatible units can be converted easily [using the `->` operator](https://numbat.dev/doc/unit-conversions.html) (`30 km/h -> mph`, `1 mrad -> degree`, `5 in + 2 ft -> cm`, `27 weeks -> days`). And unit expressions are simplified using various heuristics (`15 km/h * 30 min = 7.5 km`).
Comprehensive standard library

Numbat's [standard library](https://numbat.dev/doc/prelude.html) comes with a large number of physical dimensions and units (SI, US Customary, Imperial, Nautical, Astronomical, Atomic, Nuclear, …). See [this reference page](https://numbat.dev/doc/list-units.html) for a complete overview. It also contains a lot of [mathematical and physical constants](https://numbat.dev/doc/list-constants.html) as well as a large range of [pre-defined functions](https://numbat.dev/doc/list-functions.html).
Strict syntax

Numbat's parser never tries to be "smart" on syntactically incorrect input. This means you will either get a (descriptive) error message, or you can trust the result of your calculation.
Excellent error messages

Numbat aims to provide [descriptive and helpful error messages](https://github.com/sharkdp/numbat/blob/master/assets/numbat-error.png).
Interactive terminal

Numbat has been designed for an interactive use-case with small "one off" computations. Opening the `numbat` interpreter without any arguments starts a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) with a familiar readline interface, including all the usual features like a command history, Ctrl-R search or tab completion.
Modular and customizable

The whole system of physical dimensions and units is specified Numbat's standard library, which is [written in the Numbat language](https://github.com/sharkdp/numbat/tree/master/numbat/modules) itself. It is therefore easily extensible by [providing a `init.nbt` file](https://numbat.dev/doc/cli-customization.html). For example, a single line (`unit bathtub = 150 L`) is usually enough to add a new unit. Users can even choose to write their own `prelude` module, allowing for arbitrary modifications to the unit system.
Assertions

With its static type system, Numbat already enforces correctness of your calculations on a physical dimension level. But some checks can only be made at runtime. Numbat provides an `assert_eq` procedure that allows you to check for exact equality using `assert_eq(12 ft, 1 in)` or approximate equality using `assert_eq(c, 300_000 km/s, 1% × c)`. This can be useful to make sure that intermediate results do not change during a restructuring of your calculation.
Non-features

Numbat is a scientific calculator. It's not a computer algebra system that solves differential equations or computes intergrals. Try [WolframAlpha](http://www.wolframalpha.com/) instead.
There is no graphical user interface with buttons like `x²`, `1/x` or `DEG/RAD`. [Qalculate!](http://qalculate.github.io/) is a fantastic tool that supports both text as well as graphical input.
Numbat supports a huge range of physical units. If you need something even more comprehensive, please consider contributing. Or try [GNU units](https://www.gnu.org/software/units/).

 

 

 

 

## Installation See [this page](https://numbat.dev/doc/cli-installation.html) for details on how to install the native command-line version of Numbat. ## Development Run Numbat CLI ``` cargo run -- ``` Install the CLI version ``` cargo install -f --path numbat-cli ``` Run all tests ``` cargo test ``` ### Working on the `prelude` If you are working on [Numbat's standard library](numbat/modules/), it is convenient to point the `NUMBAT_MODULES_PATH` environment variable to the `numbat/modules/` folder. This way, you don't have to recompile Numbat to see your changes. Alternatively, you can create a symlink from `~/.config/numbat/modules` to the `numbat/modules/` folder in the repository (see [this page](https://numbat.dev/doc/cli-customization.html#module-paths) for the standard paths on other operating systems). ## Contact us To contact us, either [open a GitHub issue](https://github.com/sharkdp/numbat/issues/new/choose) or [discussion](https://github.com/sharkdp/numbat/discussions), or pop into `#numbat` on [Libera.Chat](https://libera.chat) ([link to webchat](https://web.libera.chat/gamja/#numbat)). numbat-cli-1.11.0/src/ansi_formatter.rs000064400000000000000000000020471046102023000161140ustar 00000000000000use numbat::markup::{FormatType, FormattedString, Formatter, Markup}; use colored::Colorize; pub struct ANSIFormatter; impl Formatter for ANSIFormatter { fn format_part( &self, FormattedString(_output_type, format_type, text): &FormattedString, ) -> String { (match format_type { FormatType::Whitespace => text.normal(), FormatType::Emphasized => text.bold(), FormatType::Dimmed => text.dimmed(), FormatType::Text => text.normal(), FormatType::String => text.green(), FormatType::Keyword => text.magenta(), FormatType::Value => text.yellow(), FormatType::Unit => text.cyan(), FormatType::Identifier => text.normal(), FormatType::TypeIdentifier => text.blue().italic(), FormatType::Operator => text.bold(), FormatType::Decorator => text.green(), }) .to_string() } } pub fn ansi_format(m: &Markup, indent: bool) -> String { ANSIFormatter {}.format(m, indent) } numbat-cli-1.11.0/src/completer.rs000064400000000000000000000106621046102023000150730ustar 00000000000000use std::sync::{Arc, Mutex}; use numbat::{unicode_input::UNICODE_INPUT, Context}; use rustyline::{ self, completion::{extract_word, Completer, Pair}, }; pub struct NumbatCompleter { pub context: Arc>, pub modules: Vec, pub all_timezones: Vec<&'static str>, } impl Completer for NumbatCompleter { type Candidate = Pair; fn complete( &self, line: &str, pos: usize, _: &rustyline::Context<'_>, ) -> rustyline::Result<(usize, Vec)> { for (patterns, replacement) in UNICODE_INPUT { for pattern in *patterns { let backslash_pattern = format!("\\{}", pattern); if line[..pos].ends_with(&backslash_pattern) { return Ok(( pos - (1 + pattern.len()), vec![Pair { display: backslash_pattern.to_string(), replacement: replacement.to_string(), }], )); } } } if line.starts_with("use ") { return Ok(( 0, self.modules .iter() .map(|m| { let line = format!("use {m}"); Pair { display: m.to_string(), replacement: line, } }) .filter(|p| p.replacement.starts_with(line)) .collect(), )); } else if line.starts_with("list ") || line.starts_with("ls ") { let command = if line.starts_with("list ") { "list" } else { "ls" }; return Ok(( 0, ["functions", "dimensions", "units", "variables"] .iter() .map(|category| { let line = format!("{command} {category}"); Pair { display: category.to_string(), replacement: line, } }) .filter(|p| p.replacement.starts_with(line)) .collect(), )); } // does it look like we're tab-completing a timezone? let complete_tz = line.find("tz(").and_then(|convert_pos| { if let Some(quote_pos) = line.rfind('"') { if quote_pos > convert_pos && pos > quote_pos { return Some(quote_pos + 1); } } None }); if let Some(pos_word) = complete_tz { let word_part = &line[pos_word..]; let matches = self .all_timezones .iter() .filter(|tz| tz.starts_with(word_part)) .collect::>(); let append_closing_quote = matches.len() <= 1; return Ok(( pos_word, matches .into_iter() .map(|tz| Pair { display: tz.to_string(), replacement: if append_closing_quote { format!("{tz}\"") } else { tz.to_string() }, }) .collect(), )); } let (pos_word, word_part) = extract_word(line, pos, None, |c| { // TODO: we could use is_identifier_char here potentially match c { c if c.is_alphanumeric() => false, '_' => false, _ => true, } }); // don't add an opening paren if we're completing after a reverse function call // or when completing conversion functions let add_paren = !["//", "->", "→", "➞", "to"] .iter() .any(|&s| line[..pos].contains(s)); let candidates = self .context .lock() .unwrap() .get_completions_for(word_part, add_paren); Ok(( pos_word, candidates .map(|w| Pair { display: w.to_string(), replacement: w.to_string(), }) .collect(), )) } } numbat-cli-1.11.0/src/config.rs000064400000000000000000000034251046102023000143450ustar 00000000000000use clap::ValueEnum; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, PartialEq, Eq, Default, Debug, Clone, Copy, ValueEnum)] #[serde(rename_all = "kebab-case")] pub enum IntroBanner { #[default] Long, Short, Off, } #[derive(Debug, Clone, Copy, PartialEq, ValueEnum, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum PrettyPrintMode { Always, Never, Auto, } #[derive(Serialize, Deserialize, PartialEq, Eq, Default)] #[serde(rename_all = "kebab-case")] pub enum ExchangeRateFetchingPolicy { /// Always fetch exchange rates in the background when the application is started #[default] OnStartup, /// Fetch exchange rates when a currency symbol is used OnFirstUse, /// Never fetch exchange rates Never, } #[derive(Serialize, Deserialize)] #[serde(rename_all = "kebab-case", default, deny_unknown_fields)] #[derive(Default)] pub struct ExchangeRateConfig { pub fetching_policy: ExchangeRateFetchingPolicy, } #[derive(Serialize, Deserialize)] #[serde(rename_all = "kebab-case", default, deny_unknown_fields)] pub struct Config { pub intro_banner: IntroBanner, pub prompt: String, pub pretty_print: PrettyPrintMode, #[serde(skip)] pub enter_repl: bool, #[serde(skip_serializing)] pub load_prelude: bool, #[serde(skip_serializing)] pub load_user_init: bool, pub exchange_rates: ExchangeRateConfig, } impl Default for Config { fn default() -> Self { Self { prompt: ">>> ".to_owned(), intro_banner: IntroBanner::default(), pretty_print: PrettyPrintMode::Auto, load_prelude: true, load_user_init: true, exchange_rates: Default::default(), enter_repl: true, } } } numbat-cli-1.11.0/src/highlighter.rs000064400000000000000000000032641046102023000153770ustar 00000000000000use colored::Colorize; use numbat::keywords::KEYWORDS; use numbat::{markup, Context}; use rustyline::{highlight::Highlighter, CompletionType}; use std::{ borrow::Cow, sync::{Arc, Mutex}, }; use crate::ansi_formatter::ansi_format; pub struct NumbatHighlighter { pub context: Arc>, } impl Highlighter for NumbatHighlighter { fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> { Cow::Borrowed(line) } fn highlight_prompt<'b, 's: 'b, 'p: 'b>( &self, prompt: &'p str, _default: bool, ) -> Cow<'b, str> { Cow::Owned(format!("{}", prompt.bold())) } fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { Cow::Borrowed(hint) } fn highlight_candidate<'c>( &self, candidate: &'c str, _completion: CompletionType, ) -> Cow<'c, str> { let ctx = self.context.lock().unwrap(); if ctx.variable_names().any(|n| n == candidate) || ctx.function_names().any(|n| format!("{}(", n) == candidate) { Cow::Owned(ansi_format(&markup::identifier(candidate), false)) } else if ctx .unit_names() .iter() .any(|un| un.iter().any(|n| n == candidate)) { Cow::Owned(ansi_format(&markup::unit(candidate), false)) } else if ctx.dimension_names().iter().any(|n| n == candidate) { Cow::Owned(ansi_format(&markup::type_identifier(candidate), false)) } else if KEYWORDS.iter().any(|k| k == &candidate) { Cow::Owned(ansi_format(&markup::keyword(candidate), false)) } else { Cow::Borrowed(candidate) } } } numbat-cli-1.11.0/src/main.rs000064400000000000000000000522511046102023000140250ustar 00000000000000mod ansi_formatter; mod completer; mod config; mod highlighter; use ansi_formatter::ansi_format; use completer::NumbatCompleter; use config::{Config, ExchangeRateFetchingPolicy, IntroBanner, PrettyPrintMode}; use highlighter::NumbatHighlighter; use itertools::Itertools; use numbat::diagnostic::ErrorDiagnostic; use numbat::help::help_markup; use numbat::markup as m; use numbat::module_importer::{BuiltinModuleImporter, ChainedImporter, FileSystemImporter}; use numbat::pretty_print::PrettyPrint; use numbat::resolver::CodeSource; use numbat::{Context, NumbatError}; use numbat::{InterpreterSettings, NameResolutionError}; use anyhow::{bail, Context as AnyhowContext, Result}; use clap::Parser; use rustyline::config::Configurer; use rustyline::{ self, error::ReadlineError, history::DefaultHistory, Completer, Editor, Helper, Hinter, Validator, }; use rustyline::{EventHandler, Highlighter, KeyCode, KeyEvent, Modifiers}; use std::io::IsTerminal; use std::path::PathBuf; use std::sync::{Arc, Mutex}; use std::{fs, thread}; #[derive(Debug, PartialEq, Eq)] pub enum ExitStatus { Success, Error, } type ControlFlow = std::ops::ControlFlow; #[derive(Parser, Debug)] #[command(version, about, name("numbat"), max_term_width = 90)] struct Args { /// Path to source file with Numbat code. If none is given, an interactive /// session is started. file: Option, /// Evaluate a single expression. Can be specified multiple times to evaluate several expressions in sequence. #[arg( short, long, value_name = "CODE", action = clap::ArgAction::Append )] expression: Option>, /// Enter interactive session after running a numbat script or expression #[arg(short, long)] inspect_interactively: bool, /// Do not load the user configuration file. #[arg(long, hide_short_help = true)] no_config: bool, /// Do not load the prelude with predefined physical dimensions and units. This implies --no-init. #[arg(long, hide_short_help = true)] no_prelude: bool, /// Do not load the user init file. #[arg(long, hide_short_help = true)] no_init: bool, /// Whether or not to pretty-print every input expression. #[arg(long, value_name = "WHEN")] pretty_print: Option, /// What kind of intro banner to show (if any). #[arg(long, value_name = "MODE")] intro_banner: Option, /// Generate a default configuration file #[arg(long, hide_short_help = true)] generate_config: bool, /// Turn on debug mode and print disassembler output (hidden, mainly for development) #[arg(long, short, hide = true)] debug: bool, } #[derive(Debug, Clone, Copy, PartialEq)] enum ExecutionMode { Normal, Interactive, } impl ExecutionMode { fn exit_status_in_case_of_error(&self) -> ControlFlow { if matches!(self, ExecutionMode::Normal) { ControlFlow::Break(ExitStatus::Error) } else { ControlFlow::Continue(()) } } } #[derive(Completer, Helper, Hinter, Validator, Highlighter)] struct NumbatHelper { #[rustyline(Completer)] completer: NumbatCompleter, #[rustyline(Highlighter)] highlighter: NumbatHighlighter, } struct Cli { config: Config, context: Arc>, file: Option, expression: Option>, } impl Cli { fn new(args: Args) -> Result { let user_config_path = Self::get_config_path().join("config.toml"); let mut config = if args.no_config { Config::default() } else if let Ok(contents) = fs::read_to_string(&user_config_path) { toml::from_str(&contents).context(format!( "Error while loading {}", user_config_path.to_string_lossy() ))? } else { Config::default() }; config.load_prelude &= !args.no_prelude; config.load_user_init &= !(args.no_prelude || args.no_init); config.intro_banner = args.intro_banner.unwrap_or(config.intro_banner); config.pretty_print = args.pretty_print.unwrap_or(config.pretty_print); config.enter_repl = (args.file.is_none() && args.expression.is_none()) || args.inspect_interactively; let mut fs_importer = FileSystemImporter::default(); for path in Self::get_modules_paths() { fs_importer.add_path(path); } let importer = ChainedImporter::new( Box::new(fs_importer), Box::::default(), ); let mut context = Context::new(importer); context.set_debug(args.debug); context.set_terminal_width( terminal_size::terminal_size().map(|(terminal_size::Width(w), _)| w as usize), ); Ok(Self { context: Arc::new(Mutex::new(context)), config, file: args.file, expression: args.expression, }) } fn run(&mut self) -> Result<()> { if self.config.load_prelude { let result = self.parse_and_evaluate( "use prelude", CodeSource::Internal, ExecutionMode::Normal, PrettyPrintMode::Never, ); if result.is_break() { bail!("Interpreter error in Prelude code") } } if self.config.load_user_init { let user_init_path = Self::get_config_path().join("init.nbt"); if let Ok(user_init_code) = fs::read_to_string(&user_init_path) { let result = self.parse_and_evaluate( &user_init_code, CodeSource::File(user_init_path), ExecutionMode::Normal, PrettyPrintMode::Never, ); if result.is_break() { bail!("Interpreter error in user initialization code") } } } if self.config.load_prelude && self.config.exchange_rates.fetching_policy != ExchangeRateFetchingPolicy::Never { self.context .lock() .unwrap() .load_currency_module_on_demand(true); } let mut code_and_source = Vec::new(); if let Some(ref path) = self.file { code_and_source.push(( (fs::read_to_string(path).context(format!( "Could not load source file '{}'", path.to_string_lossy() ))?), CodeSource::File(path.clone()), )); }; if let Some(expressions) = &self.expression { code_and_source.push((expressions.iter().join("\n"), CodeSource::Text)); } let mut run_result = Ok(()); if !code_and_source.is_empty() { for (code, code_source) in code_and_source { let result = self.parse_and_evaluate( &code, code_source, ExecutionMode::Normal, self.config.pretty_print, ); let result_status = match result { std::ops::ControlFlow::Continue(()) => Ok(()), std::ops::ControlFlow::Break(_) => { bail!("Interpreter stopped") } }; run_result = run_result.and(result_status); } } if self.config.enter_repl { let mut currency_fetch_thread = if self.config.load_prelude && self.config.exchange_rates.fetching_policy == ExchangeRateFetchingPolicy::OnStartup { Some(thread::spawn(move || { numbat::Context::prefetch_exchange_rates(); })) } else { None }; let repl_result = self.repl(); if let Some(thread) = currency_fetch_thread.take() { let _ = thread.join(); } run_result = run_result.and(repl_result); } run_result } fn repl(&mut self) -> Result<()> { let interactive = std::io::stdin().is_terminal(); let history_path = self.get_history_path()?; let mut rl = Editor::::new()?; rl.set_max_history_size(1000) .context("Error while configuring history size")?; rl.set_completion_type(rustyline::CompletionType::List); rl.set_helper(Some(NumbatHelper { completer: NumbatCompleter { context: self.context.clone(), modules: self.context.lock().unwrap().list_modules().collect(), all_timezones: chrono_tz::TZ_VARIANTS.map(|v| v.name()).into(), }, highlighter: NumbatHighlighter { context: self.context.clone(), }, })); rl.bind_sequence( KeyEvent(KeyCode::Enter, Modifiers::ALT), EventHandler::Simple(rustyline::Cmd::Newline), ); rl.load_history(&history_path).ok(); if interactive { match self.config.intro_banner { IntroBanner::Long => { println!(); println!( " █▄░█ █░█ █▀▄▀█ █▄▄ ▄▀█ ▀█▀ Numbat {}", env!("CARGO_PKG_VERSION") ); println!( " █░▀█ █▄█ █░▀░█ █▄█ █▀█ ░█░ {}", env!("CARGO_PKG_HOMEPAGE") ); println!(); } IntroBanner::Short => { println!("Numbat {}", env!("CARGO_PKG_VERSION")); } IntroBanner::Off => {} } } let result = self.repl_loop(&mut rl, interactive); if interactive { rl.save_history(&history_path).context(format!( "Error while saving history to '{}'", history_path.to_string_lossy() ))?; } result } fn repl_loop( &mut self, rl: &mut Editor, interactive: bool, ) -> Result<()> { loop { let readline = rl.readline(&self.config.prompt); match readline { Ok(line) => { if !line.trim().is_empty() { rl.add_history_entry(&line)?; match line.trim() { "list" | "ls" => { println!( "{}", ansi_format( &self.context.lock().unwrap().print_environment(), false ) ); } "list functions" | "ls functions" => { println!( "{}", ansi_format( &self.context.lock().unwrap().print_functions(), false ) ); } "list dimensions" | "ls dimensions" => { println!( "{}", ansi_format( &self.context.lock().unwrap().print_dimensions(), false ) ); } "list variables" | "ls variables" => { println!( "{}", ansi_format( &self.context.lock().unwrap().print_variables(), false ) ); } "list units" | "ls units" => { println!( "{}", ansi_format(&self.context.lock().unwrap().print_units(), false) ); } "clear" => { rl.clear_screen()?; } "quit" | "exit" => { return Ok(()); } "help" | "?" => { let help = help_markup(); print!("{}", ansi_format(&help, true)); // currently, the ansi formatter adds indents // _after_ each newline and so we need to manually // add an extra blank line to absorb this indent println!(); } _ => { if let Some(keyword) = line.strip_prefix("info ") { let help = self .context .lock() .unwrap() .print_info_for_keyword(keyword.trim()); println!("{}", ansi_format(&help, true)); continue; } let result = self.parse_and_evaluate( &line, CodeSource::Text, if interactive { ExecutionMode::Interactive } else { ExecutionMode::Normal }, self.config.pretty_print, ); match result { std::ops::ControlFlow::Continue(()) => {} std::ops::ControlFlow::Break(ExitStatus::Success) => { return Ok(()); } std::ops::ControlFlow::Break(ExitStatus::Error) => { bail!("Interpreter stopped due to error") } } } } } } Err(ReadlineError::Interrupted) => {} Err(ReadlineError::Eof) => { return Ok(()); } Err(err) => { bail!(err); } } } } #[must_use] fn parse_and_evaluate( &mut self, input: &str, code_source: CodeSource, execution_mode: ExecutionMode, pretty_print_mode: PrettyPrintMode, ) -> ControlFlow { let to_be_printed: Arc>> = Arc::new(Mutex::new(vec![])); let to_be_printed_c = to_be_printed.clone(); let mut settings = InterpreterSettings { print_fn: Box::new(move |s: &m::Markup| { to_be_printed_c.lock().unwrap().push(s.clone()); }), }; let (result, registry) = { let mut ctx = self.context.lock().unwrap(); let registry = ctx.dimension_registry().clone(); // TODO: get rid of this clone ( ctx.interpret_with_settings(&mut settings, input, code_source), registry, ) }; let interactive = execution_mode == ExecutionMode::Interactive; let pretty_print = match pretty_print_mode { PrettyPrintMode::Always => true, PrettyPrintMode::Never => false, PrettyPrintMode::Auto => interactive, }; match result { Ok((statements, interpreter_result)) => { if interactive || pretty_print { println!(); } if pretty_print { for statement in &statements { let repr = ansi_format(&statement.pretty_print(), true); println!("{}", repr); println!(); } } let to_be_printed = to_be_printed.lock().unwrap(); for s in to_be_printed.iter() { println!("{}", ansi_format(s, interactive)); } if interactive && !to_be_printed.is_empty() { println!(); } let result_markup = interpreter_result.to_markup( statements.last(), ®istry, interactive || pretty_print, interactive || pretty_print, ); print!("{}", ansi_format(&result_markup, false)); if (interactive || pretty_print) && interpreter_result.is_value() { println!(); } ControlFlow::Continue(()) } Err(NumbatError::ResolverError(e)) => { self.print_diagnostic(e.clone()); execution_mode.exit_status_in_case_of_error() } Err(NumbatError::NameResolutionError( e @ (NameResolutionError::IdentifierClash { .. } | NameResolutionError::ReservedIdentifier(_)), )) => { self.print_diagnostic(e); execution_mode.exit_status_in_case_of_error() } Err(NumbatError::TypeCheckError(e)) => { self.print_diagnostic(e); execution_mode.exit_status_in_case_of_error() } Err(NumbatError::RuntimeError(e)) => { self.print_diagnostic(e); execution_mode.exit_status_in_case_of_error() } } } fn print_diagnostic(&mut self, error: impl ErrorDiagnostic) { self.context.lock().unwrap().print_diagnostic(error) } fn get_config_path() -> PathBuf { let config_dir = dirs::config_dir().unwrap_or_else(|| PathBuf::from(".")); config_dir.join("numbat") } fn get_modules_paths() -> Vec { let mut paths = vec![]; if let Some(modules_path) = std::env::var_os("NUMBAT_MODULES_PATH") { for path in modules_path.to_string_lossy().split(':') { paths.push(path.into()); } } paths.push(Self::get_config_path().join("modules")); // We read the value of this environment variable at compile time to // allow package maintainers to control the system-wide module path // for Numbat. if let Some(system_module_path) = option_env!("NUMBAT_SYSTEM_MODULE_PATH") { if !system_module_path.is_empty() { paths.push(system_module_path.into()); } } else if cfg!(unix) { paths.push("/usr/share/numbat/modules".into()); } else { paths.push("C:\\Program Files\\numbat\\modules".into()); } paths } fn get_history_path(&self) -> Result { let data_dir = dirs::data_dir() .unwrap_or_else(|| PathBuf::from(".")) .join("numbat"); fs::create_dir_all(&data_dir).ok(); Ok(data_dir.join("history")) } } fn generate_config() -> Result<()> { let config_folder_path = Cli::get_config_path(); let config_file_path = config_folder_path.join("config.toml"); if config_file_path.exists() { bail!( "The file '{}' exists already.", config_file_path.to_string_lossy() ); } std::fs::create_dir_all(&config_folder_path).context(format!( "Error while creating folder '{}'", config_folder_path.to_string_lossy() ))?; let config = Config::default(); let content = toml::to_string(&config).context("Error while creating TOML from config")?; std::fs::write(&config_file_path, content)?; println!( "A default configuration has been written to '{}'.", config_file_path.to_string_lossy() ); println!("Open the file in a text editor. Modify whatever you want to change and remove the other fields"); Ok(()) } fn main() { let args = Args::parse(); if args.generate_config { if let Err(e) = generate_config() { eprintln!("{:#}", e); std::process::exit(1); } std::process::exit(0); } if let Err(e) = Cli::new(args).and_then(|mut cli| cli.run()) { eprintln!("{:#}", e); std::process::exit(1); } } numbat-cli-1.11.0/tests/examples/parser_error.nbt000064400000000000000000000000071046102023000201260ustar 00000000000000(3+4)) numbat-cli-1.11.0/tests/examples/pendulum.nbt000064400000000000000000000001761046102023000172610ustar 00000000000000fn oscillation_time(length: Length) -> Time = 2 pi × sqrt(length / g0) assert_eq(oscillation_time(30 cm), 1.1 s, 0.1 s) numbat-cli-1.11.0/tests/examples/print.nbt000064400000000000000000000001311046102023000165530ustar 00000000000000print(1) print(2 meter) print("hello world") print("pi = {pi}") print("1 + 2 = {1 + 2}") numbat-cli-1.11.0/tests/integration.rs000064400000000000000000000073631046102023000160030ustar 00000000000000use std::path::Path; use assert_cmd::Command; use predicates::boolean::PredicateBooleanExt; fn numbat() -> Command { let module_path = Path::new(&std::env::var_os("CARGO_MANIFEST_DIR").unwrap()) .parent() .unwrap() .join("numbat") .join("modules"); std::env::set_var("NUMBAT_MODULES_PATH", module_path); let mut cmd = Command::cargo_bin("numbat").unwrap(); cmd.arg("--no-init"); cmd.arg("--no-config"); cmd } #[test] fn pass_expression_on_command_line() { numbat() .arg("--expression") .arg("2 meter + 3 meter") .assert() .success() .stdout(predicates::str::contains("5 m")); numbat() .arg("-e") .arg("let x = 2") .arg("-e") .arg("x^3") .assert() .success() .stdout(predicates::str::contains("8")); numbat() .arg("--expression") .arg("2 +/ 3") .assert() .stderr(predicates::str::contains("while parsing")); numbat() .arg("--expression") .arg("2 meter + 3 second") .assert() .failure() .stderr(predicates::str::contains("while type checking")); numbat() .arg("--expression") .arg("1/0") .assert() .failure() .stderr(predicates::str::contains("runtime error")); numbat() .arg("--expression") .arg("type(2 m/s)") .assert() .success() .stdout(predicates::str::contains("Length / Time")); } #[test] fn read_code_from_file() { numbat() .arg("tests/examples/pendulum.nbt") .assert() .success(); numbat() .arg("tests/examples/parser_error.nbt") .assert() .failure() .stderr(predicates::str::contains("while parsing")); } #[test] fn process_code_from_file_and_cli_expression() { numbat() .arg("tests/examples/pendulum.nbt") .arg("--expression") .arg("oscillation_time(20cm)") .assert() .success(); numbat() .arg("tests/examples/pendulum.nbt") .arg("--expression") .arg("oscillation_time(20kg)") .assert() .failure() .stderr(predicates::str::contains("while type checking")); } #[test] fn print_calls() { numbat() .arg("tests/examples/print.nbt") .assert() .success() .stdout(predicates::str::contains( "1 \n2 m\nhello world\npi = 3.14159\n1 + 2 = 3\n", )); } #[test] fn without_prelude() { numbat() .arg("--no-prelude") .arg("--expression") .arg("2.1 + 3.1") .assert() .success() .stdout(predicates::str::contains("5.2")); numbat() .arg("--no-prelude") .arg("--expression") .arg("1 meter") .assert() .failure() .stderr(predicates::str::contains("unknown identifier")); } #[test] fn pretty_printing() { numbat() .arg("--pretty-print=always") .arg("--expression") .arg("let v=30km/h") .assert() .success() .stdout(predicates::str::contains( "let v: Velocity = 30 kilometre / hour", )); } #[test] fn help_text() { numbat() .write_stdin("help") .assert() .success() .stdout(predicates::str::contains( "Energy of red photons: 1.87855 eV", )); } #[test] fn info_text() { numbat().write_stdin("info g0").assert().success().stdout( predicates::str::contains("Standard acceleration of gravity on earth") .and(predicates::str::contains("9.80665 m/s²")), ); numbat().write_stdin("info C").assert().success().stdout( predicates::str::contains("Coulomb").and(predicates::str::contains("1 coulomb = ")), ); }