Repository: peterheesterman/chit (language: rust)

Issue:
(feat) I want to see alternatives to the crate that i am looking up
**Is your feature request related to a problem? Please describe.**

I have a hard time knowing if the crate i am using is the most recent/recommended crate for something that i am trying to achieve

**Describe the solution you'd like**
I want chit to tell me alternatives for a given crate when i chit it.

**Describe alternatives you've considered**

The alternatives are to look at blog posts and find the info there. This should centralise it. 

**Additional context**
Suggested by a reddit user (BoastfulSquirrel)



Discussion / hints:
You could manually curate some from [here](https://github.com/rust-unofficial/awesome-rust/blob/master/README.md), but I don't think it's worth it.
I like this as a way to just test if people care. Might need to get a more scalable way later on but we shall see. I am gonna shove it in here and use it from in chit. **https://github.com/peterheesterman/alt-rs** 

When i have some time i might do the top 100 from `rust-unofficial/awesome-rust` and see if people care enough to contribute by putting in a call to action if there is a crate without alternative/options listed. 😂 
I'm confused, why is that a Rust crate? Wouldn't it make sense to have a data file (like a JSON) with crates and their alternatives?
I was thinking it would be something simple like that yes. I guess i can move it out of chit if i want to use if for something else one day, no need to make another crate. 🤷‍♂️ 

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cace92d..021cd74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
 
 # Change Log
 
+## 0.1.8 - Let the people speak
+ - Alternatives for some common crates
+ - Show up in the details section of the chit
+ 
 ## 0.1.7 - Keep it simple . . . for now
  - Add crate categories to the output
  - Add crate description to the output
diff --git a/Cargo.lock b/Cargo.lock
index 747e7e4..d3dc555 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -86,11 +86,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "chit"
-version = "0.1.7"
+version = "0.1.8"
 dependencies = [
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -632,6 +634,22 @@ name = "pkg-config"
 version = "0.3.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "proc-macro2"
+version = "0.4.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand"
 version = "0.6.5"
@@ -852,6 +870,16 @@ name = "serde"
 version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "serde_derive"
+version = "1.0.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "serde_json"
 version = "1.0.39"
@@ -903,6 +931,16 @@ name = "strsim"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "syn"
+version = "0.15.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "tempfile"
 version = "3.0.7"
@@ -1107,6 +1145,11 @@ name = "unicode-width"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "url"
 version = "1.7.2"
@@ -1263,6 +1306,8 @@ dependencies = [
 "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
 "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
 "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
+"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
+"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@@ -1287,6 +1332,7 @@ dependencies = [
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560"
+"checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79"
 "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
 "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2"
 "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
@@ -1295,6 +1341,7 @@ dependencies = [
 "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
 "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
+"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed"
 "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
@@ -1315,6 +1362,7 @@ dependencies = [
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
 "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
+"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
 "checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768"
 "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
diff --git a/Cargo.toml b/Cargo.toml
index 0aa6a68..92ac670 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "chit"
-version = "0.1.7"
+version = "0.1.8"
 authors = ["Peter Heesterman <heesterman.peter@gmail.com>"]
 edition = "2018"
 
@@ -15,4 +15,6 @@ license = "MIT"
 colored = "1.7"
 reqwest = "0.9"
 serde_json = "1.0"
+serde = "1.0"
+serde_derive = "1.0"
 clap = '2.32'
diff --git a/README.md b/README.md
index 3cc2aef..9ea260a 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ If not... [find out how!](https://doc.rust-lang.org/cargo/getting-started/instal
 
 `chit hex-buffer-serde` OR `chit --crate=hex-buffer-serde`
 
-<img src="https://github.com/peterheesterman/chit/blob/master/readme-images/chit-real.png?raw=true" width="474"  height="304"/>
+<img src="https://github.com/peterheesterman/chit/blob/master/readme-images/chit.png?raw=true" width="496"  height="386"/>
 
 `chit versions --crate=hex-buffer-serde`
 
diff --git a/alternatives.json b/alternatives.json
new file mode 100644
index 0000000..ab52148
--- /dev/null
+++ b/alternatives.json
@@ -0,0 +1,36 @@
+{
+  "description": "Index of rust crates that are alternatives to one another",
+  "crates": [
+    { "name": "diesel", "alternatives": ["rustorm"] },
+    { "name": "rustorm", "alternatives": ["diesel"] },
+    {"name":"actix-web","alternatives":["gotham","iron","nickel","rustful","rocket","rustless","saphir","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"clap","alternatives":["getopts","docopt","pirate"]},
+    {"name":"curl","alternatives":["reqwest","hyper"]},
+    {"name":"docopt","alternatives":["clap","getopts","pirate"]},
+    {"name":"env_logger","alternatives":["log4r","fern"]},
+    {"name":"fancy-regex","alternatives":["regex"]},
+    {"name":"fern","alternatives":["env_logger","log4r"]},
+    {"name":"getopts","alternatives":["clap","docopt","pirate"]},
+    {"name":"gotham","alternatives":["actix-web","iron","nickel","rustful","rocket","rustless","saphir","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"hyper","alternatives":["reqwest","curl"]},
+    {"name":"iron","alternatives":["actix-web","gotham","nickel","rustful","rocket","rustless","saphir","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"json","alternatives":["serde","jsonway"]},
+    {"name":"jsonway","alternatives":["serde","json"]},
+    {"name":"log4r","alternatives":["env_logger","fern"]},
+    {"name":"nickel","alternatives":["actix-web","gotham","iron","rustful","rocket","rustless","saphir","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"pirate","alternatives":["clap","getopts","docopt"]},
+    {"name":"regex","alternatives":["fancy-regex"]},
+    {"name":"reqwest","alternatives":["hyper","curl"]},
+    {"name":"rocket","alternatives":["actix-web","gotham","iron","nickel","rustful","rustless","saphir","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"rouille","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","rustless","saphir","sapper","tiny-http","tower-web","sincere","zap"]},
+    {"name":"rustful","alternatives":["actix-web","gotham","iron","nickel","rocket","rustless","saphir","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"rustless","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","saphir","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"saphir","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","rustless","sapper","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"sapper","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","rustless","saphir","tiny-http","rouille","tower-web","sincere","zap"]},
+    {"name":"serde","alternatives":["json","jsonway"]},
+    {"name":"sincere","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","rustless","saphir","sapper","tiny-http","rouille","tower-web","zap"]},
+    {"name":"tiny-http","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","rustless","saphir","sapper","rouille","tower-web","sincere","zap"]},
+    {"name":"tower-web","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","rustless","saphir","sapper","tiny-http","rouille","sincere","zap"]},
+    {"name":"zap","alternatives":["actix-web","gotham","iron","nickel","rustful","rocket","rustless","saphir","sapper","tiny-http","rouille","tower-web","sincere"]}
+  ]
+}
diff --git a/readme-images/chit-real.png b/readme-images/chit-real.png
deleted file mode 100644
index e45a198..0000000
Binary files a/readme-images/chit-real.png and /dev/null differ
diff --git a/readme-images/chit.png b/readme-images/chit.png
new file mode 100644
index 0000000..f25f8a7
Binary files /dev/null and b/readme-images/chit.png differ
diff --git a/src/chit/details/alternatives/mod.rs b/src/chit/details/alternatives/mod.rs
new file mode 100644
index 0000000..f1806f2
--- /dev/null
+++ b/src/chit/details/alternatives/mod.rs
@@ -0,0 +1,33 @@
+use std::fs::File;
+use std::path::Path;
+
+#[derive(Serialize, Deserialize)]
+pub struct Crate {
+    pub name: String,
+    pub alternatives: Vec<String>,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct Alternatives {
+    pub description: String,
+    pub crates: Vec<Crate>,
+}
+
+pub fn get_alternatives() -> Alternatives {
+    let json_file_path = Path::new("./alternatives.json");
+    let json_file = File::open(json_file_path).expect("file not found");
+    let alternatives: Alternatives =
+        serde_json::from_reader(json_file).expect("error while reading json");
+    alternatives
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn can_parse_alternatives() {
+        let alternatives = get_alternatives();
+        assert!(alternatives.crates.len() != 0)
+    }
+}
diff --git a/src/chit/details.rs b/src/chit/details/mod.rs
similarity index 75%
rename from src/chit/details.rs
rename to src/chit/details/mod.rs
index 225be4e..acb1bb6 100644
--- a/src/chit/details.rs
+++ b/src/chit/details/mod.rs
@@ -4,6 +4,8 @@ use super::crates;
 use super::extract;
 use super::format;
 
+mod alternatives;
+
 pub fn print_details(crate_name: String) {
     let mut width = format::get_width();
     println!("{} {}...", "Searching for".magenta(), &crate_name.blue());
@@ -29,16 +31,9 @@ pub fn print_details(crate_name: String) {
                 println!("{}", format::title_bar(width, &crate_name));
 
                 // Description
-                let chars: Vec<char> = fields.description.chars().collect();
-                let split = &chars.chunks(width)
-                        .map(|chunk| chunk.iter().collect::<String>())
-                            .collect::<Vec<_>>();
+                format::bounded_print(width, &fields.description);
 
-                for bit in split.iter() {
-                    format::print(bit.to_string());
-                }
-               
-                println!(""); 
+                println!("");
                 // Rating
                 let rating = extract::calculate_rating(&fields);
                 format::print_rating(rating);
@@ -76,6 +71,28 @@ pub fn print_details(crate_name: String) {
                     ));
                 }
 
+                // TODO: move to another file
+                // ---------------------------------------------------------
+                // TODO: Clean this up by making it less imparative
+                let mut found_alternative = false;
+                let alternatives = alternatives::get_alternatives();
+                'find: for i in 0..alternatives.crates.len() {
+                    if alternatives.crates[i].name == crate_name {
+                        let list_line = format!(
+                            "Alternatives: {}",
+                            alternatives.crates[i].alternatives.join(", ")
+                        );
+                        format::bounded_print(width, &list_line);
+                        found_alternative = true;
+                        break 'find;
+                    }
+                }
+
+                if !found_alternative {
+                    format::print("Alternatives: None listed - Know one? Make a PR!".to_string());
+                }
+                // ---------------------------------------------------------
+
                 format::print(keywords);
                 format::print(categories);
             }
diff --git a/src/chit/format.rs b/src/chit/format.rs
index 27613ce..a16a10c 100644
--- a/src/chit/format.rs
+++ b/src/chit/format.rs
@@ -51,3 +51,15 @@ pub fn print_rating(rating: usize) {
 fn n_character(count: usize, string: &str) -> String {
     string.repeat(count)
 }
+
+pub fn bounded_print(width: usize, text: &str) {
+    let chars: Vec<char> = text.chars().collect();
+    let split = &chars
+        .chunks(width)
+        .map(|chunk| chunk.iter().collect::<String>())
+        .collect::<Vec<_>>();
+
+    for bit in split.iter() {
+        print(bit.to_string());
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index 9b65ea8..2e906db 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,6 @@
+#[macro_use]
+extern crate serde_derive;
+
 use clap::{App, Arg, SubCommand};
 use colored::*;
 use std::env;
diff --git a/src/meta.rs b/src/meta.rs
index fd2ae64..999c273 100644
--- a/src/meta.rs
+++ b/src/meta.rs
@@ -1,5 +1,5 @@
 pub fn get_version() -> &'static str {
-    "0.1.7"
+    "0.1.8"
 }
 
 pub fn get_author() -> &'static str {


Test patch: