mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-10 14:44:18 +00:00
feature: add nord and nord-light colours (#406)
Adds colour schemes for Nord, along with a light variant.
This commit is contained in:
parent
f2e6b9232d
commit
fb7b1226fd
11 changed files with 211 additions and 148 deletions
|
@ -9,13 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## Features
|
||||
|
||||
- [#263](https://github.com/ClementTsang/bottom/pull/263): Adds the option for fine-grained kill signals on Unix-like systems.
|
||||
|
||||
- [#333](https://github.com/ClementTsang/bottom/pull/333): Adds an "out of" indicator that can be enabled using `--show_table_scroll_position` (and its corresponding config option) to help keep track of scrolled position.
|
||||
|
||||
- [#379](https://github.com/ClementTsang/bottom/pull/379): Adds `--process_command` flag and corresponding config option to default to showing a process' command.
|
||||
|
||||
- [#381](https://github.com/ClementTsang/bottom/pull/381): Adds a filter in the config file for network interfaces.
|
||||
|
||||
## [0.5.8] - Unreleased
|
||||
- [#406](https://github.com/ClementTsang/bottom/pull/406): Adds the Nord colour scheme, as well as a light variant.
|
||||
|
||||
## Changes
|
||||
|
||||
|
|
50
README.md
50
README.md
|
@ -563,31 +563,31 @@ The following options can be set under `[flags]` to achieve the same effect as p
|
|||
|
||||
These are the following supported flag config values, which correspond to the flag of the same name described in [Flags](#flags):
|
||||
|
||||
| Field | Type | Functionality |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| `hide_avg_cpu` | Boolean | Hides the average CPU usage. |
|
||||
| `dot_marker` | Boolean | Uses a dot marker for graphs. |
|
||||
| `left_legend` | Boolean | Puts the CPU chart legend to the left side. |
|
||||
| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. |
|
||||
| `group_processes` | Boolean | Groups processes with the same name by default. |
|
||||
| `case_sensitive` | Boolean | Enables case sensitivity by default. |
|
||||
| `whole_word` | Boolean | Enables whole-word matching by default. |
|
||||
| `regex` | Boolean | Enables regex by default. |
|
||||
| `basic` | Boolean | Hides graphs and uses a more basic look. |
|
||||
| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. |
|
||||
| `battery` | Boolean | Shows the battery widget. |
|
||||
| `rate` | Unsigned Int (represents milliseconds) | Sets a refresh rate in ms. |
|
||||
| `default_time_value` | Unsigned Int (represents milliseconds) | Default time value for graphs in ms. |
|
||||
| `time_delta` | Unsigned Int (represents milliseconds) | The amount in ms changed upon zooming. |
|
||||
| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. |
|
||||
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. |
|
||||
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. |
|
||||
| `disable_click` | Boolean | Disables mouse clicks. |
|
||||
| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light"]) | Use a color scheme, use --help for supported values. |
|
||||
| `mem_as_value` | Boolean | Defaults to showing process memory usage by value. |
|
||||
| `tree` | Boolean | Defaults to showing the process widget in tree mode. |
|
||||
| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. |
|
||||
| `process_command` | Boolean | Show processes as their commands by default. |
|
||||
| Field | Type | Functionality |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| `hide_avg_cpu` | Boolean | Hides the average CPU usage. |
|
||||
| `dot_marker` | Boolean | Uses a dot marker for graphs. |
|
||||
| `left_legend` | Boolean | Puts the CPU chart legend to the left side. |
|
||||
| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. |
|
||||
| `group_processes` | Boolean | Groups processes with the same name by default. |
|
||||
| `case_sensitive` | Boolean | Enables case sensitivity by default. |
|
||||
| `whole_word` | Boolean | Enables whole-word matching by default. |
|
||||
| `regex` | Boolean | Enables regex by default. |
|
||||
| `basic` | Boolean | Hides graphs and uses a more basic look. |
|
||||
| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. |
|
||||
| `battery` | Boolean | Shows the battery widget. |
|
||||
| `rate` | Unsigned Int (represents milliseconds) | Sets a refresh rate in ms. |
|
||||
| `default_time_value` | Unsigned Int (represents milliseconds) | Default time value for graphs in ms. |
|
||||
| `time_delta` | Unsigned Int (represents milliseconds) | The amount in ms changed upon zooming. |
|
||||
| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. |
|
||||
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. |
|
||||
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. |
|
||||
| `disable_click` | Boolean | Disables mouse clicks. |
|
||||
| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light", "nord", "nord-light"]) | Use a color scheme, use --help for supported values. |
|
||||
| `mem_as_value` | Boolean | Defaults to showing process memory usage by value. |
|
||||
| `tree` | Boolean | Defaults to showing the process widget in tree mode. |
|
||||
| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. |
|
||||
| `process_command` | Boolean | Show processes as their commands by default. |
|
||||
|
||||
#### Theming
|
||||
|
||||
|
|
48
src/app.rs
48
src/app.rs
|
@ -526,7 +526,7 @@ impl App {
|
|||
);
|
||||
}
|
||||
|
||||
self.did_config_fail_to_save = self.update_config_file().is_err();
|
||||
// self.did_config_fail_to_save = self.update_config_file().is_err();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -586,7 +586,7 @@ impl App {
|
|||
);
|
||||
}
|
||||
|
||||
self.did_config_fail_to_save = self.update_config_file().is_err();
|
||||
// self.did_config_fail_to_save = self.update_config_file().is_err();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,7 +642,7 @@ impl App {
|
|||
);
|
||||
}
|
||||
|
||||
self.did_config_fail_to_save = self.update_config_file().is_err();
|
||||
// self.did_config_fail_to_save = self.update_config_file().is_err();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1565,28 +1565,28 @@ impl App {
|
|||
self.is_force_redraw = true;
|
||||
}
|
||||
|
||||
/// TODO: Disabled.
|
||||
/// Call this whenever the config value is updated!
|
||||
fn update_config_file(&mut self) -> anyhow::Result<()> {
|
||||
// TODO: Disabled.
|
||||
// if self.app_config_fields.no_write {
|
||||
// // debug!("No write enabled. Config will not be written.");
|
||||
// // Don't write!
|
||||
// // FIXME: [CONFIG] This should be made VERY clear to the user... make a thing saying "it will not write due to no_write option"
|
||||
// Ok(())
|
||||
// } else if let Some(config_path) = &self.config_path {
|
||||
// // Update
|
||||
// // debug!("Updating config file - writing to: {:?}", config_path);
|
||||
// std::fs::File::create(config_path)?
|
||||
// .write_all(self.config.get_config_as_bytes()?.as_ref())?;
|
||||
// Ok(())
|
||||
// } else {
|
||||
// // FIXME: [CONFIG] Put an actual error message?
|
||||
// Err(anyhow::anyhow!(
|
||||
// "Config path was missing, please try restarting bottom..."
|
||||
// ))
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
// fn update_config_file(&mut self) -> anyhow::Result<()> {
|
||||
// if self.app_config_fields.no_write {
|
||||
// // debug!("No write enabled. Config will not be written.");
|
||||
// // Don't write!
|
||||
// // FIXME: [CONFIG] This should be made VERY clear to the user... make a thing saying "it will not write due to no_write option"
|
||||
// Ok(())
|
||||
// } else if let Some(config_path) = &self.config_path {
|
||||
// // Update
|
||||
// // debug!("Updating config file - writing to: {:?}", config_path);
|
||||
// std::fs::File::create(config_path)?
|
||||
// .write_all(self.config.get_config_as_bytes()?.as_ref())?;
|
||||
// Ok(())
|
||||
// } else {
|
||||
// // FIXME: [CONFIG] Put an actual error message?
|
||||
// Err(anyhow::anyhow!(
|
||||
// "Config path was missing, please try restarting bottom..."
|
||||
// ))
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn kill_highlighted_process(&mut self) -> Result<()> {
|
||||
if let BottomWidgetType::Proc = self.current_widget.widget_type {
|
||||
|
|
|
@ -12,20 +12,24 @@ pub struct BottomLayout {
|
|||
pub total_row_height_ratio: u32,
|
||||
}
|
||||
|
||||
type WidgetMappings = (u32, BTreeMap<(u32, u32), u64>);
|
||||
type ColumnRowMappings = (u32, BTreeMap<(u32, u32), WidgetMappings>);
|
||||
type ColumnMappings = (u32, BTreeMap<(u32, u32), ColumnRowMappings>);
|
||||
// Represents a start and end coordinate in some dimension.
|
||||
type LineSegment = (u32, u32);
|
||||
|
||||
type WidgetMappings = (u32, BTreeMap<LineSegment, u64>);
|
||||
type ColumnRowMappings = (u32, BTreeMap<LineSegment, WidgetMappings>);
|
||||
type ColumnMappings = (u32, BTreeMap<LineSegment, ColumnRowMappings>);
|
||||
|
||||
impl BottomLayout {
|
||||
pub fn get_movement_mappings(&mut self) {
|
||||
fn is_intersecting(a: (u32, u32), b: (u32, u32)) -> bool {
|
||||
#[allow(clippy::suspicious_operation_groupings)] // Have to enable this, clippy really doesn't like me doing this with tuples...
|
||||
fn is_intersecting(a: LineSegment, b: LineSegment) -> bool {
|
||||
a.0 >= b.0 && a.1 <= b.1
|
||||
|| a.1 >= b.1 && a.0 <= b.0
|
||||
|| a.0 <= b.0 && a.1 >= b.0
|
||||
|| a.0 >= b.0 && a.0 < b.1 && a.1 >= b.1
|
||||
}
|
||||
|
||||
fn get_distance(target: (u32, u32), candidate: (u32, u32)) -> u32 {
|
||||
fn get_distance(target: LineSegment, candidate: LineSegment) -> u32 {
|
||||
if candidate.0 < target.0 {
|
||||
candidate.1 - target.0
|
||||
} else if candidate.1 < target.1 {
|
||||
|
@ -38,20 +42,20 @@ impl BottomLayout {
|
|||
// Now we need to create the correct mapping for moving from a specific
|
||||
// widget to another
|
||||
|
||||
let mut layout_mapping: BTreeMap<(u32, u32), ColumnMappings> = BTreeMap::new();
|
||||
let mut layout_mapping: BTreeMap<LineSegment, ColumnMappings> = BTreeMap::new();
|
||||
let mut total_height = 0;
|
||||
for row in &self.rows {
|
||||
let mut row_width = 0;
|
||||
let mut row_mapping: BTreeMap<(u32, u32), ColumnRowMappings> = BTreeMap::new();
|
||||
let mut row_mapping: BTreeMap<LineSegment, ColumnRowMappings> = BTreeMap::new();
|
||||
let mut is_valid_row = false;
|
||||
for col in &row.children {
|
||||
let mut col_row_height = 0;
|
||||
let mut col_mapping: BTreeMap<(u32, u32), WidgetMappings> = BTreeMap::new();
|
||||
let mut col_mapping: BTreeMap<LineSegment, WidgetMappings> = BTreeMap::new();
|
||||
let mut is_valid_col = false;
|
||||
|
||||
for col_row in &col.children {
|
||||
let mut widget_width = 0;
|
||||
let mut col_row_mapping: BTreeMap<(u32, u32), u64> = BTreeMap::new();
|
||||
let mut col_row_mapping: BTreeMap<LineSegment, u64> = BTreeMap::new();
|
||||
let mut is_valid_col_row = false;
|
||||
for widget in &col_row.children {
|
||||
match widget.widget_type {
|
||||
|
|
|
@ -27,7 +27,11 @@ impl Process {
|
|||
}
|
||||
|
||||
fn kill(self) -> Result<(), String> {
|
||||
unsafe { TerminateProcess(self.0, 1) };
|
||||
let result = unsafe { TerminateProcess(self.0, 1) };
|
||||
if result == 0 {
|
||||
return Err("Failed to kill process".to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -625,34 +625,33 @@ impl Prefix {
|
|||
is_ignoring_case,
|
||||
is_searching_with_regex,
|
||||
);
|
||||
} else if let Some((prefix_type, query_content)) = &mut self.regex_prefix {
|
||||
if let StringQuery::Value(regex_string) = query_content {
|
||||
match prefix_type {
|
||||
PrefixType::Pid | PrefixType::Name | PrefixType::State => {
|
||||
let escaped_regex: String;
|
||||
let final_regex_string = &format!(
|
||||
"{}{}{}{}",
|
||||
if is_searching_whole_word { "^" } else { "" },
|
||||
if is_ignoring_case { "(?i)" } else { "" },
|
||||
if !is_searching_with_regex {
|
||||
escaped_regex = regex::escape(regex_string);
|
||||
&escaped_regex
|
||||
} else {
|
||||
regex_string
|
||||
},
|
||||
if is_searching_whole_word { "$" } else { "" },
|
||||
);
|
||||
} else if let Some((prefix_type, StringQuery::Value(regex_string))) = &mut self.regex_prefix
|
||||
{
|
||||
match prefix_type {
|
||||
PrefixType::Pid | PrefixType::Name | PrefixType::State => {
|
||||
let escaped_regex: String;
|
||||
let final_regex_string = &format!(
|
||||
"{}{}{}{}",
|
||||
if is_searching_whole_word { "^" } else { "" },
|
||||
if is_ignoring_case { "(?i)" } else { "" },
|
||||
if !is_searching_with_regex {
|
||||
escaped_regex = regex::escape(regex_string);
|
||||
&escaped_regex
|
||||
} else {
|
||||
regex_string
|
||||
},
|
||||
if is_searching_whole_word { "$" } else { "" },
|
||||
);
|
||||
|
||||
let taken_pwc = self.regex_prefix.take();
|
||||
if let Some((taken_pt, _)) = taken_pwc {
|
||||
self.regex_prefix = Some((
|
||||
taken_pt,
|
||||
StringQuery::Regex(regex::Regex::new(final_regex_string)?),
|
||||
));
|
||||
}
|
||||
let taken_pwc = self.regex_prefix.take();
|
||||
if let Some((taken_pt, _)) = taken_pwc {
|
||||
self.regex_prefix = Some((
|
||||
taken_pt,
|
||||
StringQuery::Regex(regex::Regex::new(final_regex_string)?),
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,8 @@ pub enum ColourScheme {
|
|||
DefaultLight,
|
||||
Gruvbox,
|
||||
GruvboxLight,
|
||||
// Nord,
|
||||
Nord,
|
||||
NordLight,
|
||||
Custom,
|
||||
}
|
||||
|
||||
|
@ -80,7 +81,8 @@ impl FromStr for ColourScheme {
|
|||
"default-light" => Ok(ColourScheme::DefaultLight),
|
||||
"gruvbox" => Ok(ColourScheme::Gruvbox),
|
||||
"gruvbox-light" => Ok(ColourScheme::GruvboxLight),
|
||||
// "nord" => Ok(ColourScheme::Nord),
|
||||
"nord" => Ok(ColourScheme::Nord),
|
||||
"nord-light" => Ok(ColourScheme::NordLight),
|
||||
_ => Err(BottomError::ConfigError(format!(
|
||||
"\"{}\" is an invalid built-in color scheme.",
|
||||
s
|
||||
|
@ -227,10 +229,14 @@ impl Painter {
|
|||
self.colours
|
||||
.set_colours_from_palette(&*GRUVBOX_LIGHT_COLOUR_PALETTE)?;
|
||||
}
|
||||
// ColourScheme::Nord => {
|
||||
// self.colours
|
||||
// .set_colours_from_palette(&*NORD_COLOUR_PALETTE)?;
|
||||
// }
|
||||
ColourScheme::Nord => {
|
||||
self.colours
|
||||
.set_colours_from_palette(&*NORD_COLOUR_PALETTE)?;
|
||||
}
|
||||
ColourScheme::NordLight => {
|
||||
self.colours
|
||||
.set_colours_from_palette(&*NORD_LIGHT_COLOUR_PALETTE)?;
|
||||
}
|
||||
ColourScheme::Custom => {
|
||||
// This case should never occur, just do nothing.
|
||||
}
|
||||
|
|
13
src/clap.rs
13
src/clap.rs
|
@ -231,11 +231,22 @@ Use a pre-defined color scheme. Currently supported values are:
|
|||
+------------------------------------------------------------+
|
||||
| gruvbox-light (gruvbox but for use with light backgrounds) |
|
||||
+------------------------------------------------------------+
|
||||
| nord (an arctic, north-bluish color palette) |
|
||||
+------------------------------------------------------------+
|
||||
| nord-light (nord but for use with light backgrounds) |
|
||||
+------------------------------------------------------------+
|
||||
|
||||
Defaults to \"default\".
|
||||
\n\n",
|
||||
)
|
||||
.possible_values(&["default", "default-light", "gruvbox", "gruvbox-light"])
|
||||
.possible_values(&[
|
||||
"default",
|
||||
"default-light",
|
||||
"gruvbox",
|
||||
"gruvbox-light",
|
||||
"nord",
|
||||
"nord-light",
|
||||
])
|
||||
.hide_possible_values(true);
|
||||
let mem_as_value = Arg::with_name("mem_as_value")
|
||||
.long("mem_as_value")
|
||||
|
|
|
@ -45,6 +45,7 @@ pub static DEFAULT_LIGHT_MODE_COLOUR_PALETTE: Lazy<ConfigColours> = Lazy::new(||
|
|||
disabled_text_color: Some("gray".to_string()),
|
||||
..ConfigColours::default()
|
||||
});
|
||||
|
||||
pub static GRUVBOX_COLOUR_PALETTE: Lazy<ConfigColours> = Lazy::new(|| ConfigColours {
|
||||
table_header_color: Some("#83a598".to_string()),
|
||||
all_cpu_color: Some("#8ec07c".to_string()),
|
||||
|
@ -89,6 +90,7 @@ pub static GRUVBOX_COLOUR_PALETTE: Lazy<ConfigColours> = Lazy::new(|| ConfigColo
|
|||
medium_battery_color: Some("#fabd2f".to_string()),
|
||||
low_battery_color: Some("#fb4934".to_string()),
|
||||
});
|
||||
|
||||
pub static GRUVBOX_LIGHT_COLOUR_PALETTE: Lazy<ConfigColours> = Lazy::new(|| ConfigColours {
|
||||
table_header_color: Some("#076678".to_string()),
|
||||
all_cpu_color: Some("#8ec07c".to_string()),
|
||||
|
@ -134,6 +136,72 @@ pub static GRUVBOX_LIGHT_COLOUR_PALETTE: Lazy<ConfigColours> = Lazy::new(|| Conf
|
|||
low_battery_color: Some("#cc241d".to_string()),
|
||||
});
|
||||
|
||||
pub static NORD_COLOUR_PALETTE: Lazy<ConfigColours> = Lazy::new(|| ConfigColours {
|
||||
table_header_color: Some("#81a1c1".to_string()),
|
||||
all_cpu_color: Some("#88c0d0".to_string()),
|
||||
avg_cpu_color: Some("#8fbcbb".to_string()),
|
||||
cpu_core_colors: Some(vec![
|
||||
"#5e81ac".to_string(),
|
||||
"#81a1c1".to_string(),
|
||||
"#d8dee9".to_string(),
|
||||
"#b48ead".to_string(),
|
||||
"#a3be8c".to_string(),
|
||||
"#ebcb8b".to_string(),
|
||||
"#d08770".to_string(),
|
||||
"#bf616a".to_string(),
|
||||
]),
|
||||
ram_color: Some("#88c0d0".to_string()),
|
||||
swap_color: Some("#d08770".to_string()),
|
||||
rx_color: Some("#88c0d0".to_string()),
|
||||
tx_color: Some("#d08770".to_string()),
|
||||
rx_total_color: Some("#5e81ac".to_string()),
|
||||
tx_total_color: Some("#8fbcbb".to_string()),
|
||||
border_color: Some("#e5e9f0".to_string()),
|
||||
highlighted_border_color: Some("#88c0d0".to_string()),
|
||||
disabled_text_color: Some("#4c566a".to_string()),
|
||||
text_color: Some("#e5e9f0".to_string()),
|
||||
selected_text_color: Some("#2e3440".to_string()),
|
||||
selected_bg_color: Some("#88c0d0".to_string()),
|
||||
widget_title_color: Some("#e5e9f0".to_string()),
|
||||
graph_color: Some("#e5e9f0".to_string()),
|
||||
high_battery_color: Some("#a3be8c".to_string()),
|
||||
medium_battery_color: Some("#ebcb8b".to_string()),
|
||||
low_battery_color: Some("#bf616a".to_string()),
|
||||
});
|
||||
|
||||
pub static NORD_LIGHT_COLOUR_PALETTE: Lazy<ConfigColours> = Lazy::new(|| ConfigColours {
|
||||
table_header_color: Some("#5e81ac".to_string()),
|
||||
all_cpu_color: Some("#81a1c1".to_string()),
|
||||
avg_cpu_color: Some("#8fbcbb".to_string()),
|
||||
cpu_core_colors: Some(vec![
|
||||
"#5e81ac".to_string(),
|
||||
"#88c0d0".to_string(),
|
||||
"#4c566a".to_string(),
|
||||
"#b48ead".to_string(),
|
||||
"#a3be8c".to_string(),
|
||||
"#ebcb8b".to_string(),
|
||||
"#d08770".to_string(),
|
||||
"#bf616a".to_string(),
|
||||
]),
|
||||
ram_color: Some("#81a1c1".to_string()),
|
||||
swap_color: Some("#d08770".to_string()),
|
||||
rx_color: Some("#81a1c1".to_string()),
|
||||
tx_color: Some("#d08770".to_string()),
|
||||
rx_total_color: Some("#5e81ac".to_string()),
|
||||
tx_total_color: Some("#8fbcbb".to_string()),
|
||||
border_color: Some("#2e3440".to_string()),
|
||||
highlighted_border_color: Some("#5e81ac".to_string()),
|
||||
disabled_text_color: Some("#d8dee9".to_string()),
|
||||
text_color: Some("#2e3440".to_string()),
|
||||
selected_text_color: Some("#f5f5f5".to_string()),
|
||||
selected_bg_color: Some("#5e81ac".to_string()),
|
||||
widget_title_color: Some("#2e3440".to_string()),
|
||||
graph_color: Some("#2e3440".to_string()),
|
||||
high_battery_color: Some("#a3be8c".to_string()),
|
||||
medium_battery_color: Some("#ebcb8b".to_string()),
|
||||
low_battery_color: Some("#bf616a".to_string()),
|
||||
});
|
||||
|
||||
// Help text
|
||||
pub const HELP_CONTENTS_TEXT: [&str; 8] = [
|
||||
"Press the corresponding numbers to jump to the section, or scroll:",
|
||||
|
|
|
@ -11,7 +11,7 @@ fn get_binary_location() -> String {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_small_rate() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_small_rate() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-r")
|
||||
.arg("249")
|
||||
|
@ -20,11 +20,10 @@ fn test_small_rate() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"set your update rate to be at least 250 milliseconds.",
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_large_default_time() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_large_default_time() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-t")
|
||||
.arg("18446744073709551616")
|
||||
|
@ -33,11 +32,10 @@ fn test_large_default_time() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"set your default value to be at most",
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_small_default_time() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_small_default_time() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-t")
|
||||
.arg("900")
|
||||
|
@ -46,11 +44,10 @@ fn test_small_default_time() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"set your default value to be at least",
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_large_delta_time() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_large_delta_time() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-d")
|
||||
.arg("18446744073709551616")
|
||||
|
@ -59,11 +56,10 @@ fn test_large_delta_time() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"set your time delta to be at most",
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_small_delta_time() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_small_delta_time() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-d")
|
||||
.arg("900")
|
||||
|
@ -72,11 +68,10 @@ fn test_small_delta_time() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"set your time delta to be at least",
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_large_rate() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_large_rate() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-r")
|
||||
.arg("18446744073709551616")
|
||||
|
@ -85,11 +80,10 @@ fn test_large_rate() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"set your update rate to be at most unsigned INT_MAX.",
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_negative_rate() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_negative_rate() {
|
||||
// This test should auto fail due to how clap works
|
||||
Command::new(get_binary_location())
|
||||
.arg("-r")
|
||||
|
@ -99,24 +93,20 @@ fn test_negative_rate() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"wasn't expected, or isn't valid in this context",
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_rate() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_rate() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-r")
|
||||
.arg("100-1000")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid digit"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_conflicting_temps() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_conflicting_temps() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-c")
|
||||
.arg("-f")
|
||||
|
@ -125,24 +115,20 @@ fn test_conflicting_temps() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"cannot be used with one or more of the other specified arguments",
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_default_widget_1() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_default_widget_1() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("--default_widget_type")
|
||||
.arg("fake_widget")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid widget name"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_default_widget_2() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_default_widget_2() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("--default_widget_type")
|
||||
.arg("cpu")
|
||||
|
@ -153,12 +139,10 @@ fn test_invalid_default_widget_2() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.stderr(predicate::str::contains(
|
||||
"set your widget count to be at most unsigned INT_MAX",
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_default_widget_type() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_missing_default_widget_type() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("--default_widget_count")
|
||||
.arg("3")
|
||||
|
@ -167,6 +151,4 @@ fn test_missing_default_widget_type() -> Result<(), Box<dyn std::error::Error>>
|
|||
.stderr(predicate::str::contains(
|
||||
"The following required arguments were not provided",
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -9,150 +9,137 @@ fn get_binary_location() -> String {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_toml_mismatch_type() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_toml_mismatch_type() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/toml_mismatch_type.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid type"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_layout() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_empty_layout() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/empty_layout.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("at least one widget"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_layout_widget_type() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_layout_widget_type() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_layout_widget_type.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid widget name"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This test isn't really needed as this is technically covered by TOML spec.
|
||||
/// However, I feel like it's worth checking anyways - not like it takes long.
|
||||
#[test]
|
||||
fn test_duplicate_temp_type() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_duplicate_temp_type() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/duplicate_temp_type.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("duplicate field"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks for if a hex is valid
|
||||
#[test]
|
||||
fn test_invalid_colour_hex() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_colour_hex() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_colour_hex.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid hex colour"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks for if a hex is too long
|
||||
#[test]
|
||||
fn test_invalid_colour_hex_2() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_colour_hex_2() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_colour_hex_2.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid hex colour"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks unicode hex because the way we originally did it could cause char
|
||||
/// boundary errors!
|
||||
#[test]
|
||||
fn test_invalid_colour_hex_3() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_colour_hex_3() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_colour_hex_3.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid hex colour"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_colour_name() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_colour_name() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_colour_name.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid named colour"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_colour_rgb() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_colour_rgb() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_colour_rgb.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid RGB"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_colour_rgb_2() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_colour_rgb_2() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_colour_rgb_2.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid RGB"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_colour_string() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_colour_string() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_colour_string.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid named colour"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lone_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_lone_default_widget_count() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/lone_default_widget_count.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("it must be used with"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn test_invalid_default_widget_count() {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/invalid_default_widget_count.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("invalid number"));
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue