feat: better error reporting

This commit is contained in:
Pihkaal
2024-03-25 23:50:20 +01:00
parent ac66044508
commit 1e6cf30fea
5 changed files with 84 additions and 48 deletions

View File

@@ -1,10 +1,10 @@
use core::panic;
use std::{fs, path::PathBuf};
use std::{any::type_name, fs, path::PathBuf};
use crossterm::style::Color;
use ini::configparser::ini::Ini;
use crate::{
eprintln_quit,
modes::debug,
rendering::color::{generate_gradient, parse_hex_color, ComputableColor},
};
@@ -21,46 +21,69 @@ const DEFAULT_CONFIG: &str = include_str!("default_config");
pub fn load_from_file(path: PathBuf, debug_mode: bool) -> Config {
let mut ini = Ini::new();
ini.load(&path.to_str().unwrap()).unwrap();
ini.load(
&path
.to_str()
.unwrap_or_else(|| eprintln_quit!("Invalid configuration path")),
)
.unwrap_or_else(|_| eprintln_quit!("Unable to parse configuration file"));
Config {
be_polite: ini.getbool("general", "polite").unwrap().unwrap(),
fps: ini.getuint("general", "fps").unwrap().unwrap(),
be_polite: get_ini_value(&ini, "general", "polite"),
fps: get_ini_value(&ini, "general", "fps"),
color: load_color(&ini, debug_mode),
time_format: ini.get("format", "time").unwrap(),
date_format: ini.get("format", "date").unwrap(),
time_format: get_ini_value(&ini, "format", "time"),
date_format: get_ini_value(&ini, "format", "date"),
}
}
pub fn write_default_config(path: PathBuf) -> () {
// Write default config file to target path
let parent = path.parent().unwrap();
let parent = path
.parent()
.unwrap_or_else(|| eprintln_quit!("Invalid configuration path"));
let _ = fs::create_dir_all(parent);
let _ = fs::write(path, DEFAULT_CONFIG);
}
fn get_ini_value<T: std::str::FromStr>(ini: &Ini, section: &str, key: &str) -> T {
if let Some(value) = ini.get(section, key) {
value.parse::<T>().unwrap_or_else(|_| {
eprintln_quit!(
"Invalid value at {}.{}: Expected {}, got '{}'",
section,
key,
type_name::<T>(),
value
)
})
} else {
eprintln_quit!("Missing required config key: {}.{}", section, key)
}
}
fn load_color(ini: &Ini, debug_mode: bool) -> ComputableColor {
let color_mode = ini.get("styling", "color_mode").unwrap();
let color_mode: String = get_ini_value(&ini, "styling", "color_mode");
match color_mode.as_str() {
"term" => {
let color = ini.getint("styling", "color_term").unwrap().unwrap();
let color: u8 = get_ini_value(&ini, "styling", "color_term");
ComputableColor::from(load_term_color(color))
}
"hex" => {
let color = ini.get("styling", "color_hex").unwrap();
let color: String = get_ini_value(&ini, "styling", "color_hex");
ComputableColor::from(load_hex_color(&color))
}
"ansi" => {
let color = ini.getint("styling", "color_ansi").unwrap().unwrap();
let color: u8 = get_ini_value(&ini, "styling", "color_ansi");
ComputableColor::from(load_ansi_color(color))
}
"gradient" => load_gradient(ini, debug_mode),
_ => panic!("ERROR: Invalid color mode: {}", color_mode),
_ => eprintln_quit!("Invalid color mode: {}", color_mode),
}
}
fn load_term_color(value: i64) -> Color {
fn load_term_color(value: u8) -> Color {
match value {
0 => Color::Black,
1 => Color::DarkRed,
@@ -78,7 +101,7 @@ fn load_term_color(value: i64) -> Color {
13 => Color::Magenta,
14 => Color::Cyan,
15 => Color::White,
_ => panic!("ERROR: Invalid terminal color: {}", value),
_ => eprintln_quit!("Invalid terminal color: {}", value),
}
}
@@ -91,8 +114,8 @@ fn load_hex_color(value: &str) -> Color {
}
}
fn load_ansi_color(value: i64) -> Color {
Color::AnsiValue(value.try_into().unwrap())
fn load_ansi_color(value: u8) -> Color {
Color::AnsiValue(value)
}
fn load_gradient(ini: &Ini, debug_mode: bool) -> ComputableColor {
@@ -109,11 +132,9 @@ fn load_gradient(ini: &Ini, debug_mode: bool) -> ComputableColor {
}
// Generate gradient loop if needed
if !debug_mode && ini.getbool("gradient", "gradient_loop").unwrap().unwrap() {
let mut loop_keys = keys.clone();
loop_keys.reverse();
for i in 1..loop_keys.len() {
keys.push(*loop_keys.get(i).unwrap());
if !debug_mode && get_ini_value(&ini, "gradient", "gradient_loop") {
for &key in keys.clone().iter().rev().skip(1) {
keys.push(key);
}
}
@@ -121,11 +142,7 @@ fn load_gradient(ini: &Ini, debug_mode: bool) -> ComputableColor {
let steps: usize = if debug_mode {
debug::DEBUG_COLOR_DISPLAY_SIZE * 2
} else {
ini.getuint("gradient", "gradient_steps")
.unwrap()
.unwrap()
.try_into()
.unwrap()
get_ini_value(&ini, "gradient", "gradient_steps")
};
generate_gradient(keys, steps - 1)
}

View File

@@ -57,7 +57,10 @@ fn main() -> io::Result<()> {
PathBuf::from(custom_config)
} else {
// Or default one, located in ~/.config/tlock
let config_file = config_dir().unwrap().join("tlock").join("config");
let config_file = config_dir()
.unwrap_or_else(|| eprintln_quit!("Unble to get configuration directory"))
.join("tlock")
.join("config");
if !config_file.exists() {
write_default_config(config_file.clone());
default_generated = true;
@@ -128,7 +131,7 @@ fn main() -> io::Result<()> {
}
// Disale raw mode, leave the alternate screen and show the cursor back
let _ = terminal::disable_raw_mode().unwrap();
let _ = terminal::disable_raw_mode()?;
execute!(stdout, terminal::LeaveAlternateScreen, cursor::Show)?;
// Be polite

View File

@@ -10,11 +10,11 @@ use crossterm::{
terminal::{self, ClearType},
};
use crate::utils;
use crate::{
config::Config,
rendering::{self, symbols},
};
use crate::{eprintln_quit, utils};
struct Timer {
duration: Duration,
@@ -74,7 +74,8 @@ impl Timer {
pub fn main_loop(config: &mut Config, duration: &str) -> io::Result<()> {
let mut stdout = io::stdout();
let duration = parse_duration::parse(duration).unwrap();
let duration = parse_duration::parse(duration)
.unwrap_or_else(|_| eprintln_quit!("Invalid duration provided"));
let mut timer = Timer::new(duration);
let mut quit = false;

View File

@@ -86,9 +86,14 @@ pub fn parse_hex_color(value: &str) -> (u8, u8, u8) {
panic!("ERROR: Invalid hex color: {}", value);
}
let r = u8::from_str_radix(&value[0..2], 16).unwrap();
let g = u8::from_str_radix(&value[2..4], 16).unwrap();
let b = u8::from_str_radix(&value[4..6], 16).unwrap();
let extract_component = |index: usize| {
u8::from_str_radix(&value[index * 2..(index + 1) * 2], 16)
.unwrap_or_else(|_| panic!("error: invalid hex color: {}", value))
};
(r, g, b)
(
extract_component(0),
extract_component(1),
extract_component(2),
)
}

View File

@@ -8,3 +8,13 @@ pub fn format_duration(duration: time::Duration) -> String {
format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
}
#[macro_export]
macro_rules! eprintln_quit {
($($arg:tt)*) => ({
use std::io::Write;
write!(&mut std::io::stderr(), "ERROR: ").unwrap();
writeln!(&mut std::io::stderr(), $($arg)*).unwrap();
std::process::exit(1)
})
}