diff --git a/Cargo.toml b/Cargo.toml index b88b312c..35ea7310 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ lto = true [dependencies] chrono = "0.4.10" clap = "2.33.0" -failure = "0.1.6" fern = "0.5.9" futures-timer = "3.0.1" futures = "0.3.3" diff --git a/README.md b/README.md index 6506f2f1..3dbbc58e 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,6 @@ Note that `q` is disabled while in the search widget. - [chrono](https://github.com/chronotope/chrono) - [clap](https://github.com/clap-rs/clap) - [crossterm](https://github.com/TimonPost/crossterm) - - [failure](https://github.com/rust-lang-nursery/failure) - [fern](https://github.com/daboross/fern) - [futures-rs](https://github.com/rust-lang-nursery/futures-rs) - [futures-timer](https://github.com/rustasync/futures-timer) @@ -204,6 +203,6 @@ Note that `q` is disabled while in the search widget. - [log](https://github.com/rust-lang-nursery/log) - [sysinfo](https://github.com/GuillaumeGomez/sysinfo) - [tokio](https://github.com/tokio-rs/tokio) - - [toml-ru](https://github.com/alexcrichton/toml-rs) + - [toml-rs](https://github.com/alexcrichton/toml-rs) - [tui-rs](https://github.com/fdehau/tui-rs) - [winapi](https://github.com/retep998/winapi-rs) diff --git a/sample_config.toml b/sample_config.toml index 9ec74ded..1db147a7 100644 --- a/sample_config.toml +++ b/sample_config.toml @@ -1,7 +1,7 @@ [flags] avg_cpu = true dot_marker = true -temperature_type = "k" +temperature_type = "ke" rate = 1000 left_legend = true current_usage = false diff --git a/src/app/data_harvester/processes.rs b/src/app/data_harvester/processes.rs index 0b8371fe..f4b49f96 100644 --- a/src/app/data_harvester/processes.rs +++ b/src/app/data_harvester/processes.rs @@ -37,12 +37,10 @@ fn cpu_usage_calculation( let split_results = stat_results.split('\n').collect::>(); if split_results.is_empty() { - return Err(error::BottomError::InvalidIO { - message: format!( - "Unable to properly split the stat results; saw {} values, expected at least 1 value.", - split_results.len() - ), - }); + return Err(error::BottomError::InvalidIO(format!( + "Unable to properly split the stat results; saw {} values, expected at least 1 value.", + split_results.len() + ))); } else { first_line = split_results[0]; } @@ -51,12 +49,10 @@ fn cpu_usage_calculation( // SC in case that the parsing will fail due to length: if val.len() <= 10 { - return Err(error::BottomError::InvalidIO { - message: format!( + return Err(error::BottomError::InvalidIO(format!( "CPU parsing will fail due to too short of a return value; saw {} values, expected 10 values.", val.len() - ), - }); + ))); } let user: f64 = val[1].parse::<_>().unwrap_or(0_f64); diff --git a/src/app/process_killer.rs b/src/app/process_killer.rs index d0f374ac..85b5b402 100644 --- a/src/app/process_killer.rs +++ b/src/app/process_killer.rs @@ -42,11 +42,10 @@ pub fn kill_process_given_pid(pid: u32) -> crate::utils::error::Result<()> { process.kill()?; } } else { - return Err(BottomError::GenericError { - message: - "Sorry, support operating systems outside the main three are not implemented yet!" - .to_string(), - }); + return Err(BottomError::GenericError( + "Sorry, support operating systems outside the main three are not implemented yet!" + .to_string(), + )); } Ok(()) diff --git a/src/canvas.rs b/src/canvas.rs index c70ae720..fbbdbc39 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -27,31 +27,78 @@ const WINDOWS_NETWORK_HEADERS: [&str; 4] = ["RX", "TX", "", ""]; const FORCE_MIN_THRESHOLD: usize = 5; lazy_static! { - static ref HELP_TEXT: [Text<'static>; 22] = [ - Text::raw("\nGeneral Keybindings\n"), - Text::raw("q, Ctrl-c to quit. Note if you are currently in the search widget, `q` will not work.\n"), - Text::raw("Ctrl-r to reset all data.\n"), - Text::raw("f to toggle freezing and unfreezing the display.\n"), - Text::raw( - "Ctrl/Shift-Up, Ctrl/Shift-Down, Ctrl/Shift-Left, and Ctrl/Shift-Right to navigate between widgets.\n" + static ref DEFAULT_TEXT_STYLE: Style = Style::default().fg(Color::Gray); + static ref DEFAULT_HEADER_STYLE: Style = Style::default().fg(Color::LightBlue); + static ref HELP_TEXT: [Text<'static>; 30] = [ + Text::styled("\n General Keybindings\n", *DEFAULT_HEADER_STYLE), + Text::styled("q, Ctrl-c Quit\n", *DEFAULT_TEXT_STYLE), + Text::styled("Ctrl-r Reset all data\n", *DEFAULT_TEXT_STYLE), + Text::styled("f Freeze display\n", *DEFAULT_TEXT_STYLE), + Text::styled("Ctrl-Arrow Move selected widget\n", *DEFAULT_TEXT_STYLE), + Text::styled("Shift-Arrow Move selected widget\n", *DEFAULT_TEXT_STYLE), + Text::styled("Up, k Move cursor up\n", *DEFAULT_TEXT_STYLE), + Text::styled("Down, j Move cursor down\n", *DEFAULT_TEXT_STYLE), + Text::styled("Left, h Move cursor left\n", *DEFAULT_TEXT_STYLE), + Text::styled("Right, l Move cursor right\n", *DEFAULT_TEXT_STYLE), + Text::styled("Esc Close dialog box\n", *DEFAULT_TEXT_STYLE), + Text::styled("? Open the help screen\n", *DEFAULT_TEXT_STYLE), + Text::styled( + "gg Skip to the first entry of a list\n", + *DEFAULT_TEXT_STYLE ), - Text::raw("Up or k and Down or j scrolls through a list.\n"), - Text::raw("Esc to close a dialog window (help or dd confirmation).\n"), - Text::raw("? to get this help screen.\n"), - Text::raw("\n Process Widget Keybindings\n"), - Text::raw("dd to kill the selected process.\n"), - Text::raw("c to sort by CPU usage.\n"), - Text::raw("m to sort by memory usage.\n"), - Text::raw("p to sort by PID.\n"), - Text::raw("n to sort by process name.\n"), - Text::raw("Tab to group together processes with the same name.\n"), - Text::raw("Ctrl-f to toggle searching for a process. / to just open it.\n"), - Text::raw("Use Ctrl-p and Ctrl-n to toggle between searching for PID and name.\n"), - Text::raw("Use Tab to set the cursor to the start and end of the bar respectively.\n"), - Text::raw("Use Alt-c to toggle whether to ignore case.\n"), - Text::raw("Use Alt-m to toggle matching the entire word.\n"), - Text::raw("Use Alt-r to toggle regex.\n"), - Text::raw("\nFor startup flags, type in \"btm -h\".") + Text::styled( + "G Skip to the last entry of a list\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "\n Process Keybindings\n", + *DEFAULT_HEADER_STYLE + ), + Text::styled( + "dd Kill the highlighted process\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled("c Sort by CPU usage\n", *DEFAULT_TEXT_STYLE), + Text::styled("m Sort by memory usage\n", *DEFAULT_TEXT_STYLE), + Text::styled("p Sort by PID\n", *DEFAULT_TEXT_STYLE), + Text::styled("n Sort by process name\n", *DEFAULT_TEXT_STYLE), + Text::styled( + "Tab Group together processes with the same name\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "Ctrl-f, / Open up the search widget\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled("\n Search Keybindings\n", *DEFAULT_HEADER_STYLE), + Text::styled( + "Tab Toggle between searching for PID and name.\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "Ctrl-a Skip to the start of search widget\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "Ctrl-e Skip to the end of search widget\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "Alt-c Toggle whether to ignore case\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "Alt-m Toggle whether to match the whole word\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "Alt-r Toggle whether to use regex\n", + *DEFAULT_TEXT_STYLE + ), + Text::styled( + "\n For startup flags, type in \"btm -h\".", + *DEFAULT_TEXT_STYLE + ) ]; static ref DISK_HEADERS_LENS: Vec = DISK_HEADERS .iter() @@ -129,9 +176,9 @@ impl Painter { .margin(1) .constraints( [ - Constraint::Percentage(22), - Constraint::Percentage(60), - Constraint::Percentage(18), + Constraint::Percentage(17), + Constraint::Percentage(70), + Constraint::Percentage(13), ] .as_ref(), ) @@ -153,7 +200,7 @@ impl Painter { Paragraph::new(HELP_TEXT.iter()) .block( Block::default() - .title(" Help (Press Esc to close) ") + .title(" Help ") .title_style(self.colours.widget_title_style) .style(self.colours.border_style) .borders(Borders::ALL), diff --git a/src/canvas/canvas_colours/drawing_utils.rs b/src/canvas/canvas_colours/drawing_utils.rs index 066e9f0d..e54c99e9 100644 --- a/src/canvas/canvas_colours/drawing_utils.rs +++ b/src/canvas/canvas_colours/drawing_utils.rs @@ -60,12 +60,10 @@ pub fn convert_hex_to_color(hex: &str) -> error::Result { return Ok((r, g, b)); } - Err(error::BottomError::GenericError { - message: format!( + Err(error::BottomError::GenericError(format!( "Colour hex {} is not of valid length. It must be a 7 character string of the form \"#112233\".", hex - ), - }) + ))) } let rgb = convert_hex_to_rgb(hex)?; diff --git a/src/main.rs b/src/main.rs index 096119bd..39cf344c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,6 @@ extern crate log; #[macro_use] extern crate clap; #[macro_use] -extern crate failure; -#[macro_use] extern crate lazy_static; use serde::Deserialize; @@ -153,13 +151,13 @@ fn main() -> error::Result<()> { }; if update_rate_in_milliseconds < 250 { - return Err(BottomError::InvalidArg { - message: "Please set your update rate to be greater than 250 milliseconds.".to_string(), - }); + return Err(BottomError::InvalidArg( + "Please set your update rate to be greater than 250 milliseconds.".to_string(), + )); } else if update_rate_in_milliseconds > u128::from(std::u64::MAX) { - return Err(BottomError::InvalidArg { - message: "Please set your update rate to be less than unsigned INT_MAX.".to_string(), - }); + return Err(BottomError::InvalidArg( + "Please set your update rate to be less than unsigned INT_MAX.".to_string(), + )); } // Set other settings @@ -176,7 +174,11 @@ fn main() -> error::Result<()> { "fahrenheit" | "f" => data_harvester::temperature::TemperatureType::Fahrenheit, "kelvin" | "k" => data_harvester::temperature::TemperatureType::Kelvin, "celsius" | "c" => data_harvester::temperature::TemperatureType::Celsius, - _ => data_harvester::temperature::TemperatureType::Celsius, + _ => { + return Err(BottomError::ConfigError( + "Invalid temperature type. Please have the value be of the form ".to_string() + )); + } } } else { data_harvester::temperature::TemperatureType::Celsius diff --git a/src/utils/error.rs b/src/utils/error.rs index 2383acf9..badaaeba 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -1,102 +1,89 @@ -use failure::Fail; use std::result; /// A type alias for handling errors related to Bottom. pub type Result = result::Result; /// An error that can occur while Bottom runs. -#[derive(Debug, Fail)] +#[derive(Debug)] pub enum BottomError { /// An error when there is an IO exception. - /// - /// The data provided is the error found. - #[fail(display = "ERROR: Encountered an IO exception: {}", message)] - InvalidIO { message: String }, + InvalidIO(String), /// An error when there is an invalid argument passed in. - /// - /// The data provided is the error found. - #[fail(display = "ERROR: Invalid argument: {}", message)] - InvalidArg { message: String }, + InvalidArg(String), /// An error when the heim library encounters a problem. - /// - /// The data provided is the error found. - #[fail( - display = "ERROR: Invalid error during data collection due to Heim: {}", - message - )] - InvalidHeim { message: String }, + InvalidHeim(String), /// An error when the Crossterm library encounters a problem. - /// - /// The data provided is the error found. - #[fail(display = "ERROR: Invalid error due to Crossterm: {}", message)] - CrosstermError { message: String }, - /// An error to represent generic errors - /// - /// The data provided is the error found. - #[fail(display = "ERROR: Invalid generic error: {}", message)] - GenericError { message: String }, - /// An error to represent errors with fern - /// - /// The data provided is the error found. - #[fail(display = "ERROR: Invalid fern error: {}", message)] - FernError { message: String }, - /// An error to represent errors with fern - /// - /// The data provided is the error found. - #[fail(display = "ERROR: Invalid config file error: {}", message)] - ConfigError { message: String }, + CrosstermError(String), + /// An error to represent generic errors. + GenericError(String), + /// An error to represent errors with fern. + FernError(String), + /// An error to represent errors with the config. + ConfigError(String), +} + +impl std::fmt::Display for BottomError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match *self { + BottomError::InvalidIO(ref message) => { + write!(f, "Encountered an IO exception: {}", message) + } + BottomError::InvalidArg(ref message) => write!(f, "Invalid argument: {}", message), + BottomError::InvalidHeim(ref message) => write!( + f, + "Invalid error during data collection due to Heim: {}", + message + ), + BottomError::CrosstermError(ref message) => { + write!(f, "Invalid error due to Crossterm: {}", message) + } + BottomError::GenericError(ref message) => write!(f, "{}", message), + BottomError::FernError(ref message) => write!(f, "Invalid fern error: {}", message), + BottomError::ConfigError(ref message) => { + write!(f, "Invalid config file error: {}", message) + } + } + } } impl From for BottomError { fn from(err: std::io::Error) -> Self { - BottomError::InvalidIO { - message: err.to_string(), - } + BottomError::InvalidIO(err.to_string()) } } impl From for BottomError { fn from(err: heim::Error) -> Self { - BottomError::InvalidHeim { - message: err.to_string(), - } + BottomError::InvalidHeim(err.to_string()) } } impl From for BottomError { fn from(err: crossterm::ErrorKind) -> Self { - BottomError::CrosstermError { - message: err.to_string(), - } + BottomError::CrosstermError(err.to_string()) } } impl From for BottomError { fn from(err: std::num::ParseIntError) -> Self { - BottomError::InvalidArg { - message: err.to_string(), - } + BottomError::InvalidArg(err.to_string()) } } impl From for BottomError { fn from(err: std::string::String) -> Self { - BottomError::GenericError { message: err } + BottomError::GenericError(err) } } impl From for BottomError { fn from(err: toml::de::Error) -> Self { - BottomError::ConfigError { - message: err.to_string(), - } + BottomError::ConfigError(err.to_string()) } } impl From for BottomError { fn from(err: fern::InitError) -> Self { - BottomError::FernError { - message: err.to_string(), - } + BottomError::FernError(err.to_string()) } }