commit 0ff97907bcc6db6fc1e496bbf50478a158bd7d26 Author: EvilMuffinHa Date: Sun Jun 12 20:17:24 2022 -0400 its all unwrap? always has been diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..1e2c22b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,794 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" +dependencies = [ + "memchr 0.1.11", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "crossbeam-utils" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "directories" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +dependencies = [ + "libc", + "redox_users 0.3.5", + "winapi 0.3.9", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users 0.4.0", + "winapi 0.3.9", +] + +[[package]] +name = "enquote" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c36cb11dbde389f4096111698d8b567c0720e3452fd5ac3e6b4e47e1939932" +dependencies = [ + "thiserror", +] + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "git2" +version = "0.13.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" + +[[package]] +name = "libgit2-sys" +version = "0.12.26+1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libssh2-sys" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "memchr" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr 2.4.1", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom 0.1.16", + "redox_syscall 0.1.57", + "rust-argon2", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom 0.2.4", + "redox_syscall 0.2.10", +] + +[[package]] +name = "regex" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" +dependencies = [ + "aho-corasick", + "memchr 0.1.11", + "regex-syntax", + "thread_local", + "utf8-ranges", +] + +[[package]] +name = "regex-syntax" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "rust-ini" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac66e816614e124a692b6ac1b8437237a518c9155a3aacab83a373982630c715" + +[[package]] +name = "rustache" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86de9443c1a5618e0d51bbd8eb6227ead9916446eb8952575a70d1ef7e00209" +dependencies = [ + "regex", + "rustc-serialize", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + +[[package]] +name = "themectl" +version = "0.1.0" +dependencies = [ + "ansi_term", + "clap", + "directories", + "git2", + "rustache", + "toml", + "url", + "wallpaper", + "yaml-rust", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" +dependencies = [ + "kernel32-sys", + "libc", +] + +[[package]] +name = "thread_local" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" +dependencies = [ + "thread-id", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf8-ranges" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wallpaper" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0547c84bf49b1096b20ce49736b86cd27f8225fc426665d3fba19e71e44c4d46" +dependencies = [ + "dirs", + "enquote", + "rust-ini", + "winapi 0.3.9", + "winreg", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +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.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16cdb3898397cf7f624c294948669beafaeebc5577d5ec53d0afb76633593597" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..57479a2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "themectl" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "3.0.14", features = ['derive']} +wallpaper = { version = "3.2" } +rustache = { version = "^0.1" } +toml = { version = "0.5" } +yaml-rust = { version = "^0.4" } +directories = { version = "4.0" } +url = { version = "2.2" } +git2 = { version = "0.13.25" } +ansi_term = { version = "0.12" } diff --git a/README.md b/README.md new file mode 100644 index 0000000..e2eeb68 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Theme Control + + +### Base16 builder and theme applier + + +See examples for how to use diff --git a/examples/themectl/config.toml b/examples/themectl/config.toml new file mode 100644 index 0000000..8ba4504 --- /dev/null +++ b/examples/themectl/config.toml @@ -0,0 +1,9 @@ + +post = "echo 'after theme apply'" +pre = "echo 'before theme apply'" + + +[apps] +kitty = "~/kitty.conf" +vim = { file = "~/theme.vim", post = "echo 'after vim theme'", pre = "echo 'before vim theme'" } +test = { file = '~/test', post = "cat $HOME/test" } diff --git a/examples/themectl/schemes/oceanicnext.yaml b/examples/themectl/schemes/oceanicnext.yaml new file mode 100644 index 0000000..2c3230f --- /dev/null +++ b/examples/themectl/schemes/oceanicnext.yaml @@ -0,0 +1,18 @@ +scheme: "OceanicNext" +author: "https://github.com/voronianski/oceanic-next-color-scheme" +base00: "1B2B34" +base01: "343D46" +base02: "4F5B66" +base03: "65737E" +base04: "A7ADBA" +base05: "C0C5CE" +base06: "CDD3DE" +base07: "D8DEE9" +base08: "EC5f67" +base09: "F99157" +base0A: "FAC863" +base0B: "99C794" +base0C: "5FB3B3" +base0D: "6699CC" +base0E: "C594C5" +base0F: "AB7967" diff --git a/examples/themectl/sources.toml b/examples/themectl/sources.toml new file mode 100644 index 0000000..dd2f64b --- /dev/null +++ b/examples/themectl/sources.toml @@ -0,0 +1,7 @@ +[schemes] +local = [ "~/.config/themectl/schemes" ] +sources = [ "https://github.com/chriskempson/base16-schemes-source" ] + +[templates] +local = [ "~/.config/themectl/templates" ] +sources = [ "https://github.com/chriskempson/base16-templates-source" ] diff --git a/examples/themectl/templates/test.mustache b/examples/themectl/templates/test.mustache new file mode 100644 index 0000000..d5805fc --- /dev/null +++ b/examples/themectl/templates/test.mustache @@ -0,0 +1,3 @@ +{{scheme-name}} +{{base00-hex}} + diff --git a/src/builder.rs b/src/builder.rs new file mode 100644 index 0000000..6378448 --- /dev/null +++ b/src/builder.rs @@ -0,0 +1,177 @@ +use git2::Repository; +use std::fs::{self, File}; +use std::io::{self, Read, Write}; +use std::path::Path; +use toml::Value; +use yaml_rust::YamlLoader; + +pub fn download_sources(data: &Path, store: &Path, cache: &Path) -> Result<(), io::Error> { + + if !data.exists() { + + fs::create_dir_all(data.parent().unwrap())?; // The unwraps should not be panicking + + let mut file = File::create(data)?; + + file.write_all( + b"[schemes] +local = [ \"~/.config/themectl/schemes\" ] +sources = [ \"https://github.com/chriskempson/base16-schemes-source\" ] + +[templates] +local = [ \"~/.config/themectl/templates\" ] +sources = [ \"https://github.com/chriskempson/base16-templates-source\" ] +", + )?; + } + + if !store.exists() { + fs::create_dir_all(store)?; + fs::create_dir_all(store.join("schemes"))?; + fs::create_dir_all(store.join("templates"))? + } + + + let data = fs::read_to_string(data)? + .parse::()?; + + for source in data + .get("schemes") + .unwrap_or(&Value::String("".to_string())) + .get("sources") + .unwrap_or(&Value::Array([].to_vec())) + .as_array() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))? + .iter() + { + + let src = source + .as_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))?; + + println!("Retrieving from {}...", src); + + git_get(src, &cache.join("schemes"))?; + + let yml = yaml_from_file(&cache.join("schemes/list.yaml"))?; + + for (_name, url) in yml[0] + .as_hash() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect source list format"))? + .iter() { + + git_get(url.as_str().ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect url for source."))?, + &cache.join("gitschemes"))?; + + let dict = fs::read_dir(&cache.join("gitschemes"))? + .into_iter() + .filter(|x| + ["yml", "yaml"].contains(&(match x.as_ref().unwrap().path().extension() { + Some(a) => a.to_str().unwrap(), + None => "" // All these unwraps shouldn't panic, if they do something is very wrong + }))) + .map(|x| x.unwrap().path().into_os_string().into_string().unwrap()) + .collect::>(); + + for path in dict { + if fs::copy( + path.clone(), + store + .join("schemes") + .join(Path::new(&path).file_name().unwrap()), + ) + .is_ok() + {}; + } + } + } + + for source in data + .get("templates") + .unwrap_or(&Value::String("".to_string())) + .get("sources") + .unwrap_or(&Value::Array([].to_vec())) + .as_array() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))? + .iter() + { + + let src = source + .as_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))?; + + println!("Retrieving from {}...", src); + + git_get(src, &cache.join("template"))?; + + let yml = yaml_from_file(&cache.join("template/list.yaml"))?; + + for (name, url) in yml[0] + .as_hash() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect source list format"))? + .iter() { + + + git_get(url.as_str().ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect url for source."))?, + &cache.join("gittemplates"))?; + + let dict = fs::read_dir(&cache.join("gittemplates/templates"))? + .into_iter() + .filter(|x| + ["mustache"].contains(&(match x.as_ref().unwrap().path().extension() { + Some(a) => a.to_str().unwrap(), + None => "" // All these unwraps shouldn't panic, if they do something is very wrong + }))) + .map(|x| x.unwrap().path().into_os_string().into_string().unwrap()) + .collect::>(); + + for path in dict { + if fs::copy( + path.clone(), + store + .join("templates") + .join(format!("{}-{}", name + .as_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect template format"))?, + Path::new(&path).file_name().unwrap().to_str().unwrap() + ).replace("-default", ""))) + .is_ok() + {}; + + + } + + } + } + + Ok(()) +} + +pub fn clean(store: &Path) -> Result<(), io::Error> { + fs::remove_dir_all(store.join("schemes"))?; + fs::remove_dir_all(store.join("templates"))?; + fs::create_dir_all(store.join("schemes"))?; + fs::create_dir_all(store.join("templates"))?; + + Ok(()) +} + +fn git_get(url: &str, path: &Path) -> Result<(), io::Error> { + let dir = path.as_os_str().to_str().ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Path not found."))?; + + if fs::remove_dir_all(dir).is_ok() {}; + Repository::clone(url, dir).expect("Failed to clone. "); + + Ok(()) +} + +pub fn yaml_from_file(file: &Path) -> Result, io::Error> { + let mut f = File::open(file)?; + let mut string = String::new(); + f.read_to_string(&mut string).unwrap(); + match YamlLoader::load_from_str(&string) { + Ok(x) => Ok(x), + Err(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid yaml.")) + } +} + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d148a93 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,85 @@ +extern crate yaml_rust; + +mod builder; +mod theme; +mod preview; + +use builder::{clean, download_sources}; +use clap::{Parser, Subcommand}; +use directories::BaseDirs; +use theme::{apply, list}; +use preview::{preview}; + +// TODO: When accessing elements in the source.toml file, it will panic if it doesn't exist +// TODO: Make error parsing / checking better overall: use ?, return Results and parse them in the +// end and have better error output instead of panic + +#[derive(Parser, Debug)] +struct Args { + #[clap(subcommand)] + command: Commands, +} + +#[derive(Subcommand, Debug)] +enum Commands { + /// Lists all themes + List { + /// Name of source to list themes from + #[clap(short, long)] + source: Option, + }, + /// List all templates + Template { + #[clap(short, long)] + source: Option, + }, + /// Applies themes + Apply { + /// Builds files from config and applies a theme of your choice + theme: Option, + }, + /// Update sources + Update {}, + /// Cleans source directories + Clean {}, + /// Preview Colors + Preview { + /// Preview specific theme + #[clap(short, long)] + theme: Option, + } +} + +fn main() { + let options = Args::parse(); + + let base_dirs = BaseDirs::new().expect("Could not find configuration folder."); // Shouldn't happen? + + let data_path = base_dirs.data_dir().join("themectl"); + + let config = base_dirs.config_dir().join("themectl/config.toml"); + + let sources = base_dirs.config_dir().join("themectl/sources.toml"); + let cache = base_dirs.cache_dir().join("themectl"); + + match &options.command { + Commands::Clean {} => { + clean(&data_path).unwrap(); + } + Commands::Update {} => { + download_sources(&sources, &data_path, &cache).unwrap(); + } + Commands::Apply { theme } => { + apply(&config, &data_path, &sources, theme).unwrap(); + } + Commands::List { source } => { + list(&sources, &data_path, source, "schemes").unwrap(); + } + Commands::Template { source } => { + list(&sources, &data_path, source, "templates").unwrap(); + } + Commands::Preview { theme } => { + preview(&data_path, &sources, theme.clone()).unwrap(); + } + } +} diff --git a/src/preview.rs b/src/preview.rs new file mode 100644 index 0000000..a56b1e9 --- /dev/null +++ b/src/preview.rs @@ -0,0 +1,123 @@ +use std::process::Command; +use ansi_term::Color::RGB; +use std::collections::HashMap; +use crate::builder::yaml_from_file; +use std::path::Path; +use std::io; +use std::io::{Read}; +use toml::{Value, map::Map}; +use std::fs; + +pub fn preview(store: &Path, data: &Path, theme: Option) -> Result<(), io::Error> { + if Command::new("clear").status().is_ok() {}; + + let mut stdin = io::stdin(); + + let path = match theme { + Some(x) => { + let mut schemes: HashMap = HashMap::new(); + + let data = fs::read_to_string(data)? + .parse::()?; + + for local in data + .get("schemes") + .unwrap_or(&Value::Table(Map::new())) + .get("local") + .unwrap_or(&Value::Array([].to_vec())) + .as_array() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))? + .iter() + { + let dict = fs::read_dir(Path::new( + &local.as_str().unwrap().replace("~", env!("HOME")), + ))? + .map(|x| String::from(x.unwrap().path().to_str().unwrap())) + .collect::>(); + + for i in dict { + schemes.insert(Path::new(&i).file_stem().unwrap().to_str().unwrap().to_string(), + i.clone()); + } + + } + + let dict = fs::read_dir(&store.join("schemes"))? + .map(|x| String::from(x.unwrap().path().to_str().unwrap())) // This shouldn't error + .collect::>(); + + + for i in dict { + schemes.insert(Path::new(&i).file_stem().unwrap().to_str().unwrap().to_string(), + i.clone()); + } + + + store.join("schemes").join(schemes.get(&x) + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Invalid theme"))? + ) + } + None => store.join("current.yaml") + }; + let yaml = &yaml_from_file(&path)?[0]; + + let mut colors: HashMap = HashMap::new(); + + for (a, v) in yaml + .as_hash() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Error reading theme file."))? + .iter() { + + let val = v.as_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Error reading theme file."))? + .to_string(); + + match a.as_str().unwrap() { + "scheme" => (), + "author" => (), + + _ => { + colors.insert( + i8::from_str_radix( + &a.as_str().unwrap()[4..], 16) + .unwrap() + , [ + u8::from_str_radix(&val[0..2].to_string(), 16).unwrap(), + u8::from_str_radix(&val[2..4].to_string(), 16).unwrap(), + u8::from_str_radix(&val[4..6].to_string(), 16).unwrap(), + ]); + } + } + } + + + println!(); + for i in 0..8 { + print!("{}", + RGB(colors[&i][0], colors[&i][1], colors[&i][2]).on(RGB(colors[&i][0], colors[&i][1], colors[&i][2])).paint(" ")); + } + println!(); + + for i in 0..8 { + print!("{}", + RGB(colors[&i][0], colors[&i][1], colors[&i][2]).on(RGB(colors[&i][0], colors[&i][1], colors[&i][2])).paint(" ")); + } + println!(); + + for i in 8..16 { + print!("{}", + RGB(colors[&i][0], colors[&i][1], colors[&i][2]).on(RGB(colors[&i][0], colors[&i][1], colors[&i][2])).paint(" ")); + } + println!(); + + for i in 8..16 { + print!("{}", + RGB(colors[&i][0], colors[&i][1], colors[&i][2]).on(RGB(colors[&i][0], colors[&i][1], colors[&i][2])).paint(" ")); + } + println!(); + println!(); + + stdin.read_exact(&mut [0u8]).unwrap(); + + Ok(()) +} diff --git a/src/theme.rs b/src/theme.rs new file mode 100644 index 0000000..3b0cd38 --- /dev/null +++ b/src/theme.rs @@ -0,0 +1,344 @@ +use std::collections::HashMap; +use std::fs; +use std::fs::File; +use std::io::BufWriter; +use std::path::Path; +use std::process::Command; +use toml::{Value, map::Map}; +use rustache::{HashBuilder, Render}; +use crate::builder::{yaml_from_file}; +use std::io; + +pub fn apply(config: &Path, store: &Path, data: &Path, source: &Option) -> Result<(), io::Error> { + match source { + Some(st) => { + apply_theme(config, store, data, st.to_string())?; + } + + None => { + list(data, store, &None, "schemes")?; + } + } + + Ok(()) +} + +pub fn list(data: &Path, store: &Path, source: &Option, typ: &str) -> Result<(), io::Error> { + + let data = fs::read_to_string(data)? + .parse::()?; + + match source { + + Some(st) => { + if st == "sources" { + + println!("Source {}: ", typ); + + let dict = fs::read_dir(&store.join(typ))? + .map(|x| String::from(x.unwrap().path().file_stem().unwrap().to_str().unwrap())) // This shouldn't error + .collect::>(); + + for i in dict { + println!(" - {}", i); + } + + } else if st == "local" { + + println!("Custom {}: ", typ); + + for local in data + .get(typ) + .unwrap_or(&Value::Table(Map::new())) + .get("local") + .unwrap_or(&Value::Array([].to_vec())) + .as_array() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))? + .iter() + { + + let dict = fs::read_dir(Path::new( + &local.as_str().unwrap().replace("~", env!("HOME")), + ))? + .map(|x| String::from(x.unwrap().path().file_stem().unwrap().to_str().unwrap())) + .collect::>(); + + for i in dict { + println!(" - {}", i); + } + } + + } else { + println!("Please use a valid option (sources, local). "); + } + } + + None => { + + println!("Source {}: ", typ); + + let dict = fs::read_dir(&store.join(typ))? + .map(|x| String::from(x.unwrap().path().file_stem().unwrap().to_str().unwrap())) + .collect::>(); + + for i in dict { + println!(" - {}", i); + } + + println!("\nCustom {}: ", typ); + + for local in data + .get(typ) + .unwrap_or(&Value::Table(Map::new())) + .get("local") + .unwrap_or(&Value::Array([].to_vec())) + .as_array() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))? + .iter() + { + + let dict = fs::read_dir(Path::new( + &local.as_str().unwrap().replace("~", env!("HOME")), + ))? + .map(|x| String::from(x.unwrap().path().file_stem().unwrap().to_str().unwrap())) + .collect::>(); + + for i in dict { + println!(" - {}", i); + } + + } + } + } + Ok(()) +} + +fn apply_theme(config: &Path, store: &Path, data: &Path, theme: String) -> Result<(), io::Error> { + + let config = fs::read_to_string(config)? + .parse::()?; + + let data = fs::read_to_string(data)? + .parse::()?; + + let mut templates: HashMap = HashMap::new(); + + for local in data + .get("templates") + .unwrap_or(&Value::Table(Map::new())) + .get("local") + .unwrap_or(&Value::Array([].to_vec())) + .as_array() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))? + .iter() + { + let dict = fs::read_dir(Path::new( + &local.as_str().unwrap().replace("~", env!("HOME")), + ))? + .map(|x| String::from(x.unwrap().path().to_str().unwrap())) + .collect::>(); + + for i in dict { + templates.insert(Path::new(&i).file_stem().unwrap().to_str().unwrap().to_string(), + i.clone()); + } + + } + + let dict = fs::read_dir(&store.join("templates"))? + .map(|x| String::from(x.unwrap().path().to_str().unwrap())) // This shouldn't error + .collect::>(); + + + for i in dict { + templates.insert(Path::new(&i).file_stem().unwrap().to_str().unwrap().to_string(), + i.clone()); + } + + let mut schemes: HashMap = HashMap::new(); + + for local in data + .get("schemes") + .unwrap_or(&Value::Table(Map::new())) + .get("local") + .unwrap_or(&Value::Array([].to_vec())) + .as_array() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Incorrect sources format"))? + .iter() + { + let dict = fs::read_dir(Path::new( + &local.as_str().unwrap().replace("~", env!("HOME")), + ))? + .map(|x| String::from(x.unwrap().path().to_str().unwrap())) + .collect::>(); + + for i in dict { + schemes.insert(Path::new(&i).file_stem().unwrap().to_str().unwrap().to_string(), + i.clone()); + } + + } + + let dict = fs::read_dir(&store.join("schemes"))? + .map(|x| String::from(x.unwrap().path().to_str().unwrap())) // This shouldn't error + .collect::>(); + + + for i in dict { + schemes.insert(Path::new(&i).file_stem().unwrap().to_str().unwrap().to_string(), + i.clone()); + } + + let slug: String = schemes.get(&theme) + .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Theme not found."))? + .clone(); + + fs::copy(Path::new(&slug), &store.join("current.yaml"))?; + + let yaml = &yaml_from_file(Path::new(&slug))?[0]; + let mut name = String::new(); + let mut author = String::new(); + + let mut colors: HashMap = HashMap::new(); + + for (a, v) in yaml + .as_hash() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Error reading theme file."))? + .iter() { + + let val = v.as_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Error reading theme file."))? + .to_string(); + + match a.as_str().unwrap() { + "scheme" => name = val, + "author" => author = val, + + _ => { + colors.insert(a.as_str().unwrap().to_string(), val); + } + } + } + + + if Command::new("sh") + .arg("-c") + .arg(config.get("pre") + .unwrap_or(&Value::String("".to_string())) + .as_str().unwrap_or("")) + .spawn() + .is_ok() + {}; + + for (key, options) in config.get("apps") + + .unwrap_or(&Value::Table(Map::new())) + .as_table() + .unwrap() + .into_iter() { + + let key = key.as_str(); + let file = match options.as_table() { + Some(v) => v.get("file") + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, format!("Couldn't find file option for {}",key)))? + .as_str() + .unwrap() + .replace("~", env!("HOME")), + None => options.as_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, format!("Couldn't find file option for {}",key)))? + .replace("~", env!("HOME")), + }; + + // We have key -> Here check if key exists as a name in templates variable (String: String) + // where it is TemplateName: TemplateFile + + templates.keys() + .find(|&x| key == x) + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, format!("No key found: {}", key)))?; + + if Command::new("sh") + .arg("-c") + .arg(options + .as_table() + .unwrap_or(&Map::new()) + .get("pre") + .unwrap_or(&Value::String("".to_string())) + .as_str() + .unwrap_or("")) + .spawn() + .is_ok() + {}; + + // Here we want to parse the mustache file, and write it to the final file + // (open template file + save mustache to string) + // Copy in base16 colors in + // Write to `file` variable + + let mustache = fs::read_to_string(templates.get(key).unwrap())?; // shouldn't error + + // Need to detect these errors + let mut musthash = HashBuilder::new(); + musthash = musthash.insert("scheme-slug", slug.as_ref()); + musthash = musthash.insert("scheme-name", name.as_ref()); + musthash = musthash.insert("scheme-author", author.as_ref()); + for (b, c) in &colors { + musthash = musthash.insert(b.to_string() + "-hex", c.as_ref()); + + let red = c[0..2].to_string(); + musthash = musthash.insert(b.to_string() + "-hex-r", red.as_ref()); + let red = i32::from_str_radix(c[0..2].as_ref(), 16).unwrap(); + musthash = musthash.insert(b.to_string() + "-rgb-r", red); + musthash = musthash.insert(b.to_string() + "-dec-r", red as f64 / 255.0); + + let green = c[2..4].to_string(); + musthash = musthash.insert(b.to_string() + "-hex-g", green.as_ref()); + let green = i32::from_str_radix(c[2..4].as_ref(), 16).unwrap(); + musthash = musthash.insert(b.to_string() + "-rgb-g", green); + musthash = musthash.insert(b.to_string() + "-dec-g", green as f64 / 255.0); + + let blue = c[4..6].to_string(); + musthash = musthash.insert(b.to_string() + "-hex-b", blue.as_ref()); + let blue = i32::from_str_radix(c[4..6].as_ref(), 16).unwrap(); + musthash = musthash.insert(b.to_string() + "-rgb-b", blue); + musthash = musthash.insert(b.to_string() + "-dec-b", blue as f64 / 255.0); + + musthash = musthash.insert( + b.to_string() + "-hex-bgr", + format!("{}{}{}", blue, green, red), + ); + } + + if let Some(x) = Path::new(file.clone().as_str()).parent() { + fs::create_dir_all(x)? + }; + + let f = File::create(file.clone())?; + let mut out = BufWriter::new(f); + musthash.render(&mustache, &mut out) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid template format."))?; + + if Command::new("sh") + .arg("-c") + .arg(options + .as_table() + .unwrap_or(&Map::new()) + .get("post") + .unwrap_or(&Value::String("".to_string())) + .as_str() + .unwrap_or("")) + .spawn() + .is_ok() + {}; + }; + + if Command::new("sh") + .arg("-c") + .arg(config.get("post") + .unwrap_or(&Value::String("".to_string())) + .as_str().unwrap_or("")) + .spawn() + .is_ok() + {}; + + Ok(()) +}