diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-13 19:06:31 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-13 19:06:31 +0200 |
commit | 0f00400df98327dc01681567dc2313a9c6e57953 (patch) | |
tree | ce4a6af92cc6026b16a95945eb05f394933ec2aa | |
parent | ab36c1b5178ee0e7934b1c5cdcf2ccfccc3514bb (diff) |
Remove the Rust version.
-rw-r--r-- | Cargo.lock | 1012 | ||||
-rw-r--r-- | Cargo.toml | 22 | ||||
-rw-r--r-- | src/main.rs | 844 |
3 files changed, 0 insertions, 1878 deletions
diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index feca255..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1012 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "bitflags" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "cfg-if" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "clipboard-win" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" -dependencies = [ - "error-code", -] - -[[package]] -name = "color-eyre" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" -dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error", -] - -[[package]] -name = "color-spantrace" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" -dependencies = [ - "once_cell", - "owo-colors", - "tracing-core", - "tracing-error", -] - -[[package]] -name = "convert_case" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "crossterm" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" -dependencies = [ - "bitflags", - "crossterm_winapi", - "derive_more", - "document-features", - "mio", - "parking_lot", - "rustix", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - -[[package]] -name = "csv" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" -dependencies = [ - "memchr", -] - -[[package]] -name = "derive_more" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "document-features" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" -dependencies = [ - "litrs", -] - -[[package]] -name = "dosage" -version = "0.1.0" -dependencies = [ - "color-eyre", - "crossterm", - "eyre", - "prettytable-rs", - "regex", - "rustyline", - "thiserror 2.0.12", -] - -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "errno" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "error-code" -version = "3.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fd-lock" -version = "4.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" -dependencies = [ - "cfg-if", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.174" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" - -[[package]] -name = "libredox" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - -[[package]] -name = "litrs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" - -[[package]] -name = "lock_api" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.59.0", -] - -[[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.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "owo-colors" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" - -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "prettytable-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" -dependencies = [ - "csv", - "encode_unicode", - "is-terminal", - "lazy_static", - "term", - "unicode-width 0.1.14", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -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 = "redox_syscall" -version = "0.5.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7251471db004e509f4e75a62cca9435365b5ec7bcdff530d612ac7c87c44a792" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom", - "libredox", - "thiserror 1.0.69", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - -[[package]] -name = "rustix" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.60.2", -] - -[[package]] -name = "rustversion" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - -[[package]] -name = "rustyline" -version = "16.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fd9ca5ebc709e8535e8ef7c658eb51457987e48c98ead2be482172accc408d" -dependencies = [ - "bitflags", - "cfg-if", - "clipboard-win", - "fd-lock", - "home", - "libc", - "log", - "memchr", - "nix", - "radix_trie", - "unicode-segmentation", - "unicode-width 0.2.1", - "utf8parse", - "windows-sys 0.59.0", -] - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-error" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" -dependencies = [ - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" -dependencies = [ - "sharded-slab", - "thread_local", - "tracing-core", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-width" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[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-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.2", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 4ba529e..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "dosage" -version = "0.1.0" -edition = "2024" - -[profile.release] -lto = true -opt-level = "z" -strip = true -codegen-units = 1 -#panic = "abort" - -[dependencies] -color-eyre = "0.6" -eyre = "0.6" -thiserror = "2" -crossterm = "0.29.0" -prettytable-rs = "0.10.0" -rustyline = "16" -regex = "1.11.1" -#crossbeam = "0.8.4" -#termwiz = "0.23" diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 8b9229e..0000000 --- a/src/main.rs +++ /dev/null @@ -1,844 +0,0 @@ -use crossterm::{cursor, execute, terminal}; -use eyre::{Result, bail}; -use regex::Regex; -use rustyline::DefaultEditor; -use rustyline::error::ReadlineError; -use std::collections::{LinkedList, VecDeque}; -use std::io; -use std::io::Write; -use std::path::{Component, Path, PathBuf}; -use std::sync::mpsc::{Receiver, SyncSender, sync_channel}; -use std::thread::spawn; - -const STDOUT_BUFFER_SIZE: usize = 1024; -const STDERR_BUFFER_SIZE: usize = 1024; - -fn main() -> Result<()> { - color_eyre::install()?; - - let mut line_editor = DefaultEditor::new()?; - let mut prompt_spec = "$p$g"; - - loop { - let cwd = std::env::current_dir()?; - let full_cwd = format_path(&cwd); - let mut interpolated_prompt = prompt_spec.replace("$p", &full_cwd).replace("$g", ">"); - interpolated_prompt.push_str(" "); - - let line = match line_editor.readline(&interpolated_prompt) { - Ok(line) => line, - Err(ReadlineError::Eof) => break, - Err(err) => return Err(err.into()), - }; - - let Ok(command) = Command::parse(&line) else { - eprintln!("unrecognized command: {}", line); - continue; - }; - - line_editor.add_history_entry(&line)?; - let Ok(CommandReceivers { - stdout, - stderr, - status, - }) = command.run() - else { - eprintln!("unimplemented command: {}", line); - continue; - }; - - // print stdout, stderr interleaved until status produces something - let stdout_writer = spawn(move || { - loop { - let Ok(bytes) = stdout.recv() else { - break; - }; - let mut out = io::stderr(); - out.write_all(bytes.as_slice()) - .expect("stdout write failed"); - out.flush().expect("stdout flush failed"); - } - }); - - let stderr_writer = spawn(move || { - loop { - let Ok(bytes) = stderr.recv() else { - break; - }; - let mut out = io::stderr(); - out.write_all(bytes.as_slice()) - .expect("stderr write failed"); - out.flush().expect("stdout flush failed"); - } - }); - - stdout_writer.join().expect("stdout writer thread failed"); - stderr_writer.join().expect("stderr writer thread failed"); - - let command_result = status - .recv() - .expect("failed to receive exit status from command"); - - match command_result { - CommandStatus::ExitShell => break, - CommandStatus::Code(_) => {} - } - } - - Ok(()) -} - -/// Turns "/home/mulk/foo/longfilenames/excellent.text" into "C:\\HOME\\MULK\\FOO\\LONGFILE~1\\EXCELL~1.TEX" -fn format_path(p: &Path) -> String { - use std::path::Component::*; - - let mut prefix: Option<String> = None; - let mut components = Vec::new(); - - for component in p.components() { - match component { - Normal(c) => { - let s = c.to_string_lossy().to_uppercase(); - let s_parts: Vec<&str> = s.splitn(2, '.').collect(); - - let mut name: String; - let mut ext: Option<String>; - if s_parts.len() == 1 { - name = s.clone(); - ext = None; - } else { - name = s_parts[0].into(); - ext = Some(s_parts[1].into()); - } - - let mut result = String::new(); - - if name.len() > 8 || ext.as_ref().map_or(false, |e| e.len() > 3) { - name = name.chars().take(6).collect::<String>(); - name.push_str("~1"); - } - result.push_str(&name.to_uppercase()); - - if let Some(mut e) = ext { - if e.len() > 3 { - e = e.chars().take(3).collect::<String>(); - } - result.push_str("."); - result.push_str(&e.to_uppercase()); - } - - components.push(result); - } - - Prefix(c) => prefix = Some(component.as_os_str().to_string_lossy().to_uppercase()), - - RootDir => { - if prefix.is_none() { - prefix = Some("C:".into()) - } - components.push("".into()); - } - - CurDir => components.push(".".into()), - - ParentDir => components.push("..".into()), - } - } - - let mut result = String::new(); - if let Some(p) = prefix { - result.push_str(&p) - }; - result.push_str(&components.join("\\")); - result -} - -#[derive(Debug)] -enum FileSpec { - Con, - Lpt1, - Lpt2, - Lpt3, - Prn, - Path(PathBuf), -} - -#[derive(Debug)] -enum RedirectType { - OutputOverwrite, // > - OutputAppend, // >> - InputFrom, // < -} - -#[derive(Debug)] -struct Redirect { - redirect_type: RedirectType, - target: FileSpec, -} - -#[derive(Debug)] -enum Command { - Pipe { - left: Box<Command>, - right: Box<Command>, - }, - Redirect { - command: Box<Command>, - redirects: Vec<Redirect>, - }, - External { - program: String, - args: Vec<String>, - }, - Builtin(BuiltinCommand), - Empty, -} - -#[derive(Debug)] -enum CommandStatus { - Code(u16), - ExitShell, -} - -struct CommandReceivers { - stdout: Receiver<Vec<u8>>, - stderr: Receiver<Vec<u8>>, - status: Receiver<CommandStatus>, -} - -struct CommandSenders { - stdout: SyncSender<Vec<u8>>, - stderr: SyncSender<Vec<u8>>, - status: SyncSender<CommandStatus>, -} - -struct CommandContext { - senders: CommandSenders, - receivers: CommandReceivers, -} - -impl CommandContext { - fn new() -> Self { - let (sout, rout) = sync_channel(STDOUT_BUFFER_SIZE); - let (serr, rerr) = sync_channel(STDERR_BUFFER_SIZE); - let (sexit, rexit) = sync_channel(1); - - Self { - senders: CommandSenders { - stdout: sout, - stderr: serr, - status: sexit, - }, - receivers: CommandReceivers { - stdout: rout, - stderr: rerr, - status: rexit, - }, - } - } - - fn split(self) -> (CommandSenders, CommandReceivers) { - (self.senders, self.receivers) - } -} - -impl Command { - pub(crate) fn run(&self) -> Result<CommandReceivers> { - use crate::BuiltinCommand::*; - use crate::Command::*; - use crate::CommandStatus::*; - - let (senders, receivers) = CommandContext::new().split(); - let CommandSenders { - stdout, - stderr, - status: status, - } = senders; - - match self { - Empty => { - status.send(Code(0))?; - } - - Builtin(EchoText { message }) => { - stdout.send(message.bytes().collect())?; - stdout.send(b"\n".into())?; - status.send(Code(0))?; - } - - Builtin(Cls) => { - let mut stdout_handle = io::stdout(); - execute!(stdout_handle, terminal::Clear(terminal::ClearType::All))?; - execute!(stdout_handle, cursor::MoveTo(0, 0))?; - status.send(Code(0))?; - } - - Builtin(Exit) => { - status.send(ExitShell)?; - } - - _ => bail!("Command::run not implemented for {:?}", self), - } - - Ok(receivers) - } -} - -#[derive(Debug)] -enum BuiltinCommand { - // File-oriented - Copy { - from: FileSpec, - to: FileSpec, - }, - Deltree { - path: PathBuf, - }, - Dir { - path: PathBuf, - }, - Fc, - Find, - Mkdir { - path: PathBuf, - }, - Move, - Remove { - path: PathBuf, - }, - Rename { - from: FileSpec, - to: FileSpec, - }, - Replace, - Rmdir { - path: PathBuf, - }, - Sort, - Tree { - path: PathBuf, - }, - Type { - file: FileSpec, - }, - Xcopy { - from: FileSpec, - to: FileSpec, - recursive: bool, - }, - - // Shell-oriented - Append, - Chdir { - path: PathBuf, - }, - EchoOff, - EchoOn, - EchoPlain, - EchoText { - message: String, - }, - Exit, - PathGet, - PathSet { - value: String, - }, - PromptGet, - PromptSet { - message: String, - }, - Set { - name: String, - value: String, - }, - Setver, - Ver, - - // Utilities - Date, - Time, - - // Screen-oriented - Cls, - More, - - // Dummies - Verify, - Fastopen, - Smartdrv, - Sizer, - - // For later - Assign, - Attrib, - Chkdsk, - Doskey, - Dosshell, - Edit, - Fasthelp, - Help, - Join, - Mem, - Power, - Subst, - Truename, - - // For much later, if ever - Break, - Chcp, - Ctty, - Defrag, - Diskcopy, - Emm386, - Fdisk, - Format, - Interlnk, - Keyb, - Label, - Mode, - Msav, - Msbackup, - Mscdex, - Msd, - Print, - Qbasic, - Restore, - Scandisk, - Share, - Sys, - Undelete, - Unformat, - Vol, - Vsafe, - - // Scripting - Call, - Choice, - Echo, - For, - Goto, - If, - Pause, - Prompt, - Rem { - message: String, - }, - Shift, -} - -#[derive(Debug, Clone, PartialEq)] -enum Token { - Word(String), - Pipe, - RedirectOut, // > - RedirectAppend, // >> - RedirectIn, // < - Newline, - Eof, -} - -struct Lexer { - input: Vec<char>, - position: usize, - current_char: Option<char>, -} - -impl Lexer { - fn new(input: &str) -> Self { - let chars: Vec<char> = input.chars().collect(); - let current_char = chars.get(0).copied(); - - Self { - input: chars, - position: 0, - current_char, - } - } - - fn advance(&mut self) { - self.position += 1; - self.current_char = self.input.get(self.position).copied(); - } - - fn peek(&self) -> Option<char> { - self.input.get(self.position + 1).copied() - } - - fn skip_whitespace(&mut self) { - while let Some(ch) = self.current_char { - if ch.is_whitespace() && ch != '\n' { - self.advance(); - } else { - break; - } - } - } - - fn read_word(&mut self) -> String { - let mut word = String::new(); - let mut in_quotes = false; - let mut quote_char = '"'; - - while let Some(ch) = self.current_char { - match ch { - // Handle quotes - '"' | '\'' if !in_quotes => { - in_quotes = true; - quote_char = ch; - self.advance(); - }, - ch if in_quotes && ch == quote_char => { - in_quotes = false; - self.advance(); - }, - // Stop at special characters when not in quotes - '|' | '>' | '<' | '\n' if !in_quotes => { - break; - }, - // Stop at whitespace when not in quotes - ch if !in_quotes && ch.is_whitespace() => { - break; - }, - // Regular character - _ => { - word.push(ch); - self.advance(); - } - } - } - - word - } - - fn next_token(&mut self) -> Token { - loop { - match self.current_char { - None => return Token::Eof, - - Some('\n') => { - self.advance(); - return Token::Newline; - }, - - Some(ch) if ch.is_whitespace() => { - self.skip_whitespace(); - continue; - }, - - Some('|') => { - self.advance(); - return Token::Pipe; - }, - - Some('>') => { - self.advance(); - if self.current_char == Some('>') { - self.advance(); - return Token::RedirectAppend; - } else { - return Token::RedirectOut; - } - }, - - Some('<') => { - self.advance(); - return Token::RedirectIn; - }, - - Some(_) => { - let word = self.read_word(); - if word.is_empty() { - // This shouldn't happen, but just in case - self.advance(); - continue; - } - return Token::Word(word); - } - } - } - } - - fn tokenize(&mut self) -> Vec<Token> { - let mut tokens = Vec::new(); - - loop { - let token = self.next_token(); - let is_eof = matches!(token, Token::Eof); - tokens.push(token); - if is_eof { - break; - } - } - - tokens - } -} - -struct Parser { - tokens: Vec<Token>, - position: usize, -} - -impl Parser { - fn new(tokens: Vec<Token>) -> Self { - Self { - tokens, - position: 0, - } - } - - fn current_token(&self) -> &Token { - self.tokens.get(self.position).unwrap_or(&Token::Eof) - } - - fn advance(&mut self) { - if self.position < self.tokens.len() { - self.position += 1; - } - } - - fn expect_word(&mut self) -> Result<String> { - match self.current_token() { - Token::Word(word) => { - let result = word.clone(); - self.advance(); - Ok(result) - }, - token => Err(eyre::eyre!("Expected word, found {:?}", token)), - } - } - - fn parse_command(&mut self) -> Result<Command> { - self.parse_pipeline() - } - - fn parse_pipeline(&mut self) -> Result<Command> { - let mut left = self.parse_redirected_command()?; - - while matches!(self.current_token(), Token::Pipe) { - self.advance(); // consume | - let right = self.parse_redirected_command()?; - left = Command::Pipe { - left: Box::new(left), - right: Box::new(right), - }; - } - - Ok(left) - } - - fn parse_redirected_command(&mut self) -> Result<Command> { - let mut command = self.parse_simple_command()?; - let mut redirects = Vec::new(); - - while matches!(self.current_token(), Token::RedirectOut | Token::RedirectAppend | Token::RedirectIn) { - let redirect_type = match self.current_token() { - Token::RedirectOut => RedirectType::OutputOverwrite, - Token::RedirectAppend => RedirectType::OutputAppend, - Token::RedirectIn => RedirectType::InputFrom, - _ => unreachable!(), - }; - - self.advance(); // consume redirect token - - let target_str = self.expect_word()?; - let target = parse_filespec(&target_str); - - redirects.push(Redirect { - redirect_type, - target, - }); - } - - if redirects.is_empty() { - Ok(command) - } else { - Ok(Command::Redirect { - command: Box::new(command), - redirects, - }) - } - } - - fn parse_simple_command(&mut self) -> Result<Command> { - use BuiltinCommand::*; - use Command::*; - - if matches!(self.current_token(), Token::Eof | Token::Newline) { - return Ok(Empty); - } - - let command_name = self.expect_word()?; - let mut args = Vec::new(); - - // Collect arguments until we hit a special token - while matches!(self.current_token(), Token::Word(_)) { - if let Token::Word(arg) = self.current_token() { - args.push(arg.clone()); - self.advance(); - } - } - - match command_name.to_uppercase().as_str() { - "ECHO" => { - if args.is_empty() { - Ok(Builtin(EchoPlain)) - } else { - match args[0].to_uppercase().as_str() { - "ON" if args.len() == 1 => Ok(Builtin(EchoOn)), - "OFF" if args.len() == 1 => Ok(Builtin(EchoOff)), - _ => Ok(Builtin(EchoText { - message: args.join(" "), - })), - } - } - }, - - "CLS" => Ok(Builtin(Cls)), - - "EXIT" => Ok(Builtin(Exit)), - - "MORE" => Ok(Builtin(More)), - - "VERIFY" => Ok(Builtin(Verify)), - - // File-oriented commands - "COPY" => { - if args.len() >= 2 { - Ok(Builtin(Copy { - from: parse_filespec(&args[0]), - to: parse_filespec(&args[1]), - })) - } else { - Err(eyre::eyre!("COPY requires source and destination")) - } - }, - - "DIR" => Ok(Builtin(Dir { - path: if args.is_empty() { - PathBuf::from(".") - } else { - PathBuf::from(&args[0]) - }, - })), - - "TYPE" => { - if args.is_empty() { - Err(eyre::eyre!("TYPE requires a filename")) - } else { - Ok(Builtin(Type { - file: parse_filespec(&args[0]), - })) - } - }, - - "CD" | "CHDIR" => Ok(Builtin(Chdir { - path: if args.is_empty() { - std::env::current_dir()? - } else { - PathBuf::from(&args[0]) - }, - })), - - "MKDIR" | "MD" => { - if args.is_empty() { - Err(eyre::eyre!("MKDIR requires a directory name")) - } else { - Ok(Builtin(Mkdir { - path: PathBuf::from(&args[0]), - })) - } - }, - - "RMDIR" | "RD" => { - if args.is_empty() { - Err(eyre::eyre!("RMDIR requires a directory name")) - } else { - Ok(Builtin(Rmdir { - path: PathBuf::from(&args[0]), - })) - } - }, - - "DEL" | "ERASE" => { - if args.is_empty() { - Err(eyre::eyre!("DEL requires a filename")) - } else { - Ok(Builtin(Remove { - path: PathBuf::from(&args[0]), - })) - } - }, - - "REM" => Ok(Builtin(Rem { - message: args.join(" "), - })), - - "VER" => Ok(Builtin(Ver)), - - "DATE" => Ok(Builtin(Date)), - - "TIME" => Ok(Builtin(Time)), - - "PATH" => { - if args.is_empty() { - Ok(Builtin(PathGet)) - } else { - Ok(Builtin(PathSet { - value: args.join(" "), - })) - } - }, - - "SET" => { - if args.is_empty() { - Err(eyre::eyre!("SET requires variable name")) - } else { - let full_arg = args.join(" "); - if let Some(eq_pos) = full_arg.find('=') { - let name = full_arg[..eq_pos].trim().to_string(); - let value = full_arg[eq_pos + 1..].trim().to_string(); - Ok(Builtin(Set { name, value })) - } else { - Err(eyre::eyre!("SET requires variable=value format")) - } - } - }, - - // Drive change (like C:, D:, etc.) - _ if command_name.len() == 2 && command_name.ends_with(':') => Ok(Empty), - - // External command - _ => Ok(External { - program: command_name, - args, - }), - } - } -} - -fn parse_filespec(p0: &str) -> FileSpec { - match p0 { - "CON" => FileSpec::Con, - "LPT1" => FileSpec::Lpt1, - "LPT2" => FileSpec::Lpt2, - "LPT3" => FileSpec::Lpt3, - "PRN" => FileSpec::Prn, - _ => FileSpec::Path(PathBuf::from(p0)), - } -} - -impl Command { - fn parse(input: &str) -> Result<Command> { - let trimmed = input.trim(); - if trimmed.is_empty() { - return Ok(Command::Empty); - } - - let mut lexer = Lexer::new(trimmed); - let tokens = lexer.tokenize(); - - let mut parser = Parser::new(tokens); - parser.parse_command() - } -} |