Initial commit

This commit is contained in:
4a656666 2022-02-11 16:56:27 -06:00
parent fb8edf220b
commit 862caed98b
2 changed files with 137 additions and 0 deletions

9
Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "progress"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
termsize = "0.1"

128
src/main.rs Normal file
View file

@ -0,0 +1,128 @@
use std::{process::exit, env::Args};
static DEFAULT_MAX: usize = 100;
static DEFAULT_WIDTH: usize = 80;
fn main() {
let args = std::env::args();
let config = match Config::new(args) {
Ok(v ) => v,
Err(e) => err(&e)
};
// [#####....] ---- 50%
let percent = config.val * 100 / config.max;
let percent_str = percent.to_string();
let after_bar = format!(" {} {}% ", "-".repeat(6 - percent_str.len()), percent_str);
let bar_len = config.width - after_bar.len();
let sep = bar_len * percent / 100;
let mut bar = String::new();
bar.push(if sep > 0 { config.first_char.1 } else { config.first_char.0 });
for i in 1..bar_len-1 {
bar.push(if sep > i { config.middle_char.1 } else { config.middle_char.0 });
}
bar.push(if sep > bar_len-1 { config.last_char.1 } else { config.last_char.0 });
println!("{}{}", bar, after_bar);
}
fn err(msg: &str) -> ! {
eprintln!("{}", msg);
show_help();
exit(1);
}
fn show_help() {
eprintln!("Usage: progress <value> [--max <max>] [--width <width>] [--fira]");
}
struct Config {
val: usize,
max: usize,
first_char: (char, char),
middle_char: (char, char),
last_char: (char, char),
width: usize
}
impl Config {
fn new(mut args: Args) -> Result<Config, String> {
args.next();
let mut val = None;
let mut max = None;
let mut first_char = ('[', '[');
let mut middle_char = ('.', '#');
let mut last_char = (']', ']');
let mut width = None;
while let Some(next) = args.next() {
if next.starts_with("--") {
if next == "--fira" {
first_char = ('\u{ee00}', '\u{ee03}');
middle_char = ('\u{ee01}', '\u{ee04}');
last_char = ('\u{ee02}', '\u{ee05}');
} else if next == "--max" {
if let Some(_) = max { return Err("can only provide 1 max".to_string()) }
let next = match args.next() {
Some(v) => v,
None => return Err("must provide a max after --max".to_string())
};
let max_result = next.parse();
match max_result {
Ok(v) => max = Some(v),
Err(_) => return Err("max must be a number".to_string())
}
} else if next == "--width" {
if let Some(_) = width { return Err("can only provide 1 width".to_string()) }
let next = match args.next() {
Some(v) => v,
None => return Err("must provide a width after --width".to_string())
};
let max_result = next.parse();
match max_result {
Ok(v) => width = Some(v),
Err(_) => return Err("width must be a number".to_string())
}
} else {
return Err(format!("unknown option `{}`", next));
}
} else {
if let Some(_) = val { return Err("can only provide 1 value".to_string()) }
let val_result = next.parse();
match val_result {
Ok(v) => val = Some(v),
Err(_) => return Err("max must be a number".to_string())
}
}
}
let val = match val {
Some(v) => v,
None => return Err("must provide a value".to_string())
};
let max = max.unwrap_or(DEFAULT_MAX);
if val > max {
return Err("value cannot be > max".to_string());
}
let width = width.unwrap_or_else(|| termsize::get().map_or(DEFAULT_WIDTH, |v| v.cols.into()));
if width < 11 {
return Err("window not wide enough".to_string());
}
Ok(Config {
val,
max,
first_char,
middle_char,
last_char,
width
})
}
}