diff --git a/Cargo.lock b/Cargo.lock index 4a0b418e90..e25fd71d29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -254,6 +254,21 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "config" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "console" version = "0.7.5" @@ -771,6 +786,11 @@ dependencies = [ "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fixedbitset" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "flate2" version = "1.0.7" @@ -951,6 +971,17 @@ name = "is-match" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "isatty" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itertools" version = "0.7.11" @@ -1216,6 +1247,15 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nom" version = "5.0.0-beta1" @@ -1266,6 +1306,7 @@ dependencies = [ "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "prettyprint 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ptree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1412,6 +1453,11 @@ dependencies = [ "num-traits 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ordermap" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "output_vt100" version = "0.1.2" @@ -1487,6 +1533,15 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "petgraph" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pin-utils" version = "0.1.0-alpha.4" @@ -1572,6 +1627,22 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ptree" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "tint 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -1764,6 +1835,11 @@ dependencies = [ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rust-ini" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-demangle" version = "0.1.14" @@ -1857,6 +1933,18 @@ name = "serde" version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "serde-hjson" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde-hjson" version = "0.9.0" @@ -1869,6 +1957,15 @@ dependencies = [ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde-value" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_derive" version = "1.0.91" @@ -2124,6 +2221,14 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tint" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-executor" version = "0.1.7" @@ -2169,6 +2274,14 @@ dependencies = [ "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "toml" version = "0.5.1" @@ -2404,6 +2517,7 @@ dependencies = [ "checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum conch-parser 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "baf61cea7edff80a7d8a9a4c219d391664715559e9d4e7129494b45278705a41" +"checksum config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9107d78ed62b3fa5a86e7d18e647abed48cfd8f8fab6c72f4cdb982d196f7e6" "checksum console 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2bf3720d3f3fc30b721ef1ae54e13af3264af4af39dc476a8de56a6ee1e2184b" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum content_inspector 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" @@ -2459,6 +2573,7 @@ dependencies = [ "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" @@ -2480,6 +2595,7 @@ dependencies = [ "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" +"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" "checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" @@ -2512,6 +2628,7 @@ dependencies = [ "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" "checksum nix 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d10caafde29a846a82ae0af70414e4643e072993441033b2c93217957e2f867" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum nom 5.0.0-beta1 (registry+https://github.com/rust-lang/crates.io-index)" = "6527f311b2baba609e980e008460ab5ebff6d6da15213bb8eb193b7746eefa24" "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" "checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" @@ -2528,6 +2645,7 @@ dependencies = [ "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)" = "75bdd6dbbb4958d38e47a1d2348847ad1eb4dc205dc5d37473ae504391865acc" "checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" +"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum pancurses 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d3058bc37c433096b2ac7afef1c5cdfae49ede0a4ffec3dfc1df1df0959d0ff0" @@ -2536,6 +2654,7 @@ dependencies = [ "checksum parse-zoneinfo 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "089a398ccdcdd77b8c38909d5a1e4b67da1bc4c9dbfe6d5b536c828eddb779e5" "checksum pdcurses-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "084dd22796ff60f1225d4eb6329f33afaf4c85419d51d440ab6b8c6f4529166b" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum plist 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f4739851c08dd9a62a78beff2edf1a438517268b2c563c42fc6d9d3139e42d2a" @@ -2544,6 +2663,7 @@ dependencies = [ "checksum prettyprint 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2705417f8aa07cb6308db42e55623479c1c9667942a4d5e4174c684e5da5590d" "checksum prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum ptree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0a3be00b19ee7bd33238c1c523a7ab4df697345f6b36f90827a7860ea938d4" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -2565,6 +2685,7 @@ dependencies = [ "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum render-tree 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68ed587df09cfb7ce1bc6fe8f77e24db219f222c049326ccbfb948ec67e31664" +"checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2579,7 +2700,9 @@ dependencies = [ "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" "checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" +"checksum serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153" "checksum serde-hjson 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4640cf3168e40c00c874ff1ad436c0f18c37edec101d5d897a4396f617abce29" +"checksum serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" "checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" @@ -2609,10 +2732,12 @@ dependencies = [ "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tint 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7af24570664a3074673dbbf69a65bdae0ae0b72f2949b1adfbacb736ee4d6896" "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" "checksum toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a24369a1894ac8224efcfd567c3d141aea360292f49888e7ec7dcc316527aebb" "checksum toml-query_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c99ca245ec273c7e75c8ee58f47b882d0146f3c2c8495158082c6671e8b5335" diff --git a/Cargo.toml b/Cargo.toml index 11709f09d0..f989283fa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ lazy_static = "1.3.0" git2 = "0.8.0" dirs = "2.0.1" ctrlc = "3.1.3" +ptree = "0.2" [dependencies.pancurses] version = "0.16" diff --git a/src/cli.rs b/src/cli.rs index 528fd92e0f..fecbb5ea96 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,3 +1,7 @@ +use crate::commands::classified::SinkCommand; +use crate::commands::command::sink; +use crate::commands::{autoview, tree}; + use crate::prelude::*; use crate::commands::classified::{ @@ -7,17 +11,16 @@ use crate::commands::classified::{ use crate::context::Context; crate use crate::errors::ShellError; use crate::evaluate::Scope; -crate use crate::format::{EntriesListView, GenericView}; + use crate::git::current_branch; use crate::object::Value; use crate::parser::ast::{Expression, Leaf, RawExpression}; use crate::parser::{Args, Pipeline}; -use crate::stream::empty_stream; use log::debug; use rustyline::error::ReadlineError; use rustyline::{self, ColorMode, Config, Editor}; -use std::collections::VecDeque; + use std::error::Error; use std::iter::Iterator; use std::sync::atomic::{AtomicBool, Ordering}; @@ -44,7 +47,6 @@ pub async fn cli() -> Result<(), Box> { use crate::commands::*; context.add_commands(vec![ - command("format-list", format_list), command("ps", ps::ps), command("ls", ls::ls), command("cd", cd::cd), @@ -69,6 +71,11 @@ pub async fn cli() -> Result<(), Box> { Arc::new(Config), command("sort-by", sort_by::sort_by), ]); + + context.add_sinks(vec![ + sink("autoview", autoview::autoview), + sink("tree", tree::tree), + ]); } let config = Config::builder().color_mode(ColorMode::Forced).build(); @@ -212,7 +219,19 @@ async fn process_line(readline: Result, ctx: &mut Context debug!("=== Parsed ==="); debug!("{:#?}", result); - let pipeline = classify_pipeline(&result, ctx)?; + let mut pipeline = classify_pipeline(&result, ctx)?; + + match pipeline.commands.last() { + Some(ClassifiedCommand::Sink(_)) => {} + Some(ClassifiedCommand::External(_)) => {} + _ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand { + command: sink("autoview", autoview::autoview), + args: Args { + positional: vec![], + named: indexmap::IndexMap::new(), + }, + })), + } let mut input = ClassifiedInputStream::new(); @@ -237,9 +256,30 @@ async fn process_line(readline: Result, ctx: &mut Context )) } + (Some(ClassifiedCommand::Sink(_)), Some(_)) => { + return LineResult::Error(ShellError::string("Commands like table, save, and autoview must come last in the pipeline")) + } + + (Some(ClassifiedCommand::Sink(left)), None) => { + let input_vec: Vec = input.objects.collect().await; + left.run( + ctx, + input_vec, + )?; + break; + } + ( Some(ClassifiedCommand::Internal(left)), - Some(ClassifiedCommand::Internal(_)), + Some(ClassifiedCommand::External(_)), + ) => match left.run(ctx, input).await { + Ok(val) => ClassifiedInputStream::from_input_stream(val), + Err(err) => return LineResult::Error(err), + }, + + ( + Some(ClassifiedCommand::Internal(left)), + Some(_), ) => match left.run(ctx, input).await { Ok(val) => ClassifiedInputStream::from_input_stream(val), Err(err) => return LineResult::Error(err), @@ -260,17 +300,9 @@ async fn process_line(readline: Result, ctx: &mut Context Err(err) => return LineResult::Error(err), }, - ( - Some(ClassifiedCommand::Internal(left)), - Some(ClassifiedCommand::External(_)), - ) => match left.run(ctx, input).await { - Ok(val) => ClassifiedInputStream::from_input_stream(val), - Err(err) => return LineResult::Error(err), - }, - ( Some(ClassifiedCommand::External(left)), - Some(ClassifiedCommand::Internal(_)), + Some(_), ) => match left.run(ctx, input, StreamNext::Internal).await { Ok(val) => val, Err(err) => return LineResult::Error(err), @@ -285,21 +317,6 @@ async fn process_line(readline: Result, ctx: &mut Context } } - let input_vec: VecDeque<_> = input.objects.collect().await; - - if input_vec.len() > 0 { - if equal_shapes(&input_vec) { - let array = crate::commands::stream_to_array(input_vec.boxed()).await; - let args = CommandArgs::from_context(ctx, vec![], array); - let mut result = format(args); - let mut vec = vec![]; - vec.send_all(&mut result).await?; - } else { - let args = CommandArgs::from_context(ctx, vec![], input_vec.boxed()); - format(args).collect::>().await; - } - } - LineResult::Success(line.to_string()) } Err(ReadlineError::Interrupted) => LineResult::Error(ShellError::string("CTRL-C")), @@ -365,17 +382,31 @@ fn classify_command( args, })) } - false => { - let arg_list_strings: Vec = match args { - Some(args) => args.iter().map(|i| i.as_external_arg()).collect(), - None => vec![], - }; + false => match context.has_sink(&name.to_string()) { + true => { + let command = context.get_sink(&name.to_string()); + let config = command.config(); + let scope = Scope::empty(); - Ok(ClassifiedCommand::External(ExternalCommand { - name: name.to_string(), - args: arg_list_strings, - })) - } + let args = match args { + Some(args) => config.evaluate_args(args.iter(), &scope)?, + None => Args::default(), + }; + + Ok(ClassifiedCommand::Sink(SinkCommand { command, args })) + } + false => { + let arg_list_strings: Vec = match args { + Some(args) => args.iter().map(|i| i.as_external_arg()).collect(), + None => vec![], + }; + + Ok(ClassifiedCommand::External(ExternalCommand { + name: name.to_string(), + args: arg_list_strings, + })) + } + }, }, (_, None) => Err(ShellError::string( @@ -390,64 +421,3 @@ fn classify_command( ))) } } - -crate fn format(args: CommandArgs) -> OutputStream { - let host = args.host.clone(); - let input = args.input.map(|a| a.copy()); - let input = input.collect::>(); - - input - .then(move |input| { - let last = input.len() - 1; - let mut host = host.lock().unwrap(); - for (i, item) in input.iter().enumerate() { - let view = GenericView::new(item); - - handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); - - if last != i { - host.stdout(""); - } - } - - futures::future::ready(empty_stream()) - }) - .flatten_stream() - .boxed() -} - -crate fn format_list(args: CommandArgs) -> Result { - let host = args.host.clone(); - - let view = EntriesListView::from_stream(args.input); - - Ok(view - .then(move |view| { - handle_unexpected(&mut *host.lock().unwrap(), |host| { - crate::format::print_view(&view, host) - }); - - futures::future::ready(empty_stream()) - }) - .flatten_stream() - .boxed()) -} - -fn equal_shapes(input: &VecDeque) -> bool { - let mut items = input.iter(); - - let item = match items.next() { - Some(item) => item, - None => return false, - }; - - let desc = item.data_descriptors(); - - for item in items { - if desc != item.data_descriptors() { - return false; - } - } - - true -} diff --git a/src/commands.rs b/src/commands.rs index b0b8a55c06..9dbcd8e767 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,4 +1,5 @@ crate mod args; +crate mod autoview; crate mod cd; crate mod classified; crate mod command; @@ -21,11 +22,12 @@ crate mod split_row; crate mod to_array; crate mod to_json; crate mod to_toml; +crate mod tree; crate mod trim; crate mod view; crate mod where_; crate use command::command; crate use config::Config; -crate use to_array::stream_to_array; + crate use where_::Where; diff --git a/src/commands/autoview.rs b/src/commands/autoview.rs new file mode 100644 index 0000000000..c38578324d --- /dev/null +++ b/src/commands/autoview.rs @@ -0,0 +1,43 @@ +use crate::commands::command::SinkCommandArgs; +use crate::errors::ShellError; +use crate::format::{GenericView, TableView}; +use crate::prelude::*; + +pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> { + if args.input.len() > 0 { + if equal_shapes(&args.input) { + let mut host = args.ctx.host.lock().unwrap(); + let view = TableView::from_list(&args.input).unwrap(); + + handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); + } else { + let mut host = args.ctx.host.lock().unwrap(); + for i in args.input.iter() { + let view = GenericView::new(&i); + handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); + host.stdout(""); + } + } + } + + Ok(()) +} + +fn equal_shapes(input: &Vec) -> bool { + let mut items = input.iter(); + + let item = match items.next() { + Some(item) => item, + None => return false, + }; + + let desc = item.data_descriptors(); + + for item in items { + if desc != item.data_descriptors() { + return false; + } + } + + true +} diff --git a/src/commands/classified.rs b/src/commands/classified.rs index 44452635be..e10496f6ad 100644 --- a/src/commands/classified.rs +++ b/src/commands/classified.rs @@ -1,3 +1,4 @@ +use crate::commands::command::Sink; use crate::parser::ast::Expression; use crate::parser::registry::Args; use crate::prelude::*; @@ -79,9 +80,21 @@ crate enum ClassifiedCommand { #[allow(unused)] Expr(Expression), Internal(InternalCommand), + Sink(SinkCommand), External(ExternalCommand), } +crate struct SinkCommand { + crate command: Arc, + crate args: Args, +} + +impl SinkCommand { + crate fn run(self, context: &mut Context, input: Vec) -> Result<(), ShellError> { + context.run_sink(self.command, self.args, input) + } +} + crate struct InternalCommand { crate command: Arc, crate args: Args, diff --git a/src/commands/command.rs b/src/commands/command.rs index 8ac5ee0618..cf98bb5ac7 100644 --- a/src/commands/command.rs +++ b/src/commands/command.rs @@ -2,6 +2,7 @@ use crate::errors::ShellError; use crate::object::Value; use crate::parser::CommandConfig; use crate::prelude::*; +use core::future::Future; use std::path::PathBuf; pub struct CommandArgs { @@ -28,6 +29,28 @@ impl CommandArgs { } } +pub struct SinkCommandArgs { + pub ctx: Context, + pub positional: Vec, + pub named: indexmap::IndexMap, + pub input: Vec, +} + +impl SinkCommandArgs { + crate fn from_context( + ctx: &'caller mut Context, + positional: Vec, + input: Vec, + ) -> SinkCommandArgs { + SinkCommandArgs { + ctx: ctx.clone(), + positional, + named: indexmap::IndexMap::default(), + input, + } + } +} + #[derive(Debug)] pub enum CommandAction { ChangeCwd(PathBuf), @@ -60,6 +83,21 @@ pub trait Command { } } +pub trait Sink { + fn run(&self, args: SinkCommandArgs) -> Result<(), ShellError>; + fn name(&self) -> &str; + + fn config(&self) -> CommandConfig { + CommandConfig { + name: self.name().to_string(), + mandatory_positional: vec![], + optional_positional: vec![], + rest_positional: true, + named: indexmap::IndexMap::new(), + } + } +} + pub struct FnCommand { name: String, func: fn(CommandArgs) -> Result, @@ -84,3 +122,25 @@ pub fn command( func, }) } + +pub struct FnSink { + name: String, + func: fn(SinkCommandArgs) -> Result<(), ShellError>, +} + +impl Sink for FnSink { + fn run(&self, args: SinkCommandArgs) -> Result<(), ShellError> { + (self.func)(args) + } + + fn name(&self) -> &str { + &self.name + } +} + +pub fn sink(name: &str, func: fn(SinkCommandArgs) -> Result<(), ShellError>) -> Arc { + Arc::new(FnSink { + name: name.to_string(), + func, + }) +} diff --git a/src/commands/format.rs b/src/commands/format.rs index 02c32dabd6..9cbaa20fe6 100644 --- a/src/commands/format.rs +++ b/src/commands/format.rs @@ -1,5 +1,5 @@ use crate::prelude::*; -use crate::{EntriesListView, GenericView}; +use crate::{EntriesListView, GenericView, TreeView}; use futures::stream::{self, StreamExt}; use std::sync::{Arc, Mutex}; diff --git a/src/commands/tree.rs b/src/commands/tree.rs new file mode 100644 index 0000000000..c66ae596a0 --- /dev/null +++ b/src/commands/tree.rs @@ -0,0 +1,17 @@ +use crate::commands::command::SinkCommandArgs; +use crate::errors::ShellError; +use crate::format::TreeView; +use crate::prelude::*; + +pub fn tree(args: SinkCommandArgs) -> Result<(), ShellError> { + if args.input.len() > 0 { + let mut host = args.ctx.host.lock().unwrap(); + for i in args.input.iter() { + let view = TreeView::from_value(&i); + handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); + host.stdout(""); + } + } + + Ok(()) +} diff --git a/src/context.rs b/src/context.rs index 5c5bb4a8f2..b63252f767 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,3 +1,5 @@ +use crate::commands::command::Sink; +use crate::commands::command::SinkCommandArgs; use crate::parser::Args; use crate::prelude::*; @@ -5,8 +7,10 @@ use indexmap::IndexMap; use std::error::Error; use std::sync::Arc; +#[derive(Clone)] pub struct Context { commands: IndexMap>, + sinks: IndexMap>, crate host: Arc>, crate env: Arc>, } @@ -15,6 +19,7 @@ impl Context { crate fn basic() -> Result> { Ok(Context { commands: indexmap::IndexMap::new(), + sinks: indexmap::IndexMap::new(), host: Arc::new(Mutex::new(crate::env::host::BasicHost)), env: Arc::new(Mutex::new(Environment::basic()?)), }) @@ -26,6 +31,40 @@ impl Context { } } + pub fn add_sinks(&mut self, sinks: Vec>) { + for sink in sinks { + self.sinks.insert(sink.name().to_string(), sink); + } + } + + pub fn clone_sinks(&self) -> indexmap::IndexMap> { + self.sinks.clone() + } + + crate fn has_sink(&self, name: &str) -> bool { + self.sinks.contains_key(name) + } + + crate fn get_sink(&self, name: &str) -> Arc { + self.sinks.get(name).unwrap().clone() + } + + crate fn run_sink( + &mut self, + command: Arc, + args: Args, + input: Vec, + ) -> Result<(), ShellError> { + let command_args = SinkCommandArgs { + ctx: self.clone(), + positional: args.positional, + named: args.named, + input, + }; + + command.run(command_args) + } + pub fn clone_commands(&self) -> indexmap::IndexMap> { self.commands.clone() } diff --git a/src/format.rs b/src/format.rs index 8494697e64..43c2c1db91 100644 --- a/src/format.rs +++ b/src/format.rs @@ -2,12 +2,15 @@ crate mod entries; crate mod generic; crate mod list; crate mod table; +crate mod tree; use crate::prelude::*; crate use entries::{EntriesListView, EntriesView}; crate use generic::GenericView; +crate use list::ListView; crate use table::TableView; +crate use tree::TreeView; crate trait RenderView { fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError>; diff --git a/src/format/generic.rs b/src/format/generic.rs index da5954398f..18b7c0d582 100644 --- a/src/format/generic.rs +++ b/src/format/generic.rs @@ -1,4 +1,4 @@ -use crate::format::{EntriesView, RenderView, TableView}; +use crate::format::{EntriesView, ListView, RenderView, TableView, TreeView}; use crate::object::Value; use crate::prelude::*; use derive_new::new; diff --git a/src/format/tree.rs b/src/format/tree.rs new file mode 100644 index 0000000000..cb2b650907 --- /dev/null +++ b/src/format/tree.rs @@ -0,0 +1,83 @@ +use crate::format::RenderView; +use crate::prelude::*; +use derive_new::new; +use ptree::item::StringItem; +use ptree::output::print_tree_with; +use ptree::print_config::PrintConfig; +use ptree::style::{Color, Style}; +use ptree::TreeBuilder; + +// An entries list is printed like this: +// +// name : ... +// name2 : ... +// another_name : ... +#[derive(new)] +pub struct TreeView { + //entries: Vec<(crate::object::DescriptorName, Value)>, + tree: StringItem, +} + +impl TreeView { + fn from_value_helper(value: &Value, mut builder: &mut TreeBuilder) { + match value { + Value::Primitive(p) => builder = builder.add_empty_child(p.format(None)), + Value::Object(o) => { + for (k, v) in o.entries.iter() { + builder = builder.begin_child(k.name.display().to_string()); + Self::from_value_helper(v, builder); + builder = builder.end_child(); + } + } + Value::List(l) => { + for elem in l.iter() { + Self::from_value_helper(elem, builder); + } + } + Value::Block(_) => {} + Value::Error(_) => {} + } + } + crate fn from_value(value: &Value) -> TreeView { + let descs = value.data_descriptors(); + + let mut tree = TreeBuilder::new("".to_string()); + let mut builder = &mut tree; + + for desc in descs { + let value = value.get_data(&desc); + builder = builder.begin_child(desc.name.display().to_string()); + Self::from_value_helper(value.borrow(), &mut builder); + builder = builder.end_child(); + //entries.push((desc.name.clone(), value.borrow().copy())) + } + + TreeView::new(builder.build()) + } +} + +impl RenderView for TreeView { + fn render_view(&self, _host: &mut dyn Host) -> Result<(), ShellError> { + // Set up the print configuration + let config = { + let mut config = PrintConfig::from_env(); + config.branch = Style { + foreground: Some(Color::Green), + dimmed: true, + ..Style::default() + }; + config.leaf = Style { + bold: true, + ..Style::default() + }; + //config.characters = UTF_CHARS_BOLD.into(); + config.indent = 4; + config + }; + + // Print out the tree using custom formatting + print_tree_with(&self.tree, &config)?; + + Ok(()) + } +} diff --git a/src/object/dict.rs b/src/object/dict.rs index 22167698c6..c9ff168a0c 100644 --- a/src/object/dict.rs +++ b/src/object/dict.rs @@ -4,13 +4,13 @@ use crate::object::DataDescriptor; use crate::object::{Primitive, Value}; use derive_new::new; use indexmap::IndexMap; +use serde::ser::{Serialize, SerializeMap, Serializer}; use serde_derive::Deserialize; -use serde::ser::{Serialize, Serializer, SerializeMap}; use std::cmp::{Ordering, PartialOrd}; #[derive(Debug, Default, Eq, PartialEq, Deserialize, Clone, new)] pub struct Dictionary { - entries: IndexMap, + pub entries: IndexMap, } impl PartialOrd for Dictionary { @@ -28,8 +28,8 @@ impl Serialize for Dictionary { let mut map = serializer.serialize_map(Some(self.entries.len()))?; for (k, v) in self.entries.iter() { match v { - Value::Object(_) => {}, - _ => map.serialize_entry(k, v)? + Value::Object(_) => {} + _ => map.serialize_entry(k, v)?, } } for (k, v) in self.entries.iter() {