From 17683d999d73f9d060229653d0141e73f980d79f Mon Sep 17 00:00:00 2001 From: Joe Abbate Date: Thu, 3 Mar 2022 20:17:20 -0500 Subject: [PATCH] Add Colors --- Cargo.lock | 111 ++++++++++++++++++++++++++++++++++ Cargo.toml | 3 +- src/commands/list.rs | 139 ++++++++++++++++++++++++++----------------- 3 files changed, 198 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af55865..8fb8c69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,9 +90,12 @@ dependencies = [ "http", "isahc", "ncurses", + "rpassword", "serde", "serde_json", + "term", "url", + "users", ] [[package]] @@ -145,6 +148,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "encoding_rs" version = "0.8.29" @@ -212,6 +236,17 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "getrandom" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -484,6 +519,41 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "rpassword" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + [[package]] name = "ryu" version = "1.0.5" @@ -505,6 +575,20 @@ name = "serde" version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "serde_json" @@ -561,6 +645,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -667,6 +762,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -679,6 +784,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "wepoll-ffi" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index 0b8869f..b9ec785 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,10 +9,11 @@ edition = "2021" [dependencies] url = "2.2.2" serde_json = "1.0.71" -serde = "1.0.130" ncurses = "5.101.0" http = "0.2.5" rpassword = "5.0" users = "0.11.0" clap = { version = "3.1.6", features = ["cargo"] } isahc = { version = "1.6.0", features = ["json", "spnego"] } +serde = { version = "1.0.71", features = ["derive"] } +term = "0.7.0" diff --git a/src/commands/list.rs b/src/commands/list.rs index 6be084d..9652b3f 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -1,14 +1,78 @@ use clap::ArgMatches; use isahc::{HttpClient, ReadResponseExt, Request}; - +use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; +use std::fmt; +use std::io::prelude::*; use crate::api::APIError; use crate::api::API; +#[derive(Debug, Deserialize)] +struct Drinks { + machines: Vec, +} + +#[derive(Debug, Deserialize)] +struct Machine { + name: String, + display_name: String, + slots: Vec, +} + +impl fmt::Display for Machine { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{} ({})\n{}", + self.display_name, + self.name, + "=".repeat(self.display_name.len() + self.name.len() + 3) + ) + } +} + +#[derive(Debug, Deserialize)] +struct Slot { + item: Item, + number: u64, + empty: bool, + active: bool, + count: Option, +} + +impl fmt::Display for Slot { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}. {}{}", + self.number, + self.item, + match self.empty { + true => " [EMPTY]", + false => "", + } + ) + } +} + +#[derive(Debug, Deserialize)] +struct Item { + name: String, + price: u64, +} + +impl fmt::Display for Item { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} ({} Credits)", self.name, self.price) + } +} + pub fn list(matches: &ArgMatches, api: &mut API) -> Result<(), Box> { let token = api.get_token()?; + let mut term = term::stdout().unwrap(); + let client = HttpClient::new()?; let mut url = "https://drink.csh.rit.edu/drinks".to_string(); if let Some(machine) = matches.value_of("machine") { @@ -17,61 +81,28 @@ pub fn list(matches: &ArgMatches, api: &mut API) -> Result<(), Box = match drinks.as_object() { - Some(drinks) => drinks, - None => panic!("Fuck"), - }; - let machines: &Vec = match drinks.get("machines") { - Some(machines) => match machines.as_array() { - Some(machines) => machines, - None => return Err(Box::new(APIError::BadFormat)), - }, - None => { - eprintln!("Couldn't fetch machines! {:?}", drinks); - return Err(Box::new(APIError::BadFormat)); - } - }; - for machine in machines { - let machine: &Map = match machine.as_object() { - Some(machine) => machine, - None => panic!("Fuck!"), - }; - let display_name = match machine["display_name"].as_str() { - Some(name) => name.to_string(), - None => return Err(Box::new(APIError::BadFormat)), - }; - let name = match machine["name"].as_str() { - Some(name) => name.to_string(), - None => return Err(Box::new(APIError::BadFormat)), - }; - let subject_line = format!("{} ({})", display_name, name); - println!("{}", &subject_line); - println!("{}", "=".repeat(subject_line.len())); - let slots: &Vec = match machine["slots"].as_array() { - Some(slots) => slots, - None => return Err(Box::new(APIError::BadFormat)), - }; - for slot in slots { - let slot: &Map = match slot.as_object() { - Some(slot) => slot, - None => return Err(Box::new(APIError::BadFormat)), - }; - - let item: &Map = match slot["item"].as_object() { - Some(item) => item, - None => return Err(Box::new(APIError::BadFormat)), - }; - - let price = item["price"].as_u64().unwrap(); - let slot_number = slot["number"].as_u64().unwrap(); - let name = item["name"].as_str().unwrap(); - print!("{}. {} ({} Credits)", slot_number, name, price); - if slot["empty"].as_bool().unwrap() { - print!(" [EMPTY]"); + let drinks: Drinks = client.send(request)?.json()?; + for machine in drinks.machines { + term.fg(term::color::CYAN).unwrap(); + writeln!(term, "{}", machine).unwrap(); + for slot in machine.slots { + match slot.count { + Some(0) => term.fg(term::color::RED), + Some(_) => term.reset(), + None => { + if slot.empty || !slot.active { + term.fg(term::color::RED) + } else { + term.reset() + } + } } - println!(""); + .unwrap(); + writeln!(term, "{}", slot).unwrap(); } + println!(""); + term.reset().unwrap(); } + term.flush().unwrap(); return Ok(()); }