Skip to content

Commit 17683d9

Browse files
committed
Add Colors
1 parent b18c39a commit 17683d9

File tree

3 files changed

+198
-55
lines changed

3 files changed

+198
-55
lines changed

Cargo.lock

Lines changed: 111 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ edition = "2021"
99
[dependencies]
1010
url = "2.2.2"
1111
serde_json = "1.0.71"
12-
serde = "1.0.130"
1312
ncurses = "5.101.0"
1413
http = "0.2.5"
1514
rpassword = "5.0"
1615
users = "0.11.0"
1716
clap = { version = "3.1.6", features = ["cargo"] }
1817
isahc = { version = "1.6.0", features = ["json", "spnego"] }
18+
serde = { version = "1.0.71", features = ["derive"] }
19+
term = "0.7.0"

src/commands/list.rs

Lines changed: 85 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,78 @@
11
use clap::ArgMatches;
22
use isahc::{HttpClient, ReadResponseExt, Request};
3-
3+
use serde::{Deserialize, Serialize};
44
use serde_json::{Map, Value};
5+
use std::fmt;
6+
use std::io::prelude::*;
57

68
use crate::api::APIError;
79
use crate::api::API;
810

11+
#[derive(Debug, Deserialize)]
12+
struct Drinks {
13+
machines: Vec<Machine>,
14+
}
15+
16+
#[derive(Debug, Deserialize)]
17+
struct Machine {
18+
name: String,
19+
display_name: String,
20+
slots: Vec<Slot>,
21+
}
22+
23+
impl fmt::Display for Machine {
24+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25+
write!(
26+
f,
27+
"{} ({})\n{}",
28+
self.display_name,
29+
self.name,
30+
"=".repeat(self.display_name.len() + self.name.len() + 3)
31+
)
32+
}
33+
}
34+
35+
#[derive(Debug, Deserialize)]
36+
struct Slot {
37+
item: Item,
38+
number: u64,
39+
empty: bool,
40+
active: bool,
41+
count: Option<u16>,
42+
}
43+
44+
impl fmt::Display for Slot {
45+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46+
write!(
47+
f,
48+
"{}. {}{}",
49+
self.number,
50+
self.item,
51+
match self.empty {
52+
true => " [EMPTY]",
53+
false => "",
54+
}
55+
)
56+
}
57+
}
58+
59+
#[derive(Debug, Deserialize)]
60+
struct Item {
61+
name: String,
62+
price: u64,
63+
}
64+
65+
impl fmt::Display for Item {
66+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67+
write!(f, "{} ({} Credits)", self.name, self.price)
68+
}
69+
}
70+
971
pub fn list(matches: &ArgMatches, api: &mut API) -> Result<(), Box<dyn std::error::Error>> {
1072
let token = api.get_token()?;
1173

74+
let mut term = term::stdout().unwrap();
75+
1276
let client = HttpClient::new()?;
1377
let mut url = "https://drink.csh.rit.edu/drinks".to_string();
1478
if let Some(machine) = matches.value_of("machine") {
@@ -17,61 +81,28 @@ pub fn list(matches: &ArgMatches, api: &mut API) -> Result<(), Box<dyn std::erro
1781
}
1882
let request = Request::get(url).header("Authorization", token).body(())?;
1983

20-
let drinks: Value = client.send(request)?.json()?;
21-
let drinks: &Map<String, Value> = match drinks.as_object() {
22-
Some(drinks) => drinks,
23-
None => panic!("Fuck"),
24-
};
25-
let machines: &Vec<Value> = match drinks.get("machines") {
26-
Some(machines) => match machines.as_array() {
27-
Some(machines) => machines,
28-
None => return Err(Box::new(APIError::BadFormat)),
29-
},
30-
None => {
31-
eprintln!("Couldn't fetch machines! {:?}", drinks);
32-
return Err(Box::new(APIError::BadFormat));
33-
}
34-
};
35-
for machine in machines {
36-
let machine: &Map<String, Value> = match machine.as_object() {
37-
Some(machine) => machine,
38-
None => panic!("Fuck!"),
39-
};
40-
let display_name = match machine["display_name"].as_str() {
41-
Some(name) => name.to_string(),
42-
None => return Err(Box::new(APIError::BadFormat)),
43-
};
44-
let name = match machine["name"].as_str() {
45-
Some(name) => name.to_string(),
46-
None => return Err(Box::new(APIError::BadFormat)),
47-
};
48-
let subject_line = format!("{} ({})", display_name, name);
49-
println!("{}", &subject_line);
50-
println!("{}", "=".repeat(subject_line.len()));
51-
let slots: &Vec<Value> = match machine["slots"].as_array() {
52-
Some(slots) => slots,
53-
None => return Err(Box::new(APIError::BadFormat)),
54-
};
55-
for slot in slots {
56-
let slot: &Map<String, Value> = match slot.as_object() {
57-
Some(slot) => slot,
58-
None => return Err(Box::new(APIError::BadFormat)),
59-
};
60-
61-
let item: &Map<String, Value> = match slot["item"].as_object() {
62-
Some(item) => item,
63-
None => return Err(Box::new(APIError::BadFormat)),
64-
};
65-
66-
let price = item["price"].as_u64().unwrap();
67-
let slot_number = slot["number"].as_u64().unwrap();
68-
let name = item["name"].as_str().unwrap();
69-
print!("{}. {} ({} Credits)", slot_number, name, price);
70-
if slot["empty"].as_bool().unwrap() {
71-
print!(" [EMPTY]");
84+
let drinks: Drinks = client.send(request)?.json()?;
85+
for machine in drinks.machines {
86+
term.fg(term::color::CYAN).unwrap();
87+
writeln!(term, "{}", machine).unwrap();
88+
for slot in machine.slots {
89+
match slot.count {
90+
Some(0) => term.fg(term::color::RED),
91+
Some(_) => term.reset(),
92+
None => {
93+
if slot.empty || !slot.active {
94+
term.fg(term::color::RED)
95+
} else {
96+
term.reset()
97+
}
98+
}
7299
}
73-
println!("");
100+
.unwrap();
101+
writeln!(term, "{}", slot).unwrap();
74102
}
103+
println!("");
104+
term.reset().unwrap();
75105
}
106+
term.flush().unwrap();
76107
return Ok(());
77108
}

0 commit comments

Comments
 (0)