Skip to content

Commit 0e69e1d

Browse files
committed
✨ addd cli-candlestick-chart binary usage
1 parent da97062 commit 0e69e1d

5 files changed

Lines changed: 217 additions & 2 deletions

File tree

Cargo.lock

Lines changed: 53 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: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,21 @@ edition = "2021"
1414
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1515

1616
[dependencies]
17-
serde = { version = "1", features = ["derive"], optional = true }
1817
terminal_size = "0.1.17"
1918
colored = "2"
19+
serde = { version = "1", features = ["derive"], optional = true }
20+
clap = { version = "2.33.3", optional = true }
21+
serde_json = { version = "1.0.1", optional = true }
22+
csv = { version = "1.1", optional = true }
2023

2124
[dev-dependencies]
22-
csv = "1.1"
2325
reqwest = { version = "0.11", features = ["blocking", "json"] }
2426

27+
[[bin]]
28+
name = "cli-candlestick-chart"
29+
path = "src/bin/cli/main.rs"
30+
required-features = ["serde", "serde_json", "csv", "clap"]
31+
2532
[[example]]
2633
name = "basic-with-csv-parsing"
2734
required-features = ["serde"]

src/bin/cli/get_args.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use clap::{App, Arg};
2+
use std::str::FromStr;
3+
4+
pub enum ReadingMode {
5+
Stdin,
6+
CsvFile,
7+
}
8+
9+
impl FromStr for ReadingMode {
10+
type Err = &'static str;
11+
12+
fn from_str(s: &str) -> Result<Self, Self::Err> {
13+
match s {
14+
"Stdin" => Ok(ReadingMode::Stdin),
15+
"CsvFile" => Ok(ReadingMode::CsvFile),
16+
_ => Err("no match"),
17+
}
18+
}
19+
}
20+
21+
pub struct CliOptions {
22+
pub reading_mode: ReadingMode,
23+
pub file_path: Option<String>,
24+
pub chart_name: Option<String>,
25+
pub bear_color: Option<String>,
26+
pub bull_color: Option<String>,
27+
}
28+
29+
pub fn get_args() -> CliOptions {
30+
let matches = App::new(env!("CARGO_PKG_NAME"))
31+
.version(env!("CARGO_PKG_VERSION"))
32+
.author(env!("CARGO_PKG_AUTHORS"))
33+
.arg(
34+
Arg::with_name("READING_MODE")
35+
.short("r")
36+
.long("reading-mode")
37+
.help("Make the program reads and parse candles from stdin.")
38+
.possible_values(&["stdin", "csv-file", "json-file"])
39+
.takes_value(true)
40+
.required(true),
41+
)
42+
.arg(
43+
Arg::with_name("FILE")
44+
.short("f")
45+
.long("file")
46+
.help("File to read candles from, if reading-mode is `*-file.`")
47+
.takes_value(true),
48+
)
49+
.arg(
50+
Arg::with_name("CHART_NAME")
51+
.long("chart-name")
52+
.help("Sets the chart name.")
53+
.takes_value(true),
54+
)
55+
.arg(
56+
Arg::with_name("BEAR_COLOR")
57+
.long("bear-color")
58+
.help("Sets the descending candles color in hexadecimal.")
59+
.takes_value(true),
60+
)
61+
.arg(
62+
Arg::with_name("BULL_COLOR")
63+
.long("bull-color")
64+
.help("Sets the ascending candles color in hexadecimal.")
65+
.takes_value(true),
66+
)
67+
.get_matches();
68+
69+
return CliOptions {
70+
reading_mode: match matches.value_of("READING_MODE").unwrap() {
71+
"stdin" => ReadingMode::Stdin,
72+
"csv-file" => ReadingMode::CsvFile,
73+
_ => panic!("Invalid reading mode."),
74+
},
75+
file_path: matches.value_of("FILE").map(|s| s.to_string()),
76+
chart_name: matches.value_of("CHART_NAME").map(|s| s.to_string()),
77+
bear_color: matches.value_of("BEAR_COLOR").map(|s| s.to_string()),
78+
bull_color: matches.value_of("BULL_COLOR").map(|s| s.to_string()),
79+
};
80+
}

src/bin/cli/main.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use clap::{App, Arg};
2+
use cli_candlestick_chart::{Candle, Chart};
3+
use std::error::Error;
4+
use std::io::{self, BufRead};
5+
6+
mod utils;
7+
use utils::hexa_to_rgb;
8+
9+
mod get_args;
10+
use get_args::{get_args, ReadingMode};
11+
12+
fn parse_candles_from_stdin() -> Vec<Candle> {
13+
let stdin = io::stdin();
14+
15+
let mut stdin_lines = String::new();
16+
for line in stdin.lock().lines() {
17+
let line = line.expect("Could not read line from standard in");
18+
stdin_lines.push_str(&line);
19+
}
20+
21+
let candles: Vec<Candle> = serde_json::from_str(&stdin_lines).expect("Could not parse json");
22+
candles
23+
}
24+
25+
fn parse_candles_from_csv(filepath: &str) -> Result<Vec<Candle>, Box<dyn Error>> {
26+
let mut rdr = csv::Reader::from_path(filepath)?;
27+
let mut candles: Vec<Candle> = Vec::new();
28+
29+
for result in rdr.deserialize() {
30+
let candle: Candle = result?;
31+
candles.push(candle);
32+
}
33+
34+
Ok(candles)
35+
}
36+
37+
fn main() {
38+
let options = get_args();
39+
let mut candles: Vec<Candle> = Vec::new();
40+
41+
match options.reading_mode {
42+
ReadingMode::Stdin => {
43+
candles = parse_candles_from_stdin();
44+
}
45+
ReadingMode::CsvFile => {
46+
let filepath = options.file_path.expect("No file path provided.");
47+
candles = parse_candles_from_csv(&filepath).unwrap();
48+
}
49+
};
50+
51+
let mut chart = Chart::new(&candles);
52+
53+
if let Some(chart_name) = options.chart_name {
54+
chart.set_name(chart_name);
55+
}
56+
57+
if let Some(bear_color) = options.bear_color {
58+
let (r, g, b) = hexa_to_rgb(bear_color);
59+
chart.set_bear_color(r, g, b);
60+
}
61+
62+
if let Some(bull_color) = options.bull_color {
63+
let (r, g, b) = hexa_to_rgb(bull_color);
64+
chart.set_bull_color(r, g, b);
65+
}
66+
67+
chart.draw();
68+
}

src/bin/cli/utils.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub fn hexa_to_rgb(hex_code: String) -> (u8, u8, u8) {
2+
let hex_code = hex_code.trim_start_matches('#');
3+
let r = u8::from_str_radix(&hex_code[0..2], 16).unwrap();
4+
let g = u8::from_str_radix(&hex_code[2..4], 16).unwrap();
5+
let b = u8::from_str_radix(&hex_code[4..6], 16).unwrap();
6+
(r, g, b)
7+
}

0 commit comments

Comments
 (0)