diff options
author | ClementTsang <34804052+ClementTsang@users.noreply.github.com> | 2024-06-01 03:01:57 -0400 |
---|---|---|
committer | ClementTsang <34804052+ClementTsang@users.noreply.github.com> | 2024-06-01 03:01:57 -0400 |
commit | 78e96ba1d6e3f3bdd8f9154a8bed2198f1be961b (patch) | |
tree | fde427873f385d743dbcb3510d0f3509ed092e88 | |
parent | ee2e1fee1c6758ee0ec33af28f9d51f1c423599e (diff) |
refactor: sort out some error handlingunify_quote_err
-rw-r--r-- | src/app.rs | 5 | ||||
-rw-r--r-- | src/app/layout_manager.rs | 10 | ||||
-rw-r--r-- | src/app/process_killer.rs | 6 | ||||
-rw-r--r-- | src/app/query.rs | 42 | ||||
-rw-r--r-- | src/canvas.rs | 6 | ||||
-rw-r--r-- | src/canvas/styling/colour_utils.rs | 52 | ||||
-rw-r--r-- | src/data_collection/disks/unix/linux/partition.rs | 7 | ||||
-rw-r--r-- | src/data_collection/disks/unix/other/partition.rs | 3 | ||||
-rw-r--r-- | src/data_collection/processes.rs | 2 | ||||
-rw-r--r-- | src/data_collection/processes/linux.rs | 13 | ||||
-rw-r--r-- | src/data_collection/processes/unix/user_table.rs | 6 | ||||
-rw-r--r-- | src/data_collection/temperature/linux.rs | 10 | ||||
-rw-r--r-- | src/lib.rs | 8 | ||||
-rw-r--r-- | src/options.rs | 165 | ||||
-rw-r--r-- | src/options/config/layout.rs | 11 | ||||
-rw-r--r-- | src/utils/error.rs | 107 | ||||
-rw-r--r-- | src/utils/error/collection.rs | 46 | ||||
-rw-r--r-- | src/utils/error/config.rs | 47 | ||||
-rw-r--r-- | src/utils/error/draw.rs | 14 |
19 files changed, 326 insertions, 234 deletions
@@ -1406,9 +1406,8 @@ impl App { self.to_delete_process_list = None; Ok(()) } else { - Err(BottomError::GenericError( - "Cannot kill processes if the current widget is not the Process widget!" - .to_string(), + Err(BottomError::user( + "Cannot kill processes if the current widget is not the Process widget!", )) } } diff --git a/src/app/layout_manager.rs b/src/app/layout_manager.rs index e7904c9a..3e4ec84f 100644 --- a/src/app/layout_manager.rs +++ b/src/app/layout_manager.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use crate::{ constants::DEFAULT_WIDGET_ID, - error::{BottomError, Result}, + utils::error::{ConfigError, ConfigResult}, }; /// Represents a more usable representation of the layout, derived from the @@ -985,9 +985,9 @@ impl BottomWidgetType { } impl std::str::FromStr for BottomWidgetType { - type Err = BottomError; + type Err = ConfigError; - fn from_str(s: &str) -> Result<Self> { + fn from_str(s: &str) -> ConfigResult<Self> { let lower_case = s.to_lowercase(); match lower_case.as_str() { "cpu" => Ok(BottomWidgetType::Cpu), @@ -1002,7 +1002,7 @@ impl std::str::FromStr for BottomWidgetType { _ => { #[cfg(feature = "battery")] { - Err(BottomError::ConfigError(format!( + Err(ConfigError::other(format!( "\"{s}\" is an invalid widget name. Supported widget names: @@ -1028,7 +1028,7 @@ Supported widget names: } #[cfg(not(feature = "battery"))] { - Err(BottomError::ConfigError(format!( + Err(BottomError::config(format!( "\"{s}\" is an invalid widget name. Supported widget names: diff --git a/src/app/process_killer.rs b/src/app/process_killer.rs index c68b81ab..df846a33 100644 --- a/src/app/process_killer.rs +++ b/src/app/process_killer.rs @@ -74,11 +74,9 @@ pub fn kill_process_given_pid(pid: Pid, signal: usize) -> crate::utils::error::R }; return if let Some(err_code) = err_code { - Err(BottomError::GenericError(format!( - "Error code {err_code} - {err}" - ))) + Err(BottomError::user(format!("Error code {err_code} - {err}"))) } else { - Err(BottomError::GenericError(format!("Error code ??? - {err}"))) + Err(BottomError::user(format!("Error code ??? - {err}"))) }; } diff --git a/src/app/query.rs b/src/app/query.rs index 5737cbc7..81e6efcf 100644 --- a/src/app/query.rs +++ b/src/app/query.rs @@ -1,5 +1,4 @@ use std::{ - borrow::Cow, collections::VecDeque, fmt::{Debug, Formatter}, time::Duration, @@ -13,10 +12,7 @@ use crate::{ multi_eq_ignore_ascii_case, utils::{ data_prefixes::*, - error::{ - BottomError::{self, QueryError}, - Result, - }, + error::{BottomError, Result}, }, }; @@ -86,7 +82,7 @@ pub fn parse_query( break; } } else if COMPARISON_LIST.contains(¤t_lowercase.as_str()) { - return Err(QueryError(Cow::Borrowed("Comparison not valid here"))); + return Err(BottomError::user("Comparison not valid here")); } else { break; } @@ -125,7 +121,7 @@ pub fn parse_query( break; } } else if COMPARISON_LIST.contains(¤t_lowercase.as_str()) { - return Err(QueryError(Cow::Borrowed("Comparison not valid here"))); + return Err(BottomError::user("Comparison not valid here")); } else { break; } @@ -206,7 +202,7 @@ pub fn parse_query( } } else if queue_top == "(" { if query.is_empty() { - return Err(QueryError(Cow::Borrowed("Missing closing parentheses"))); + return Err(BottomError::user("Missing closing parentheses")); } let mut list_of_ors = VecDeque::new(); @@ -221,7 +217,7 @@ pub fn parse_query( // Ensure not empty if list_of_ors.is_empty() { - return Err(QueryError("No values within parentheses group".into())); + return Err(BottomError::user("No values within parentheses group")); } // Now convert this back to a OR... @@ -260,13 +256,13 @@ pub fn parse_query( compare_prefix: None, }); } else { - return Err(QueryError("Missing closing parentheses".into())); + return Err(BottomError::user("Missing closing parentheses")); } } else { - return Err(QueryError("Missing closing parentheses".into())); + return Err(BottomError::user("Missing closing parentheses")); } } else if queue_top == ")" { - return Err(QueryError("Missing opening parentheses".into())); + return Err(BottomError::user("Missing opening parentheses")); } else if queue_top == "\"" { // Similar to parentheses, trap and check for missing closing quotes. Note, however, that we // will DIRECTLY call another process_prefix call... @@ -276,10 +272,10 @@ pub fn parse_query( if close_paren == "\"" { return Ok(prefix); } else { - return Err(QueryError("Missing closing quotation".into())); + return Err(BottomError::user("Missing closing quotation")); } } else { - return Err(QueryError("Missing closing quotation".into())); + return Err(BottomError::user("Missing closing quotation")); } } else { // Get prefix type... @@ -355,15 +351,15 @@ pub fn parse_query( duration_string = Some(queue_next); } } else { - return Err(QueryError("Missing value".into())); + return Err(BottomError::user("Missing value")); } } if let Some(condition) = condition { let duration = parse_duration( - &duration_string.ok_or(QueryError("Missing value".into()))?, + &duration_string.ok_or(BottomError::user("Missing value"))?, ) - .map_err(|err| QueryError(err.to_string().into()))?; + .map_err(|err| BottomError::user(err.to_string()))?; return Ok(Prefix { or: None, @@ -392,7 +388,7 @@ pub fn parse_query( if let Some(queue_next) = query.pop_front() { value = queue_next.parse::<f64>().ok(); } else { - return Err(QueryError("Missing value".into())); + return Err(BottomError::user("Missing value")); } } else if content == ">" || content == "<" { // We also have to check if the next string is an "="... @@ -406,7 +402,7 @@ pub fn parse_query( if let Some(queue_next_next) = query.pop_front() { value = queue_next_next.parse::<f64>().ok(); } else { - return Err(QueryError("Missing value".into())); + return Err(BottomError::user("Missing value")); } } else { condition = Some(if content == ">" { @@ -417,7 +413,7 @@ pub fn parse_query( value = queue_next.parse::<f64>().ok(); } } else { - return Err(QueryError("Missing value".into())); + return Err(BottomError::user("Missing value")); } } @@ -459,15 +455,15 @@ pub fn parse_query( } } } else { - return Err(QueryError("Missing argument for search prefix".into())); + return Err(BottomError::user("Missing argument for search prefix")); } } } else if inside_quotation { // Uh oh, it's empty with quotes! - return Err(QueryError("Missing closing quotation".into())); + return Err(BottomError::user("Missing closing quotation")); } - Err(QueryError("Invalid query".into())) + Err(BottomError::user("Invalid query")) } let mut split_query = VecDeque::new(); diff --git a/src/canvas.rs b/src/canvas.rs index ca144c15..91529075 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -48,7 +48,7 @@ impl FromStr for ColourScheme { "gruvbox-light" => Ok(ColourScheme::GruvboxLight), "nord" => Ok(ColourScheme::Nord), "nord-light" => Ok(ColourScheme::NordLight), - _ => Err(BottomError::ConfigError(format!( + _ => Err(BottomError::config(format!( "`{s}` is an invalid built-in color scheme." ))), } @@ -81,7 +81,7 @@ pub enum LayoutConstraint { } impl Painter { - pub fn init(layout: BottomLayout, styling: CanvasStyling) -> anyhow::Result<Self> { + pub fn init(layout: BottomLayout, styling: CanvasStyling) -> error::Result<Self> { // Now for modularity; we have to also initialize the base layouts! // We want to do this ONCE and reuse; after this we can just construct // based on the console size. @@ -204,7 +204,7 @@ impl Painter { pub fn draw_data<B: Backend>( &mut self, terminal: &mut Terminal<B>, app_state: &mut App, - ) -> error::Result<()> { + ) -> error::DrawResult<()> { use BottomWidgetType::*; terminal.draw(|f| { diff --git a/src/canvas/styling/colour_utils.rs b/src/canvas/styling/colour_utils.rs index 1c1def3e..acaee373 100644 --- a/src/canvas/styling/colour_utils.rs +++ b/src/canvas/styling/colour_utils.rs @@ -3,7 +3,7 @@ use itertools::Itertools; use tui::style::{Color, Style}; use unicode_segmentation::UnicodeSegmentation; -use crate::utils::error; +use crate::utils::error::{self, BottomError}; pub const FIRST_COLOUR: Color = Color::LightMagenta; pub const SECOND_COLOUR: Color = Color::LightYellow; @@ -19,14 +19,14 @@ pub const ALL_COLOUR: Color = Color::Green; fn convert_hex_to_color(hex: &str) -> error::Result<Color> { fn hex_component_to_int(hex: &str, first: &str, second: &str) -> error::Result<u8> { u8::from_str_radix(&concat_string!(first, second), 16).map_err(|_| { - error::BottomError::ConfigError(format!( + BottomError::config(format!( "\"{hex}\" is an invalid hex color, could not decode." )) }) } - fn invalid_hex_format(hex: &str) -> error::BottomError { - error::BottomError::ConfigError(format!( + fn invalid_hex_format(hex: &str) -> BottomError { + BottomError::config(format!( "\"{hex}\" is an invalid hex color. It must be either a 7 character hex string of the form \"#12ab3c\" or a 3 character hex string of the form \"#1a2\".", )) } @@ -69,7 +69,7 @@ pub fn str_to_colour(input_val: &str) -> error::Result<Color> { convert_name_to_colour(input_val) } } else { - Err(error::BottomError::ConfigError(format!( + Err(BottomError::config(format!( "value \"{input_val}\" is not valid.", ))) } @@ -78,7 +78,7 @@ pub fn str_to_colour(input_val: &str) -> error::Result<Color> { fn convert_rgb_to_color(rgb_str: &str) -> error::Result<Color> { let rgb_list = rgb_str.split(',').collect::<Vec<&str>>(); if rgb_list.len() != 3 { - return Err(error::BottomError::ConfigError(format!( + return Err(BottomError::config(format!( "value \"{rgb_str}\" is an invalid RGB colour. It must be a comma separated value with 3 integers from 0 to 255 (ie: \"255, 0, 155\").", ))); } @@ -96,7 +96,7 @@ fn convert_rgb_to_color(rgb_str: &str) -> error::Result<Color> { if rgb.len() == 3 { Ok(Color::Rgb(rgb[0], rgb[1], rgb[2])) } else { - Err(error::BottomError::ConfigError(format!( + Err(BottomError::config(format!( "value \"{rgb_str}\" contained invalid RGB values. It must be a comma separated value with 3 integers from 0 to 255 (ie: \"255, 0, 155\").", ))) } @@ -121,7 +121,7 @@ fn convert_name_to_colour(color_name: &str) -> error::Result<Color> { "lightmagenta" | "light magenta" => Ok(Color::LightMagenta), "lightcyan" | "light cyan" => Ok(Color::LightCyan), "white" => Ok(Color::White), - _ => Err(error::BottomError::ConfigError(format!( + _ => Err(BottomError::config(format!( "\"{color_name}\" is an invalid named color. The following are supported strings: @@ -177,35 +177,41 @@ mod test { #[test] fn valid_colour_names() { // Standard color should work - assert_eq!(convert_name_to_colour("red"), Ok(Color::Red)); + assert_eq!(convert_name_to_colour("red").unwrap(), Color::Red); // Capitalizing should be fine. - assert_eq!(convert_name_to_colour("RED"), Ok(Color::Red)); + assert_eq!(convert_name_to_colour("RED").unwrap(), Color::Red); // Spacing shouldn't be an issue now. - assert_eq!(convert_name_to_colour(" red "), Ok(Color::Red)); + assert_eq!(convert_name_to_colour(" red ").unwrap(), Color::Red); // The following are all equivalent. - assert_eq!(convert_name_to_colour("darkgray"), Ok(Color::DarkGray)); - assert_eq!(convert_name_to_colour("darkgrey"), Ok(Color::DarkGray)); - assert_eq!(convert_name_to_colour("dark grey"), Ok(Color::DarkGray)); - assert_eq!(convert_name_to_colour("dark gray"), Ok(Color::DarkGray)); + assert_eq!(convert_name_to_colour("darkgray").unwrap(), Color::DarkGray); + assert_eq!(convert_name_to_colour("darkgrey").unwrap(), Color::DarkGray); + assert_eq!( + convert_name_to_colour("dark grey").unwrap(), + Color::DarkGray + ); + assert_eq!( + convert_name_to_colour("dark gray").unwrap(), + Color::DarkGray + ); - assert_eq!(convert_name_to_colour("grey"), Ok(Color::Gray)); - assert_eq!(convert_name_to_colour("gray"), Ok(Color::Gray)); + assert_eq!(convert_name_to_colour("grey").unwrap(), Color::Gray); + assert_eq!(convert_name_to_colour("gray").unwrap(), Color::Gray); // One more test with spacing. assert_eq!( - convert_name_to_colour(" lightmagenta "), - Ok(Color::LightMagenta) + convert_name_to_colour(" lightmagenta ").unwrap(), + Color::LightMagenta ); assert_eq!( - convert_name_to_colour("light magenta"), - Ok(Color::LightMagenta) + convert_name_to_colour("light magenta").unwrap(), + Color::LightMagenta ); assert_eq!( - convert_name_to_colour(" light magenta "), - Ok(Color::LightMagenta) + convert_name_to_colour(" light magenta ").unwrap(), + Color::LightMagenta ); } diff --git a/src/data_collection/disks/unix/linux/partition.rs b/src/data_collection/disks/unix/linux/partition.rs index 488ad8d9..1d8a0008 100644 --- a/src/data_collection/disks/unix/linux/partition.rs +++ b/src/data_collection/disks/unix/linux/partition.rs @@ -12,7 +12,10 @@ use std::{ use anyhow::bail; -use crate::data_collection::disks::unix::{FileSystem, Usage}; +use crate::{ + data_collection::disks::unix::{FileSystem, Usage}, + utils::error, +}; /// Representation of partition details. Based on [`heim`](https://github.com/heim-rs/heim/tree/master). pub(crate) struct Partition { @@ -164,7 +167,7 @@ pub(crate) fn partitions() -> anyhow::Result<Vec<Partition>> { /// Returns a [`Vec`] containing all *physical* partitions. This is defined by /// [`FileSystem::is_physical()`]. -pub(crate) fn physical_partitions() -> anyhow::Result<Vec<Partition>> { +pub(crate) fn physical_partitions() -> error::CollectionResult<Vec<Partition>> { const PROC_MOUNTS: &str = "/proc/mounts"; let mut results = vec![]; diff --git a/src/data_collection/disks/unix/other/partition.rs b/src/data_collection/disks/unix/other/partition.rs index 1e64a70d..78420717 100644 --- a/src/data_collection/disks/unix/other/partition.rs +++ b/src/data_collection/disks/unix/other/partition.rs @@ -2,6 +2,7 @@ use std::{ ffi::{CStr, CString}, os::unix::prelude::OsStrExt, path::{Path, PathBuf}, + std::mem::MaybeUninit, str::FromStr, }; @@ -32,7 +33,7 @@ impl Partition { /// Returns the usage stats for this partition. pub fn usage(&self) -> anyhow::Result<Usage> { let path = CString::new(self.mount_point().as_os_str().as_bytes())?; - let mut vfs = std::mem::MaybeUninit::<libc::statvfs>::uninit(); + let mut vfs = MaybeUninit::<libc::statvfs>::uninit(); // SAFETY: System API call. Arguments should be correct. let result = unsafe { libc::statvfs(path.as_ptr(), vfs.as_mut_ptr()) }; diff --git a/src/data_collection/processes.rs b/src/data_collection/processes.rs index ef96c818..80f84ed1 100644 --- a/src/data_collection/processes.rs +++ b/src/data_collection/processes.rs @@ -120,7 +120,7 @@ impl ProcessHarvest { } impl DataCollector { - pub(crate) fn get_processes(&mut self) -> error::Result<Vec<ProcessHarvest>> { + pub(crate) fn get_processes(&mut self) -> error::CollectionResult<Vec<ProcessHarvest>> { cfg_if! { if #[cfg(target_os = "linux")] { let time_diff = self.data.collection_time diff --git a/src/data_collection/processes/linux.rs b/src/data_collection/processes/linux.rs index 5d99fbbc..4065b076 100644 --- a/src/data_collection/processes/linux.rs +++ b/src/data_collection/processes/linux.rs @@ -15,7 +15,7 @@ use sysinfo::ProcessStatus; use super::{ProcessHarvest, UserTable}; use crate::{ data_collection::DataCollector, - utils::error::{self, BottomError}, + utils::error::{self, CollectionError}, Pid, }; @@ -65,7 +65,9 @@ struct CpuUsage { cpu_fraction: f64, } -fn cpu_usage_calculation(prev_idle: &mut f64, prev_non_idle: &mut f64) -> error::Result<CpuUsage> { +fn cpu_usage_calculation( + prev_idle: &mut f64, prev_non_idle: &mut f64, +) -> error::CollectionResult<CpuUsage> { let (idle, non_idle) = { // From SO answer: https://stackoverflow.com/a/23376195 let first_line = { @@ -299,7 +301,7 @@ pub(crate) struct ReadProcArgs { pub(crate) fn linux_process_data( collector: &mut DataCollector, time_difference_in_secs: u64, -) -> error::Result<Vec<ProcessHarvest>> { +) -> error::CollectionResult<Vec<ProcessHarvest>> { let total_memory = collector.total_memory(); let prev_proc = PrevProc { prev_idle: &mut collector.prev_idle, @@ -402,8 +404,9 @@ pub(crate) fn linux_process_data( Ok(process_vector) } else { - Err(BottomError::GenericError( - "Could not calculate CPU usage.".to_string(), + Err(CollectionError::other( + "Process", + "Could not calculate CPU usage.", )) } } diff --git a/src/data_collection/processes/unix/user_table.rs b/src/data_collection/processes/unix/user_table.rs index 6245a858..5d5b2f04 100644 --- a/src/data_collection/processes/unix/user_table.rs +++ b/src/data_collection/processes/unix/user_table.rs @@ -1,6 +1,6 @@ use hashbrown::HashMap; -use crate::utils::error; +use crate::utils::error::{CollectionError, CollectionResult}; #[derive(Debug, Default)] pub struct UserTable { @@ -8,7 +8,7 @@ pub struct UserTable { } impl UserTable { - pub fn get_uid_to_username_mapping(&mut self, uid: libc::uid_t) -> error::Result<String> { + pub fn get_uid_to_username_mapping(&mut self, uid: libc::uid_t) -> CollectionResult<String> { if let Some(user) = self.uid_user_mapping.get(&uid) { Ok(user.clone()) } else { @@ -16,7 +16,7 @@ impl UserTable { let passwd = unsafe { libc::getpwuid(uid) }; if passwd.is_null() { - Err(error::BottomError::QueryError("Missing passwd".into())) + Err(CollectionError::other("processes", "Missing passwd")) } else { // SAFETY: We return early if passwd is null. let username = unsafe { std::ffi::CStr::from_ptr((*passwd).pw_name) } diff --git a/src/data_collection/temperature/linux.rs b/src/data_collection/temperature/linux.rs index 50b858d1..1c1fb54e 100644 --- a/src/data_collection/temperature/linux.rs +++ b/src/data_collection/temperature/linux.rs @@ -9,7 +9,7 @@ use anyhow::Result; use hashbrown::{HashMap, HashSet}; use super::{is_temp_filtered, TempHarvest, TemperatureType}; -use crate::{app::filter::Filter, utils::error::BottomError}; +use crate::{app::filter::Filter, utils::error::CollectionResult}; const EMPTY_NAME: &str = "Unknown"; @@ -20,12 +20,8 @@ struct HwmonResults { } /// Parses and reads temperatures that were in millidegree Celsius, and if successful, returns a temperature in Celsius. -fn parse_temp(path: &Path) -> Result<f32> { - Ok(fs::read_to_string(path)? - .trim_end() - .parse::<f32>() - .map_err(|e| BottomError::ConversionError(e.to_string()))? - / 1_000.0) +fn parse_temp(path: &Path) -> CollectionResult<f32> { + Ok(fs::read_to_string(path)?.trim_end().parse::<f32>()? / 1_000.0) } /// Get all candidates from hwmon and coretemp. It will also return the number of entries from hwmon. @@ -62,7 +62,7 @@ use crossterm::{ use data_conversion::*; pub use options::args; use options::ConfigV1; -use utils::error; +use utils::error::{self, ConfigResult}; #[allow(unused_imports)] pub use utils::logging::*; @@ -235,7 +235,7 @@ pub fn get_config_path(override_config_path: Option<&Path>) -> Option<PathBuf> { } } -pub fn get_or_create_config(override_config_path: Option<&Path>) -> error::Result<ConfigV1> { +pub fn get_or_create_config(override_config_path: Option<&Path>) -> ConfigResult<ConfigV1> { let config_path = get_config_path(override_config_path); if let Some(path) = &config_path { @@ -258,7 +258,7 @@ pub fn get_or_create_config(override_config_path: Option<&Path>) -> error::Resul pub fn try_drawing( terminal: &mut tui::terminal::Terminal<tui::backend::CrosstermBackend<std::io::Stdout>>, app: &mut App, painter: &mut canvas::Painter, -) -> error::Result<()> { +) -> error::DrawResult<()> { if let Err(err) = painter.draw_data(terminal, app) { cleanup_terminal(terminal)?; Err(err) @@ -269,7 +269,7 @@ pub fn try_drawing( pub fn cleanup_terminal( terminal: &mut tui::terminal::Terminal<tui::backend::CrosstermBackend<std::io::Stdout>>, -) -> error::Result<()> { +) -> error::DrawResult<()> { disable_raw_mode()?; execute!( terminal.backend_mut(), diff --git a/src/options.rs b/src/options.rs index c98618b2..54cb9f12 100644 --- a/src/options.rs +++ b/src/options.rs @@ -32,7 +32,7 @@ use crate::{ data_collection::temperature::TemperatureType, utils::{ data_units::DataUnit, - error::{self, BottomError}, + error::{self, BottomError, ConfigError, ConfigResult}, }, widgets::*, }; @@ -369,7 +369,7 @@ pub fn init_app( pub fn get_widget_layout( args: &BottomArgs, config: &ConfigV1, -) -> error::Result<(BottomLayout, u64, Option<BottomWidgetType>)> { +) -> ConfigResult<(BottomLayout, u64, Option<BottomWidgetType>)> { let cpu_left_legend = is_flag_enabled!(cpu_left_legend, args.cpu, config); let (default_widget_type, mut default_widget_count) = @@ -413,7 +413,7 @@ pub fn get_widget_layout( cpu_left_legend, ) }) - .collect::<error::Result<Vec<_>>>()?, + .collect::<ConfigResult<Vec<_>>>()?, total_row_height_ratio: total_height_ratio, }; @@ -422,8 +422,8 @@ pub fn get_widget_layout( ret_bottom_layout.get_movement_mappings(); ret_bottom_layout } else { - return Err(BottomError::ConfigError( - "please have at least one widget under the '[[row]]' section.".to_string(), + return Err(ConfigError::other( + "please have at least one widget under the '[[row]]' section.", )); } }; @@ -433,15 +433,13 @@ pub fn get_widget_layout( fn get_update_rate(args: &BottomArgs, config: &ConfigV1) -> error::Result<u64> { let update_rate = if let Some(update_rate) = &args.general.rate { - try_parse_ms(update_rate).map_err(|_| { - BottomError::ArgumentError("set your update rate to be valid".to_string()) - })? + try_parse_ms(update_rate) + .map_err(|_| BottomError::config("set your update rate to be valid"))? } else if let Some(flags) = &config.flags { if let Some(rate) = &flags.rate { match rate { - StringOrNum::String(s) => try_parse_ms(s).map_err(|_| { - BottomError::ConfigError("set your update rate to be valid".to_string()) - })?, + StringOrNum::String(s) => try_parse_ms(s) + .map_err(|_| BottomError::config("set your update rate to be valid"))?, StringOrNum::Num(n) => *n, } } else { @@ -452,8 +450,8 @@ fn get_update_rate(args: &BottomArgs, config: &ConfigV1) -> error::Result<u64> { }; if update_rate < 250 { - return Err(BottomError::ConfigError( - "set your update rate to be at least 250 ms.".to_string(), + return Err(BottomError::config( + "set your update rate to be at least 250 ms.", )); } @@ -469,7 +467,7 @@ fn get_temperature(args: &BottomArgs, config: &ConfigV1) -> error::Result<Temper return Ok(TemperatureType::Celsius); } else if let Some(flags) = &config.flags { if let Some(temp_type) = &flags.temperature_type { - return TemperatureType::from_str(temp_type).map_err(BottomError::ConfigError); + return TemperatureType::from_str(temp_type).map_err(BottomError::config); } } Ok(TemperatureType::Celsius) @@ -494,8 +492,8 @@ fn try_parse_ms(s: &str) -> error::Result<u64> { } else if let Ok(val) = s.parse::<u64>() { Ok(val) } else { - Err(BottomError::ConfigError( - "could not parse as a valid 64-bit unsigned integer or a human time".to_string(), + Err(BottomError::config( + "could not parse as a valid 64-bit unsigned integer or a human time", )) } } @@ -504,15 +502,13 @@ fn get_default_time_value( args: &BottomArgs, config: &ConfigV1, retention_ms: u64, ) -> error::Result<u64> { let default_time = if let Some(default_time_value) = &args.general.default_time_value { - try_parse_ms(default_time_value).map_err(|_| { - BottomError::ArgumentError("set your default time to be valid".to_string()) - })? + try_parse_ms(default_time_value) + .map_err(|_| BottomError::config("set your default time to be valid"))? } else if let Some(flags) = &config.flags { if let Some(default_time_value) = &flags.default_time_value { match default_time_value { - StringOrNum::String(s) => try_parse_ms(s).map_err(|_| { - BottomError::ConfigError("set your default time to be valid".to_string()) - })?, + StringOrNum::String(s) => try_parse_ms(s) + .map_err(|_| BottomError::config("set your default time to be valid"))?, StringOrNum::Num(n) => *n, } } else { @@ -523,11 +519,11 @@ fn get_default_time_value( }; if default_time < 30000 { - return Err(BottomError::ConfigError( - "set your default time to be at least 30s.".to_string(), + return Err(BottomError::config( + "set your default time to be at least 30s.", )); } else if default_time > retention_ms { - return Err(BottomError::ConfigError(format!( + return Err(BottomError::config(format!( "set your default time to be at most {}.", humantime::Duration::from(Duration::from_millis(retention_ms)) ))); @@ -540,15 +536,13 @@ fn get_time_interval( args: &BottomArgs, config: &ConfigV1, retention_ms: u64, ) -> error::Result<u64> { let time_interval = if let Some(time_interval) = &args.general.time_delta { - try_parse_ms(time_interval).map_err(|_| { - BottomError::ArgumentError("set your time delta to be valid".to_string()) - })? + try_parse_ms(time_interval) + .map_err(|_| BottomError::config("set your time delta to be valid"))? } else if let Some(flags) = &config.flags { if let Some(time_interval) = &flags.time_delta { match time_interval { - StringOrNum::String(s) => try_parse_ms(s).map_err(|_| { - BottomError::ArgumentError("set your time delta to be valid".to_string()) - })?, + StringOrNum::String(s) => try_parse_ms(s) + .map_err(|_| BottomError::config("set your time delta to be valid"))?, StringOrNum::Num(n) => *n, } } else { @@ -559,22 +553,22 @@ fn get_time_interval( }; if time_interval < 1000 { - return Err(BottomError::ConfigError( - "set your time delta to be at least 1s.".to_string(), - )); + Err(BottomError::config( + "set your time delta to be at least 1s.", + )) } else if time_interval > retention_ms { - return Err(BottomError::ConfigError(format!( + Err(BottomE |