diff --git a/Cargo.lock b/Cargo.lock index c71e299..a9d3e2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,556 +1,984 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + [[package]] -name = "ansi_term" -version = "0.11.0" +name = "addr2line" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gimli", ] +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.6", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" + [[package]] name = "atomicwrites" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb8f2cd6962fa53c0e2a9d3f97eaa7dbd1e3cbbeeb4745403515b42ae07b3ff6" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile", + "winapi", ] [[package]] name = "atty" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi", ] [[package]] -name = "base64" -version = "0.9.1" +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" dependencies = [ - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", ] [[package]] -name = "bitflags" -version = "0.9.1" +name = "base64" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "bitflags" -version = "1.0.3" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "byteorder" -version = "1.2.2" +name = "cc" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" -version = "0.1.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.2" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "num-integer", + "num-traits", + "time 0.1.43", + "winapi", ] [[package]] name = "clap" -version = "2.31.2" +version = "3.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db" +dependencies = [ + "atty", + "bitflags", + "clap_lex", + "indexmap", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", ] [[package]] name = "cursive" -version = "0.5.1" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca536d245342f6c005e7547ab640e444a3dc2fc0319a92124c8c1cbff025e775" +dependencies = [ + "ahash", + "cfg-if", + "crossbeam-channel", + "cursive_core", + "lazy_static", + "libc", + "log", + "maplit", + "ncurses", + "signal-hook", + "term_size", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "cursive_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27fbda42833e46148ff28db338f6189a4407e4a38ba1f4105e2f623089e66a0" +dependencies = [ + "ahash", + "crossbeam-channel", + "enum-map", + "enumset", + "lazy_static", + "log", + "num", + "owning_ref", + "time 0.3.9", + "unicode-segmentation", + "unicode-width", + "xi-unicode", +] + +[[package]] +name = "darling" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ - "ncurses 5.91.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", - "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", ] [[package]] name = "email" -version = "0.0.19" +version = "0.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65360503b8831670969621be3d3814c4c7be44c642de11f8c0f5aaa01f057b3e" dependencies = [ - "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64", + "chrono", + "encoding", + "lazy_static", + "rand 0.7.3", + "version_check", ] [[package]] name = "encoding" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" dependencies = [ - "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", ] [[package]] name = "encoding-index-japanese" version = "1.20141219.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_index_tests", ] [[package]] name = "encoding-index-korean" version = "1.20141219.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_index_tests", ] [[package]] name = "encoding-index-simpchinese" version = "1.20141219.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_index_tests", ] [[package]] name = "encoding-index-singlebyte" version = "1.20141219.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_index_tests", ] [[package]] name = "encoding-index-tradchinese" version = "1.20141219.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_index_tests", ] [[package]] name = "encoding_index_tests" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "enum-map" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0348b2a57c82f98b9dbd8098b1abb2416f221823d3e50cbe24eaebdd16896826" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-map-derive", ] [[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "enum-map-derive" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a63b7a0ddec6f38dcec5e36257750b7a8fcaf4227e12ceb306e341d63634da05" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "gcc" -version = "0.3.54" +name = "enumset" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4799cdb24d48f1f8a7a98d06b7fde65a85a2d1e42b25a889f5406aa1fbefe074" +dependencies = [ + "enumset_derive", +] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "enumset_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea83a3fbdc1d999ccfbcbee717eab36f8edf2d71693a23ce0d7cca19e085304c" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "lazy_static" -version = "1.0.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.40" +version = "0.2.124" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" [[package]] -name = "mates" -version = "0.3.0" +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" dependencies = [ - "atomicwrites 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cursive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "email 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "vobject 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] -name = "ncurses" -version = "5.91.0" +name = "maplit" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "mates" +version = "1.0.0" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow", + "atomicwrites", + "clap", + "cursive", + "email", + "uuid", + "vobject", ] [[package]] -name = "nix" -version = "0.9.0" +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "miniz_oxide" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "adler", ] [[package]] -name = "num" -version = "0.1.42" +name = "ncurses" +version = "5.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c5d34d72657dc4b638a1c25d40aae81e4f1c699062f72f467237920752032" dependencies = [ - "num-bigint 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "pkg-config", ] [[package]] -name = "num-bigint" -version = "0.1.43" +name = "num" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" dependencies = [ - "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", ] [[package]] name = "num-complex" -version = "0.1.43" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" dependencies = [ - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", ] [[package]] name = "num-integer" -version = "0.1.38" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-traits", ] [[package]] name = "num-iter" -version = "0.1.37" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ - "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-integer", + "num-traits", ] [[package]] name = "num-rational" -version = "0.1.42" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" dependencies = [ - "num-bigint 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-integer", + "num-traits", ] [[package]] name = "num-traits" -version = "0.2.4" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_threads" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" +dependencies = [ + "libc", +] [[package]] -name = "odds" -version = "0.2.26" +name = "object" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" [[package]] name = "owning_ref" -version = "0.2.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" +dependencies = [ + "stable_deref_trait", +] [[package]] name = "pkg-config" -version = "0.3.11" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] [[package]] name = "rand" -version = "0.3.22" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", ] [[package]] name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.16", ] [[package]] -name = "redox_syscall" -version = "0.1.37" +name = "rand_hc" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] [[package]] -name = "redox_termios" -version = "0.1.1" +name = "rdrand" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", ] [[package]] name = "remove_dir_all" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] -name = "rustc-serialize" -version = "0.3.24" +name = "rustc-demangle" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] -name = "safemem" -version = "0.2.0" +name = "signal-hook" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" +dependencies = [ + "libc", + "signal-hook-registry", +] [[package]] -name = "serde" -version = "0.9.15" +name = "signal-hook-registry" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "tempdir" -version = "0.3.7" +name = "syn" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" dependencies = [ - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] -name = "termion" -version = "1.5.1" +name = "synstructure" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] -name = "textwrap" -version = "0.9.0" +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "term_size" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "time" -version = "0.1.40" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi", ] [[package]] -name = "toml" -version = "0.3.2" +name = "time" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" dependencies = [ - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "libc", + "num_threads", ] [[package]] name = "unicode-segmentation" -version = "1.2.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" -version = "0.1.4" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "uuid" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" dependencies = [ - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23", ] -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "version_check" -version = "0.1.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vobject" -version = "0.2.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b2fe16e1c89a8e50f7c27a5bc35ea61fb10d14b5e0ace8308fff091c0fe67f9" +dependencies = [ + "failure", +] [[package]] -name = "void" -version = "1.0.2" +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] -name = "winapi" -version = "0.2.8" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "winapi" -version = "0.3.4" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "winapi-build" -version = "0.1.1" +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-i686-pc-windows-gnu" -version = "0.4.0" +name = "winapi-util" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[metadata] -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atomicwrites 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7adff0f3666b56fb01ce4caea58193a26d97d384587a10e950e0e9c857de3cca" -"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" -"checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" -"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" -"checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" -"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" -"checksum cursive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b717f6e01158b6d8bc6cad90badc2adfa8ce8a45594125efb90b854abc98ed93" -"checksum email 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "faacb54ba5ccc18b63f197548756b92e25a3a311696e84044238baf39b90c74a" -"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" -"checksum ncurses 5.91.0 (registry+https://github.com/rust-lang/crates.io-index)" = "431cc11a5225e21cb85ea479858ac2e0b3c7a67c9506016cd8818de15dcdc8f1" -"checksum nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" -"checksum num-bigint 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "81b483ea42927c463e191802e7334556b48e7875297564c0e9951bd3a0ae53e3" -"checksum num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" -"checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45" -"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" -"checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" -"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" -"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" -"checksum owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d52571ddcb42e9c900c901a18d8d67e393df723fcd51dd59c5b1a85d0acb6cc" -"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" -"checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" -"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" -"checksum vobject 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d8c8e593ed666f591f3313cb4ac158d5135ccd825e71ca8b2afe5a16c601eed8" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "xi-unicode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" diff --git a/Cargo.toml b/Cargo.toml index aa36ff5..36690bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mates" -version = "0.3.0" -authors = ["Markus Unterwaditzer "] +version = "1.0.0" +authors = ["Markus Unterwaditzer ", "Shaleen Jain "] license = "MIT" keywords = ["vdir", "vcard", "contacts", "addressbook"] readme = "README.md" @@ -11,22 +11,13 @@ documentation = "https://github.com/untitaker/mates.rs" homepage = "https://github.com/untitaker/mates.rs" repository = "https://github.com/untitaker/mates.rs" -[lib] -name = "mates" -path = "src/mates/lib.rs" - -[[bin]] -name = "mates" -test = false -doc = false +edition = "2018" [dependencies] uuid = { version = "0.5", features = ["v4"] } -atomicwrites = "0.1" +atomicwrites = "0.3" email = "0.0" -clap = "2.31" -vobject = "0.2" -cursive = "0.5" - -[build-dependencies] -clap = "2.31" +clap = "3.1" +vobject = "0.7" +cursive = "0.17" +anyhow = "1.0" diff --git a/build.rs b/build.rs.bak similarity index 85% rename from build.rs rename to build.rs.bak index 19d3ff8..319511d 100644 --- a/build.rs +++ b/build.rs.bak @@ -1,13 +1,11 @@ extern crate clap; +extern crate mates; use std::env; use std::fs; use clap::Shell; -#[path = "src/mates/app.rs"] -mod app; - fn main() { let outdir = match env::var_os("OUT_DIR") { None => return, @@ -15,7 +13,7 @@ fn main() { }; fs::create_dir_all(&outdir).unwrap(); - let mut app = app::app(); + let mut app = mates::app(); app.gen_completions("mates", Shell::Bash, &outdir); app.gen_completions("mates", Shell::Fish, &outdir); app.gen_completions("mates", Shell::Zsh, &outdir); diff --git a/src/bin/mates.rs b/src/bin/mates.rs deleted file mode 100644 index e34f9f5..0000000 --- a/src/bin/mates.rs +++ /dev/null @@ -1,4 +0,0 @@ -extern crate mates; -use mates::cli; - -fn main() { cli::cli_main() } diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..740da92 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,192 @@ +use anyhow::Result; +use std::borrow::ToOwned; +use std::env; +use std::fs; +use std::io; +use std::io::{Read, Write}; +use std::path; + +use atomicwrites::{AllowOverwrite, AtomicFile}; + +use crate::editor; +use crate::utils; +use crate::utils::CustomPathExt; + +#[inline] +fn get_pwd() -> path::PathBuf { + env::current_dir().ok().expect("Failed to get CWD") +} + +#[inline] +fn get_envvar(key: &str) -> Option { + match env::var(key) { + Ok(x) => Some(x), + Err(env::VarError::NotPresent) => None, + Err(env::VarError::NotUnicode(_)) => panic!("{} is not unicode.", key), + } +} + +pub fn index_contact(index_path: &path::Path, contact: &utils::Contact) -> Result<()> { + let mut index_fp = fs::OpenOptions::new() + .append(true) + .write(true) + .open(&index_path)?; + + let index_entry = utils::index_item_from_contact(contact)?; + index_fp.write_all(index_entry.as_bytes())?; + Ok(()) +} + +pub fn build_index(outfile: &path::Path, dir: &path::Path) -> Result<()> { + if !dir.is_dir() { + return Err(anyhow!("MATES_DIR must be a directory.")); + }; + + let af = AtomicFile::new(&outfile, AllowOverwrite); + let mut errors = false; + + af.write::<(), io::Error, _>(|outf| { + for entry in fs::read_dir(dir)? { + let entry = match entry { + Ok(x) => x, + Err(e) => { + println!("Error while listing directory: {}", e); + errors = true; + continue; + } + }; + + let pathbuf = entry.path(); + + if pathbuf.str_extension().unwrap_or("") != "vcf" || !pathbuf.is_file() { + continue; + }; + + let contact = match utils::Contact::from_file(&pathbuf) { + Ok(x) => x, + Err(e) => { + println!("Error while reading {}: {}", pathbuf.display(), e); + errors = true; + continue; + } + }; + + match utils::index_item_from_contact(&contact) { + Ok(index_string) => { + outf.write_all(index_string.as_bytes())?; + } + Err(e) => { + println!("Error while indexing {}: {}", pathbuf.display(), e); + errors = true; + continue; + } + }; + } + Ok(()) + })?; + + if errors { + Err(anyhow!( + "Several errors happened while generating the index." + )) + } else { + Ok(()) + } +} + +pub fn edit_contact(config: &Configuration, query: &str) -> Result<()> { + let results = if get_pwd().join(query).is_file() { + vec![path::PathBuf::from(query)] + } else { + utils::file_query(config, query)?.into_iter().collect() + }; + + if results.len() < 1 { + return Err(anyhow!("No such contact.")); + } else if results.len() > 1 { + return Err(anyhow!("Ambiguous query.")); + } + + let fpath = &results[0]; + editor::cli_main(fpath); + + let fcontent = { + let mut fcontent = String::new(); + let mut file = fs::File::open(fpath)?; + file.read_to_string(&mut fcontent)?; + fcontent + }; + + if (&fcontent[..]).trim().len() == 0 { + fs::remove_file(fpath)?; + return Err(anyhow!("Contact emptied, file removed.")); + }; + + Ok(()) +} + +pub fn mutt_query(config: &Configuration, disable_first_line: bool, query: &str) -> Result<()> { + // For some reason mutt requires an empty line + // We need to ignore errors here, otherwise mutt's UI will glitch + if !disable_first_line { + println!(); + } + + if let Ok(items) = utils::index_query(config, query) { + for item in items { + if item.email.len() > 0 && item.name.len() > 0 { + println!("{}\t{}", item.email, item.name); + }; + } + }; + Ok(()) +} + +pub fn file_query(config: &Configuration, query: &str) -> Result<()> { + for path in utils::file_query(config, query)?.iter() { + println!("{}", path.display()); + } + Ok(()) +} + +pub fn email_query(config: &Configuration, query: &str) -> Result<()> { + for item in utils::index_query(config, query)? { + if item.name.len() > 0 && item.email.len() > 0 { + println!("{} <{}>", item.name, item.email); + }; + } + Ok(()) +} + +pub struct Configuration { + pub index_path: path::PathBuf, + pub vdir_path: path::PathBuf, + pub grep_cmd: String, +} + +impl Configuration { + pub fn new() -> Result { + Ok(Configuration { + index_path: match get_envvar("MATES_INDEX") { + Some(x) => path::PathBuf::from(&x), + None => match get_envvar("HOME") { + Some(home) => get_pwd().join(&home).join(".mates_index"), + None => return Err("Unable to determine user's home directory.".to_owned()), + }, + }, + vdir_path: match get_envvar("MATES_DIR") { + Some(x) => path::PathBuf::from(&x), + None => { + return Err( + "MATES_DIR must be set to your vdir path (directory of vcf-files)." + .to_owned(), + ) + } + }, + grep_cmd: match get_envvar("MATES_GREP") { + Some(x) => x, + None => "grep -i".to_owned(), + }, + }) + } +} diff --git a/src/mates/editor/mod.rs b/src/editor/mod.rs similarity index 50% rename from src/mates/editor/mod.rs rename to src/editor/mod.rs index 6b37793..a839598 100644 --- a/src/mates/editor/mod.rs +++ b/src/editor/mod.rs @@ -1,16 +1,18 @@ use std::fs; -use std::io::{Read,Write}; -use std::process; +use std::io::{Read, Write}; use std::path::Path; +use std::process; use vobject; use atomicwrites; -use cursive::Cursive; +use crate::cursive::CursiveExt; use cursive::theme; -use cursive::theme::Color::*; use cursive::theme::BaseColor::*; +use cursive::theme::Color::*; +use cursive::Cursive; +use cursive::With; mod widgets; @@ -29,33 +31,33 @@ pub fn cli_main>(filename: P) { process::exit(1); } - let (editor, editor_view) = VcardEditor::new(vobj); - let mut siv = Cursive::new(); + let mut siv = Cursive::default(); siv.add_fullscreen_layer(editor_view); siv.set_theme(theme::Theme { shadow: false, - borders: Some(theme::BorderStyle::Simple), - colors: theme::Palette { - background: Dark(Black), - shadow: Dark(Black), - view: Dark(Black), - primary: Dark(White), - secondary: Dark(White), - tertiary: Dark(White), - title_primary: Dark(White), - title_secondary: Dark(White), - highlight: Light(White), - highlight_inactive: Dark(Black), - } + borders: theme::BorderStyle::Simple, + palette: theme::Palette::default().with(|p| { + p.set_color("background", Dark(Black)); + p.set_color("shadow", Dark(Black)); + p.set_color("view", Dark(Black)); + p.set_color("primary", Dark(White)); + p.set_color("secondary", Dark(White)); + p.set_color("tertiary", Dark(White)); + p.set_color("title_primary", Dark(White)); + p.set_color("title_secondary", Dark(White)); + p.set_color("highlight", Light(White)); + p.set_color("highlight_inactive", Dark(Black)); + }), }); siv.run(); vobj = editor.to_vobject(&mut siv); - drop(siv); // Necessary to be able to write text immediately afterwards + drop(siv); // Necessary to be able to write text immediately afterwards let af = atomicwrites::AtomicFile::new(filename, atomicwrites::AllowOverwrite); - af.write(|mut f| f.write_all(vobject::write_component(&vobj).as_bytes())).unwrap(); + af.write(|f| f.write_all(vobject::write_component(&vobj).as_bytes())) + .unwrap(); } diff --git a/src/mates/editor/widgets.rs b/src/editor/widgets.rs similarity index 60% rename from src/mates/editor/widgets.rs rename to src/editor/widgets.rs index 24b405b..4de155e 100644 --- a/src/mates/editor/widgets.rs +++ b/src/editor/widgets.rs @@ -1,43 +1,48 @@ use std::ops::Deref; -use cursive::Cursive; use cursive::traits::*; use cursive::views; +use cursive::Cursive; use vobject; struct FormattedNameEditor { - original_prop: Option + original_prop: Option, } impl FormattedNameEditor { - pub fn pop_from_vobject(vobj: &mut vobject::Component) -> (Self, views::IdView) { + pub fn pop_from_vobject( + vobj: &mut vobject::Component, + ) -> (Self, views::NamedView) { let prop = vobj.pop("FN"); let content = match prop { Some(ref p) => p.value_as_string(), - None => "".to_owned() + None => "".to_owned(), }; - (FormattedNameEditor { original_prop: prop }, - views::EditView::new().content(content).with_id("FN")) + ( + FormattedNameEditor { + original_prop: prop, + }, + views::EditView::new().content(content).with_name("FN"), + ) } pub fn push_to_vobject(&self, siv: &mut Cursive, vobj: &mut vobject::Component) { - let v = siv.find_id::("FN").unwrap(); + let v = siv.find_name::("FN").unwrap(); let content = v.get_content(); let new_prop = match self.original_prop { Some(ref x) => { let mut nx = x.clone(); nx.raw_value = vobject::escape_chars(content.as_str()); nx - }, - None => vobject::Property::new("FN", content.as_str()) + } + None => vobject::Property::new("FN", content.as_str()), }; vobj.push(new_prop); } } - fn mprops_to_view(props: Vec) -> views::TextArea { let mut edit_text = String::new(); for prop in props { @@ -52,7 +57,11 @@ fn mprops_to_view(props: Vec) -> views::TextArea { views::TextArea::new().content(edit_text) } -fn view_to_mprops>(v: V, prop_name: &str, vobj: &mut vobject::Component) { +fn view_to_mprops>( + v: V, + prop_name: &str, + vobj: &mut vobject::Component, +) { for line in v.get_content().split('\n') { let mut split = line.rsplitn(2, ' '); let mut prop = match split.next() { @@ -69,13 +78,15 @@ fn view_to_mprops>(v: V, prop_name: &str, vobj: struct EmailsEditor; impl EmailsEditor { - pub fn pop_from_vobject(vobj: &mut vobject::Component) -> (Self, views::IdView) { + pub fn pop_from_vobject( + vobj: &mut vobject::Component, + ) -> (Self, views::NamedView) { let props = vobj.props.remove("EMAIL").unwrap_or_else(Vec::new); - (EmailsEditor, mprops_to_view(props).with_id("emails")) + (EmailsEditor, mprops_to_view(props).with_name("emails")) } pub fn push_to_vobject(&self, siv: &mut Cursive, vobj: &mut vobject::Component) { - let v = siv.find_id::("emails").unwrap(); + let v = siv.find_name::("emails").unwrap(); view_to_mprops(v, "EMAIL", vobj); } } @@ -83,13 +94,15 @@ impl EmailsEditor { struct TelEditor; impl TelEditor { - pub fn pop_from_vobject(vobj: &mut vobject::Component) -> (Self, views::IdView) { + pub fn pop_from_vobject( + vobj: &mut vobject::Component, + ) -> (Self, views::NamedView) { let props = vobj.props.remove("TEL").unwrap_or_else(Vec::new); - (TelEditor, mprops_to_view(props).with_id("tels")) + (TelEditor, mprops_to_view(props).with_name("tels")) } pub fn push_to_vobject(&self, siv: &mut Cursive, vobj: &mut vobject::Component) { - let v = siv.find_id::("tels").unwrap(); + let v = siv.find_name::("tels").unwrap(); view_to_mprops(v, "TEL", vobj); } } @@ -98,30 +111,38 @@ pub struct VcardEditor { vobj: vobject::Component, fn_field: FormattedNameEditor, email_field: EmailsEditor, - tel_field: TelEditor + tel_field: TelEditor, } impl VcardEditor { - pub fn new(mut vobj: vobject::Component) -> (Self, views::BoxView) { + pub fn new(mut vobj: vobject::Component) -> (Self, views::ResizedView) { let (fn_field, fn_view) = FormattedNameEditor::pop_from_vobject(&mut vobj); let (email_field, email_view) = EmailsEditor::pop_from_vobject(&mut vobj); let (tel_field, tel_view) = TelEditor::pop_from_vobject(&mut vobj); let main_col = views::LinearLayout::vertical() - .child(views::Panel::new(views::LinearLayout::vertical() - .child(views::TextView::new("Formatted Name:")) - .child(fn_view))) - .child(views::Panel::new(views::LinearLayout::vertical() - .child(views::TextView::new("Hit ^C to abort, or ")) - .child(views::Button::new("Save", |s| s.quit())))); + .child(views::Panel::new( + views::LinearLayout::vertical() + .child(views::TextView::new("Formatted Name:")) + .child(fn_view), + )) + .child(views::Panel::new( + views::LinearLayout::vertical() + .child(views::TextView::new("Hit ^C to abort, or ")) + .child(views::Button::new("Save", |s| s.quit())), + )); let props_list = views::LinearLayout::vertical() - .child(views::Panel::new(views::LinearLayout::vertical() - .child(views::TextView::new("Email addresses: (type + email)")) - .child(email_view))) - .child(views::Panel::new(views::LinearLayout::vertical() - .child(views::TextView::new("Telephone numbers: (type + nr)")) - .child(tel_view))); + .child(views::Panel::new( + views::LinearLayout::vertical() + .child(views::TextView::new("Email addresses: (type + email)")) + .child(email_view), + )) + .child(views::Panel::new( + views::LinearLayout::vertical() + .child(views::TextView::new("Telephone numbers: (type + nr)")) + .child(tel_view), + )); let cols = views::LinearLayout::horizontal() .child(main_col) @@ -132,7 +153,7 @@ impl VcardEditor { vobj: vobj, fn_field: fn_field, email_field: email_field, - tel_field: tel_field + tel_field: tel_field, }; (rv, cols) diff --git a/src/mates/lib.rs b/src/lib.rs similarity index 75% rename from src/mates/lib.rs rename to src/lib.rs index 7f52dd7..0559205 100644 --- a/src/mates/lib.rs +++ b/src/lib.rs @@ -1,11 +1,12 @@ -extern crate vobject; -extern crate email; -extern crate uuid; +#[macro_use] +extern crate anyhow; extern crate atomicwrites; extern crate clap; extern crate cursive; +extern crate email; +extern crate uuid; +extern crate vobject; -pub mod app; pub mod cli; -mod utils; mod editor; +pub mod utils; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..28e080d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,113 @@ +#[macro_use] +extern crate anyhow; +use anyhow::Result; +use clap::{Arg, Command}; +use std::io; +use std::io::Read; + +use mates::cli; +use mates::utils; + +fn main() -> Result<()> { + let app = Command::new("mates") + .version(env!("CARGO_PKG_VERSION")) + .author("Markus Unterwaditzer") + .about("A simple commandline addressbook") + .subcommand_required(true) + .subcommand(Command::new("index").about("Rewrite/create the index")) + .subcommand( + Command::new("mutt-query") + .about("Search for contact, output is usable for mutt's query_command.") + .arg( + Arg::new("disable-empty-line") + .long("disable-empty-line") + .help("Disable printing an empty first line"), + ) + .arg(Arg::new("query").required(true)), + ) + .subcommand( + Command::new("file-query") + .about("Search for contact, return just the filename.") + .arg(Arg::new("query").required(true)), + ) + .subcommand( + Command::new("email-query") + .about("Search for contact, return \"name \".") + .arg(Arg::new("query").required(true)), + ) + .subcommand( + Command::new("add") + .about("Manually add a contacts email id and full name.") + .arg(Arg::new("email").required(true)) + .arg(Arg::new("fullname")), + ) + .subcommand( + Command::new("add-email") + .about("Take mail from stdin, add sender to contacts. Print filename."), + ) + .subcommand( + Command::new("edit") + .about("Open contact (given by filepath or search-string) interactively.") + .arg(Arg::new("file-or-query").required(true)), + ) + .get_matches(); + + let config = match cli::Configuration::new() { + Ok(x) => x, + Err(e) => { + return Err(anyhow!("Error while reading configuration: {}", e)); + } + }; + + match app.subcommand() { + Some(("index", _)) => { + println!( + "Rebuilding index file \"{}\"...", + config.index_path.display() + ); + cli::build_index(&config.index_path, &config.vdir_path)?; + } + Some(("mutt-query", args)) => { + if let Some(value) = args.value_of("query") { + cli::mutt_query(&config, args.is_present("disable-empty-line"), value)? + } + } + Some(("file-query", args)) => { + if let Some(value) = args.value_of("query") { + cli::file_query(&config, value)? + } + } + Some(("email-query", args)) => { + if let Some(value) = args.value_of("query") { + cli::email_query(&config, value)? + } + } + Some(("add", args)) => { + let contact = utils::Contact::generate( + args.value_of("fullname"), + args.value_of("email"), + &config.vdir_path, + ); + contact.write_create()?; + + cli::index_contact(&config.index_path, &contact)? + } + Some(("add-email", _)) => { + let stdin = io::stdin(); + let mut email = String::new(); + stdin.lock().read_to_string(&mut email)?; + let contact = utils::add_contact_from_email(&config.vdir_path, &email[..])?; + println!("{}", contact.path.display()); + + cli::index_contact(&config.index_path, &contact)? + } + Some(("edit", args)) => { + if let Some(value) = args.value_of("file-or-query") { + cli::edit_contact(&config, value)? + } + } + _ => (), + } + + Ok(()) +} diff --git a/src/mates/app.rs b/src/mates/app.rs deleted file mode 100644 index 36b79fe..0000000 --- a/src/mates/app.rs +++ /dev/null @@ -1,25 +0,0 @@ -use clap::{App, Arg, AppSettings, SubCommand}; - -pub fn app() -> App<'static, 'static> { - App::new("mates") - .version(env!("CARGO_PKG_VERSION")) - .author("Markus Unterwaditzer") - .about("A simple commandline addressbook") - .setting(AppSettings::SubcommandRequired) - .subcommand(SubCommand::with_name("index") - .about("Rewrite/create the index")) - .subcommand(SubCommand::with_name("mutt-query") - .about("Search for contact, output is usable for mutt's query_command.") - .arg(Arg::with_name("query").index(1))) - .subcommand(SubCommand::with_name("file-query") - .about("Search for contact, return just the filename.") - .arg(Arg::with_name("query").index(1))) - .subcommand(SubCommand::with_name("email-query") - .about("Search for contact, return \"name \".") - .arg(Arg::with_name("query").index(1))) - .subcommand(SubCommand::with_name("add") - .about("Take mail from stdin, add sender to contacts. Print filename.")) - .subcommand(SubCommand::with_name("edit") - .about("Open contact (given by filepath or search-string) interactively.") - .arg(Arg::with_name("file-or-query").index(1))) -} diff --git a/src/mates/cli.rs b/src/mates/cli.rs deleted file mode 100644 index b96f84c..0000000 --- a/src/mates/cli.rs +++ /dev/null @@ -1,275 +0,0 @@ -use std::borrow::ToOwned; -use std::env; -use std::error::Error; -use std::fmt;use std::fs; -use std::io::{Read,Write}; -use std::io; -use std::path; -use std::process; - -use atomicwrites::{AtomicFile,AllowOverwrite}; - -use utils; -use utils::CustomPathExt; -use app; -use editor; - - -#[inline] -fn get_pwd() -> path::PathBuf { - env::current_dir().ok().expect("Failed to get CWD") -} - -#[inline] -fn get_envvar(key: &str) -> Option { - match env::var(key) { - Ok(x) => Some(x), - Err(env::VarError::NotPresent) => None, - Err(env::VarError::NotUnicode(_)) => panic!(format!("{} is not unicode.", key)), - } -} - -fn build_index(outfile: &path::Path, dir: &path::Path) -> MainResult<()> { - if !dir.is_dir() { - return Err(MainError::new("MATES_DIR must be a directory.").into()); - }; - - let af = AtomicFile::new(&outfile, AllowOverwrite); - let mut errors = false; - - try!(af.write::<(), io::Error, _>(|outf| { - for entry in try!(fs::read_dir(dir)) { - let entry = match entry { - Ok(x) => x, - Err(e) => { - println!("Error while listing directory: {}", e); - errors = true; - continue; - } - }; - - let pathbuf = entry.path(); - - if pathbuf.str_extension().unwrap_or("") != "vcf" || !pathbuf.is_file() { - continue; - }; - - let contact = match utils::Contact::from_file(&pathbuf) { - Ok(x) => x, - Err(e) => { - println!("Error while reading {}: {}", pathbuf.display(), e); - errors = true; - continue - } - }; - - match utils::index_item_from_contact(&contact) { - Ok(index_string) => { - try!(outf.write_all(index_string.as_bytes())); - }, - Err(e) => { - println!("Error while indexing {}: {}", pathbuf.display(), e); - errors = true; - continue - } - }; - }; - Ok(()) - })); - - if errors { - Err(MainError::new("Several errors happened while generating the index.").into()) - } else { - Ok(()) - } -} - -pub fn cli_main() { - match cli_main_raw() { - Err(e) => { - writeln!(&mut io::stderr(), "{}", e).unwrap(); - process::exit(1); - }, - _ => () - }; -} - -pub fn cli_main_raw() -> MainResult<()> { - let matches = app::app().get_matches(); - - let command = matches.subcommand_name().unwrap(); - - let config = match Configuration::new() { - Ok(x) => x, - Err(e) => { - return Err(MainError::new(format!("Error while reading configuration: {}", e)).into()); - } - }; - - let submatches = matches.subcommand_matches(command).expect("Internal error."); - - match command { - "index" => { - println!("Rebuilding index file \"{}\"...", config.index_path.display()); - try!(build_index(&config.index_path, &config.vdir_path)); - }, - "mutt-query" => { - let query = submatches.value_of("query").unwrap_or(""); - try!(mutt_query(&config, &query[..])); - }, - "file-query" => { - let query = submatches.value_of("query").unwrap_or(""); - try!(file_query(&config, &query[..])); - }, - "email-query" => { - let query = submatches.value_of("query").unwrap_or(""); - try!(email_query(&config, &query[..])); - }, - "add" => { - let stdin = io::stdin(); - let mut email = String::new(); - try!(stdin.lock().read_to_string(&mut email)); - let contact = try!(utils::add_contact_from_email( - &config.vdir_path, - &email[..] - )); - println!("{}", contact.path.display()); - - let mut index_fp = try!(fs::OpenOptions::new() - .append(true) - .write(true) - .open(&config.index_path)); - - let index_entry = try!(utils::index_item_from_contact(&contact)); - try!(index_fp.write_all(index_entry.as_bytes())); - }, - "edit" => { - let query = submatches.value_of("file-or-query").unwrap_or(""); - try!(edit_contact(&config, &query[..])); - }, - _ => { - return Err(MainError::new(format!("Invalid command: {}", command)).into()); - } - }; - Ok(()) -} - -fn edit_contact(config: &Configuration, query: &str) -> MainResult<()> { - let results = if get_pwd().join(query).is_file() { - vec![path::PathBuf::from(query)] - } else { - try!(utils::file_query(config, query)).into_iter().collect() - }; - - if results.len() < 1 { - return Err(MainError::new("No such contact.").into()); - } else if results.len() > 1 { - return Err(MainError::new("Ambiguous query.").into()); - } - - let fpath = &results[0]; - editor::cli_main(fpath); - - let fcontent = { - let mut fcontent = String::new(); - let mut file = try!(fs::File::open(fpath)); - try!(file.read_to_string(&mut fcontent)); - fcontent - }; - - if (&fcontent[..]).trim().len() == 0 { - try!(fs::remove_file(fpath)); - return Err(MainError::new("Contact emptied, file removed.").into()); - }; - - Ok(()) -} - -fn mutt_query<'a>(config: &Configuration, query: &str) -> MainResult<()> { - println!(""); // For some reason mutt requires an empty line - // We need to ignore errors here, otherwise mutt's UI will glitch - if let Ok(items) = utils::index_query(config, query) { - for item in items { - if item.email.len() > 0 && item.name.len() > 0 { - println!("{}\t{}", item.email, item.name); - }; - }; - }; - Ok(()) -} - -fn file_query<'a>(config: &Configuration, query: &str) -> MainResult<()> { - for path in try!(utils::file_query(config, query)).iter() { - println!("{}", path.display()); - }; - Ok(()) -} - -fn email_query<'a>(config: &Configuration, query: &str) -> MainResult<()> { - for item in try!(utils::index_query(config, query)) { - if item.name.len() > 0 && item.email.len() > 0 { - println!("{} <{}>", item.name, item.email); - }; - }; - Ok(()) -} - -pub struct Configuration { - pub index_path: path::PathBuf, - pub vdir_path: path::PathBuf, - pub grep_cmd: String -} - -impl Configuration { - pub fn new() -> Result { - Ok(Configuration { - index_path: match get_envvar("MATES_INDEX") { - Some(x) => path::PathBuf::from(&x), - None => match get_envvar("HOME") { - Some(home) => get_pwd().join(&home).join(".mates_index"), - None => return Err("Unable to determine user's home directory.".to_owned()) - } - }, - vdir_path: match get_envvar("MATES_DIR") { - Some(x) => path::PathBuf::from(&x), - None => return Err("MATES_DIR must be set to your vdir path (directory of vcf-files).".to_owned()) - }, - grep_cmd: match get_envvar("MATES_GREP") { - Some(x) => x, - None => "grep -i".to_owned() - } - }) - } -} - - -#[derive(PartialEq, Eq, Debug)] -pub struct MainError { - desc: String, -} - -pub type MainResult = Result>; - -impl Error for MainError { - fn description(&self) -> &str { - &self.desc[..] - } - - fn cause(&self) -> Option<&Error> { - None - } -} - -impl fmt::Display for MainError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -impl MainError { - pub fn new>(desc: T) -> Self { - MainError { - desc: desc.into(), - } - } -} diff --git a/src/mates/utils.rs b/src/utils.rs similarity index 70% rename from src/mates/utils.rs rename to src/utils.rs index 4fb54c8..86bfd11 100644 --- a/src/mates/utils.rs +++ b/src/utils.rs @@ -1,18 +1,18 @@ use std::borrow::ToOwned; use std::collections::HashSet; +use std::convert::AsRef; use std::fs; -use std::io::{Read,Write}; use std::io; +use std::io::{Read, Write}; use std::path; use std::process; -use std::convert::AsRef; -use atomicwrites::{AtomicFile,DisallowOverwrite}; +use atomicwrites::{AtomicFile, DisallowOverwrite}; use email::rfc5322::Rfc5322Parser; use uuid::Uuid; -use vobject::{Component,Property,parse_component,write_component}; +use vobject::{parse_component, write_component, Component, Property}; -use cli::Configuration; +use crate::cli::Configuration; pub trait CustomPathExt { fn metadata(&self) -> io::Result; @@ -23,9 +23,13 @@ pub trait CustomPathExt { } impl CustomPathExt for path::Path { - fn metadata(&self) -> io::Result { fs::metadata(self) } + fn metadata(&self) -> io::Result { + fs::metadata(self) + } - fn exists(&self) -> bool { fs::metadata(self).is_ok() } + fn exists(&self) -> bool { + fs::metadata(self).is_ok() + } fn is_file(&self) -> bool { fs::metadata(self).map(|s| s.is_file()).unwrap_or(false) @@ -40,27 +44,24 @@ impl CustomPathExt for path::Path { } pub fn handle_process(process: &mut process::Child) -> io::Result<()> { - let exitcode = try!(process.wait()); + let exitcode = process.wait()?; if !exitcode.success() { return Err(io::Error::new( io::ErrorKind::Other, - format!("{}", exitcode) + format!("{}", exitcode), )); }; Ok(()) } - pub struct IndexIterator { - linebuffer: Vec + linebuffer: Vec, } impl IndexIterator { fn new(output: &String) -> IndexIterator { let rv = output.split('\n').map(|x| x.to_string()).collect(); - IndexIterator { - linebuffer: rv - } + IndexIterator { linebuffer: rv } } } @@ -70,7 +71,7 @@ impl Iterator for IndexIterator { fn next(&mut self) -> Option { match self.linebuffer.pop() { Some(x) => Some(IndexItem::new(x)), - None => None + None => None, } } } @@ -78,7 +79,7 @@ impl Iterator for IndexIterator { pub struct IndexItem { pub email: String, pub name: String, - pub filepath: Option + pub filepath: Option, } impl IndexItem { @@ -90,35 +91,40 @@ impl IndexItem { name: parts.next().unwrap_or("").to_string(), filepath: match parts.next() { Some(x) => Some(path::PathBuf::from(x)), - None => None - } + None => None, + }, } } } pub struct Contact { pub component: Component, - pub path: path::PathBuf + pub path: path::PathBuf, } impl Contact { pub fn from_file>(path: P) -> io::Result { - let mut contact_file = try!(fs::File::open(&path)); + let mut contact_file = fs::File::open(&path)?; let contact_string = { let mut x = String::new(); - try!(contact_file.read_to_string(&mut x)); + contact_file.read_to_string(&mut x)?; x }; let item = match parse_component(&contact_string[..]) { Ok(x) => x, - Err(e) => return Err(io::Error::new( - io::ErrorKind::Other, - format!("Error while parsing contact: {}", e) - )) + Err(e) => { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("Error while parsing contact: {}", e), + )) + } }; - Ok(Contact { component: item, path: path.as_ref().to_owned() }) + Ok(Contact { + component: item, + path: path.as_ref().to_owned(), + }) } pub fn generate(fullname: Option<&str>, email: Option<&str>, dir: &path::Path) -> Contact { @@ -129,26 +135,26 @@ impl Contact { uid = Uuid::new_v4().hyphenated().to_string(); contact_path = dir.join(&format!("{}.vcf", uid)); if !(*contact_path).exists() { - break + break; } - }; + } (uid, contact_path) }; - Contact { path: contact_path, component: generate_component(uid.into(), fullname, email) } + Contact { + path: contact_path, + component: generate_component(uid.into(), fullname, email), + } } pub fn write_create(&self) -> io::Result<()> { let string = write_component(&self.component); let af = AtomicFile::new(&self.path, DisallowOverwrite); - try!(af.write(|f| { - f.write_all(string.as_bytes()) - })); + af.write(|f| f.write_all(string.as_bytes()))?; Ok(()) } } - fn generate_component(uid: String, fullname: Option<&str>, email: Option<&str>) -> Component { let mut comp = Component::new("VCARD"); @@ -156,39 +162,40 @@ fn generate_component(uid: String, fullname: Option<&str>, email: Option<&str>) match fullname { Some(x) => comp.push(Property::new("FN", x)), - None => () + None => (), }; match email { Some(x) => comp.push(Property::new("EMAIL", x)), - None => () + None => (), }; comp.push(Property::new("UID", &uid[..])); comp } pub fn index_query<'a>(config: &Configuration, query: &str) -> io::Result { - let mut process = try!( - command_from_config(&config.grep_cmd[..]) + let mut process = command_from_config(&config.grep_cmd[..]) .arg(&query[..]) .arg(&config.index_path) .stdin(process::Stdio::piped()) .stdout(process::Stdio::piped()) .stderr(process::Stdio::inherit()) - .spawn()); + .spawn()?; - try!(handle_process(&mut process)); + handle_process(&mut process)?; let stream = match process.stdout.as_mut() { Some(x) => x, - None => return Err(io::Error::new( - io::ErrorKind::Other, - "Failed to get stdout from grep process.", - )) + None => { + return Err(io::Error::new( + io::ErrorKind::Other, + "Failed to get stdout from grep process.", + )) + } }; let mut output = String::new(); - try!(stream.read_to_string(&mut output)); + stream.read_to_string(&mut output)?; Ok(IndexIterator::new(&output)) } @@ -196,26 +203,28 @@ pub fn index_query<'a>(config: &Configuration, query: &str) -> io::Result io::Result> { let mut rv: HashSet = HashSet::new(); - rv.extend( - try!(index_query(config, query)).filter_map(|x| x.filepath) - ); + rv.extend(index_query(config, query)?.filter_map(|x| x.filepath)); Ok(rv) } pub fn index_item_from_contact(contact: &Contact) -> io::Result { let name = match contact.component.get_only("FN") { Some(name) => name.value_as_string(), - None => return Err(io::Error::new( - io::ErrorKind::Other, - "No name found.", - )) + None => return Err(io::Error::new(io::ErrorKind::Other, "No name found.")), }; let emails = contact.component.get_all("EMAIL"); let mut rv = String::new(); for email in emails.iter() { - rv.push_str(&format!("{}\t{}\t{}\n", email.value_as_string(), name, contact.path.display())[..]); - }; + rv.push_str( + &format!( + "{}\t{}\t{}\n", + email.value_as_string(), + name, + contact.path.display() + )[..], + ); + } Ok(rv) } @@ -223,8 +232,8 @@ pub fn index_item_from_contact(contact: &Contact) -> io::Result { pub fn parse_from_header<'a>(s: &'a String) -> (Option<&'a str>, Option<&'a str>) { let mut split = s.rsplitn(2, '<'); let email = match split.next() { - Some(x) => Some(x.trim_right_matches('>')), - None => Some(&s[..]) + Some(x) => Some(x.trim_end_matches('>')), + None => Some(&s[..]), }; let name = split.next(); (name, email) @@ -237,12 +246,12 @@ pub fn read_sender_from_email(email: &str) -> Option { match parser.consume_header() { Some(header) => { if header.name == "From" { - return header.get_value().ok() + return header.get_value().ok(); }; - }, - None => return None + } + None => return None, }; - }; + } None } @@ -250,18 +259,19 @@ pub fn read_sender_from_email(email: &str) -> Option { pub fn add_contact_from_email(contact_dir: &path::Path, email_input: &str) -> io::Result { let from_header = match read_sender_from_email(email_input) { Some(x) => x, - None => return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Couldn't find From-header in email.", - )) + None => { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Couldn't find From-header in email.", + )) + } }; let (fullname, email) = parse_from_header(&from_header); let contact = Contact::generate(fullname, email, contact_dir); - try!(contact.write_create()); + contact.write_create()?; Ok(contact) } - fn command_from_config(config_val: &str) -> process::Command { let mut parts = config_val.split(' '); let main = parts.next().unwrap();