Update and clean up ? menu... some more work to be done though

This commit is contained in:
ClementTsang 2020-02-08 22:38:55 -05:00
parent b593a29e9c
commit 4ac3a10fbf
9 changed files with 142 additions and 115 deletions

View File

@ -23,7 +23,6 @@ lto = true
[dependencies] [dependencies]
chrono = "0.4.10" chrono = "0.4.10"
clap = "2.33.0" clap = "2.33.0"
failure = "0.1.6"
fern = "0.5.9" fern = "0.5.9"
futures-timer = "3.0.1" futures-timer = "3.0.1"
futures = "0.3.3" futures = "0.3.3"

View File

@ -195,7 +195,6 @@ Note that `q` is disabled while in the search widget.
- [chrono](https://github.com/chronotope/chrono) - [chrono](https://github.com/chronotope/chrono)
- [clap](https://github.com/clap-rs/clap) - [clap](https://github.com/clap-rs/clap)
- [crossterm](https://github.com/TimonPost/crossterm) - [crossterm](https://github.com/TimonPost/crossterm)
- [failure](https://github.com/rust-lang-nursery/failure)
- [fern](https://github.com/daboross/fern) - [fern](https://github.com/daboross/fern)
- [futures-rs](https://github.com/rust-lang-nursery/futures-rs) - [futures-rs](https://github.com/rust-lang-nursery/futures-rs)
- [futures-timer](https://github.com/rustasync/futures-timer) - [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) - [log](https://github.com/rust-lang-nursery/log)
- [sysinfo](https://github.com/GuillaumeGomez/sysinfo) - [sysinfo](https://github.com/GuillaumeGomez/sysinfo)
- [tokio](https://github.com/tokio-rs/tokio) - [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) - [tui-rs](https://github.com/fdehau/tui-rs)
- [winapi](https://github.com/retep998/winapi-rs) - [winapi](https://github.com/retep998/winapi-rs)

View File

@ -1,7 +1,7 @@
[flags] [flags]
avg_cpu = true avg_cpu = true
dot_marker = true dot_marker = true
temperature_type = "k" temperature_type = "ke"
rate = 1000 rate = 1000
left_legend = true left_legend = true
current_usage = false current_usage = false

View File

@ -37,12 +37,10 @@ fn cpu_usage_calculation(
let split_results = stat_results.split('\n').collect::<Vec<&str>>(); let split_results = stat_results.split('\n').collect::<Vec<&str>>();
if split_results.is_empty() { if split_results.is_empty() {
return Err(error::BottomError::InvalidIO { return Err(error::BottomError::InvalidIO(format!(
message: format!(
"Unable to properly split the stat results; saw {} values, expected at least 1 value.", "Unable to properly split the stat results; saw {} values, expected at least 1 value.",
split_results.len() split_results.len()
), )));
});
} else { } else {
first_line = split_results[0]; first_line = split_results[0];
} }
@ -51,12 +49,10 @@ fn cpu_usage_calculation(
// SC in case that the parsing will fail due to length: // SC in case that the parsing will fail due to length:
if val.len() <= 10 { if val.len() <= 10 {
return Err(error::BottomError::InvalidIO { return Err(error::BottomError::InvalidIO(format!(
message: format!(
"CPU parsing will fail due to too short of a return value; saw {} values, expected 10 values.", "CPU parsing will fail due to too short of a return value; saw {} values, expected 10 values.",
val.len() val.len()
), )));
});
} }
let user: f64 = val[1].parse::<_>().unwrap_or(0_f64); let user: f64 = val[1].parse::<_>().unwrap_or(0_f64);

View File

@ -42,11 +42,10 @@ pub fn kill_process_given_pid(pid: u32) -> crate::utils::error::Result<()> {
process.kill()?; process.kill()?;
} }
} else { } else {
return Err(BottomError::GenericError { return Err(BottomError::GenericError(
message:
"Sorry, support operating systems outside the main three are not implemented yet!" "Sorry, support operating systems outside the main three are not implemented yet!"
.to_string(), .to_string(),
}); ));
} }
Ok(()) Ok(())

View File

@ -27,31 +27,78 @@ const WINDOWS_NETWORK_HEADERS: [&str; 4] = ["RX", "TX", "", ""];
const FORCE_MIN_THRESHOLD: usize = 5; const FORCE_MIN_THRESHOLD: usize = 5;
lazy_static! { lazy_static! {
static ref HELP_TEXT: [Text<'static>; 22] = [ static ref DEFAULT_TEXT_STYLE: Style = Style::default().fg(Color::Gray);
Text::raw("\nGeneral Keybindings\n"), static ref DEFAULT_HEADER_STYLE: Style = Style::default().fg(Color::LightBlue);
Text::raw("q, Ctrl-c to quit. Note if you are currently in the search widget, `q` will not work.\n"), static ref HELP_TEXT: [Text<'static>; 30] = [
Text::raw("Ctrl-r to reset all data.\n"), Text::styled("\n General Keybindings\n", *DEFAULT_HEADER_STYLE),
Text::raw("f to toggle freezing and unfreezing the display.\n"), Text::styled("q, Ctrl-c Quit\n", *DEFAULT_TEXT_STYLE),
Text::raw( Text::styled("Ctrl-r Reset all data\n", *DEFAULT_TEXT_STYLE),
"Ctrl/Shift-Up, Ctrl/Shift-Down, Ctrl/Shift-Left, and Ctrl/Shift-Right to navigate between widgets.\n" 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::styled(
Text::raw("Esc to close a dialog window (help or dd confirmation).\n"), "G Skip to the last entry of a list\n",
Text::raw("? to get this help screen.\n"), *DEFAULT_TEXT_STYLE
Text::raw("\n Process Widget Keybindings\n"), ),
Text::raw("dd to kill the selected process.\n"), Text::styled(
Text::raw("c to sort by CPU usage.\n"), "\n Process Keybindings\n",
Text::raw("m to sort by memory usage.\n"), *DEFAULT_HEADER_STYLE
Text::raw("p to sort by PID.\n"), ),
Text::raw("n to sort by process name.\n"), Text::styled(
Text::raw("Tab to group together processes with the same name.\n"), "dd Kill the highlighted process\n",
Text::raw("Ctrl-f to toggle searching for a process. / to just open it.\n"), *DEFAULT_TEXT_STYLE
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::styled("c Sort by CPU usage\n", *DEFAULT_TEXT_STYLE),
Text::raw("Use Alt-c to toggle whether to ignore case.\n"), Text::styled("m Sort by memory usage\n", *DEFAULT_TEXT_STYLE),
Text::raw("Use Alt-m to toggle matching the entire word.\n"), Text::styled("p Sort by PID\n", *DEFAULT_TEXT_STYLE),
Text::raw("Use Alt-r to toggle regex.\n"), Text::styled("n Sort by process name\n", *DEFAULT_TEXT_STYLE),
Text::raw("\nFor startup flags, type in \"btm -h\".") 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<usize> = DISK_HEADERS static ref DISK_HEADERS_LENS: Vec<usize> = DISK_HEADERS
.iter() .iter()
@ -129,9 +176,9 @@ impl Painter {
.margin(1) .margin(1)
.constraints( .constraints(
[ [
Constraint::Percentage(22), Constraint::Percentage(17),
Constraint::Percentage(60), Constraint::Percentage(70),
Constraint::Percentage(18), Constraint::Percentage(13),
] ]
.as_ref(), .as_ref(),
) )
@ -153,7 +200,7 @@ impl Painter {
Paragraph::new(HELP_TEXT.iter()) Paragraph::new(HELP_TEXT.iter())
.block( .block(
Block::default() Block::default()
.title(" Help (Press Esc to close) ") .title(" Help ")
.title_style(self.colours.widget_title_style) .title_style(self.colours.widget_title_style)
.style(self.colours.border_style) .style(self.colours.border_style)
.borders(Borders::ALL), .borders(Borders::ALL),

View File

@ -60,12 +60,10 @@ pub fn convert_hex_to_color(hex: &str) -> error::Result<Color> {
return Ok((r, g, b)); return Ok((r, g, b));
} }
Err(error::BottomError::GenericError { Err(error::BottomError::GenericError(format!(
message: format!(
"Colour hex {} is not of valid length. It must be a 7 character string of the form \"#112233\".", "Colour hex {} is not of valid length. It must be a 7 character string of the form \"#112233\".",
hex hex
), )))
})
} }
let rgb = convert_hex_to_rgb(hex)?; let rgb = convert_hex_to_rgb(hex)?;

View File

@ -3,8 +3,6 @@ extern crate log;
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;
#[macro_use] #[macro_use]
extern crate failure;
#[macro_use]
extern crate lazy_static; extern crate lazy_static;
use serde::Deserialize; use serde::Deserialize;
@ -153,13 +151,13 @@ fn main() -> error::Result<()> {
}; };
if update_rate_in_milliseconds < 250 { if update_rate_in_milliseconds < 250 {
return Err(BottomError::InvalidArg { return Err(BottomError::InvalidArg(
message: "Please set your update rate to be greater than 250 milliseconds.".to_string(), "Please set your update rate to be greater than 250 milliseconds.".to_string(),
}); ));
} else if update_rate_in_milliseconds > u128::from(std::u64::MAX) { } else if update_rate_in_milliseconds > u128::from(std::u64::MAX) {
return Err(BottomError::InvalidArg { return Err(BottomError::InvalidArg(
message: "Please set your update rate to be less than unsigned INT_MAX.".to_string(), "Please set your update rate to be less than unsigned INT_MAX.".to_string(),
}); ));
} }
// Set other settings // Set other settings
@ -176,7 +174,11 @@ fn main() -> error::Result<()> {
"fahrenheit" | "f" => data_harvester::temperature::TemperatureType::Fahrenheit, "fahrenheit" | "f" => data_harvester::temperature::TemperatureType::Fahrenheit,
"kelvin" | "k" => data_harvester::temperature::TemperatureType::Kelvin, "kelvin" | "k" => data_harvester::temperature::TemperatureType::Kelvin,
"celsius" | "c" => data_harvester::temperature::TemperatureType::Celsius, "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 <kelvin|k|celsius|c|fahrenheit|f>".to_string()
));
}
} }
} else { } else {
data_harvester::temperature::TemperatureType::Celsius data_harvester::temperature::TemperatureType::Celsius

View File

@ -1,102 +1,89 @@
use failure::Fail;
use std::result; use std::result;
/// A type alias for handling errors related to Bottom. /// A type alias for handling errors related to Bottom.
pub type Result<T> = result::Result<T, BottomError>; pub type Result<T> = result::Result<T, BottomError>;
/// An error that can occur while Bottom runs. /// An error that can occur while Bottom runs.
#[derive(Debug, Fail)] #[derive(Debug)]
pub enum BottomError { pub enum BottomError {
/// An error when there is an IO exception. /// An error when there is an IO exception.
/// InvalidIO(String),
/// The data provided is the error found.
#[fail(display = "ERROR: Encountered an IO exception: {}", message)]
InvalidIO { message: String },
/// An error when there is an invalid argument passed in. /// An error when there is an invalid argument passed in.
/// InvalidArg(String),
/// The data provided is the error found.
#[fail(display = "ERROR: Invalid argument: {}", message)]
InvalidArg { message: String },
/// An error when the heim library encounters a problem. /// An error when the heim library encounters a problem.
/// InvalidHeim(String),
/// The data provided is the error found.
#[fail(
display = "ERROR: Invalid error during data collection due to Heim: {}",
message
)]
InvalidHeim { message: String },
/// An error when the Crossterm library encounters a problem. /// An error when the Crossterm library encounters a problem.
/// CrosstermError(String),
/// The data provided is the error found. /// An error to represent generic errors.
#[fail(display = "ERROR: Invalid error due to Crossterm: {}", message)] GenericError(String),
CrosstermError { message: String }, /// An error to represent errors with fern.
/// An error to represent generic errors FernError(String),
/// /// An error to represent errors with the config.
/// The data provided is the error found. ConfigError(String),
#[fail(display = "ERROR: Invalid generic error: {}", message)] }
GenericError { message: String },
/// An error to represent errors with fern impl std::fmt::Display for BottomError {
/// fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
/// The data provided is the error found. match *self {
#[fail(display = "ERROR: Invalid fern error: {}", message)] BottomError::InvalidIO(ref message) => {
FernError { message: String }, write!(f, "Encountered an IO exception: {}", message)
/// An error to represent errors with fern }
/// BottomError::InvalidArg(ref message) => write!(f, "Invalid argument: {}", message),
/// The data provided is the error found. BottomError::InvalidHeim(ref message) => write!(
#[fail(display = "ERROR: Invalid config file error: {}", message)] f,
ConfigError { message: String }, "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<std::io::Error> for BottomError { impl From<std::io::Error> for BottomError {
fn from(err: std::io::Error) -> Self { fn from(err: std::io::Error) -> Self {
BottomError::InvalidIO { BottomError::InvalidIO(err.to_string())
message: err.to_string(),
}
} }
} }
impl From<heim::Error> for BottomError { impl From<heim::Error> for BottomError {
fn from(err: heim::Error) -> Self { fn from(err: heim::Error) -> Self {
BottomError::InvalidHeim { BottomError::InvalidHeim(err.to_string())
message: err.to_string(),
}
} }
} }
impl From<crossterm::ErrorKind> for BottomError { impl From<crossterm::ErrorKind> for BottomError {
fn from(err: crossterm::ErrorKind) -> Self { fn from(err: crossterm::ErrorKind) -> Self {
BottomError::CrosstermError { BottomError::CrosstermError(err.to_string())
message: err.to_string(),
}
} }
} }
impl From<std::num::ParseIntError> for BottomError { impl From<std::num::ParseIntError> for BottomError {
fn from(err: std::num::ParseIntError) -> Self { fn from(err: std::num::ParseIntError) -> Self {
BottomError::InvalidArg { BottomError::InvalidArg(err.to_string())
message: err.to_string(),
}
} }
} }
impl From<std::string::String> for BottomError { impl From<std::string::String> for BottomError {
fn from(err: std::string::String) -> Self { fn from(err: std::string::String) -> Self {
BottomError::GenericError { message: err } BottomError::GenericError(err)
} }
} }
impl From<toml::de::Error> for BottomError { impl From<toml::de::Error> for BottomError {
fn from(err: toml::de::Error) -> Self { fn from(err: toml::de::Error) -> Self {
BottomError::ConfigError { BottomError::ConfigError(err.to_string())
message: err.to_string(),
}
} }
} }
impl From<fern::InitError> for BottomError { impl From<fern::InitError> for BottomError {
fn from(err: fern::InitError) -> Self { fn from(err: fern::InitError) -> Self {
BottomError::FernError { BottomError::FernError(err.to_string())
message: err.to_string(),
}
} }
} }