refactor: use clippy::unwrap_used (#1882)

* refactor: use clippy::unwrap_used

* fix log format use

* fix a bunch of macos ones

* oop

* allow schema script

* driveby schema bump
This commit is contained in:
Clement Tsang 2025-11-22 23:26:02 -05:00 committed by GitHub
parent 85af7ba50d
commit 86b35bcd79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 188 additions and 120 deletions

View File

@ -254,3 +254,4 @@ missing_crate_level_docs = "deny"
todo = "deny" todo = "deny"
unimplemented = "deny" unimplemented = "deny"
missing_safety_doc = "deny" missing_safety_doc = "deny"
unwrap_used = "deny"

View File

@ -1,5 +1,7 @@
//! General build script used by bottom to generate completion files and set binary version. //! General build script used by bottom to generate completion files and set binary version.
#![expect(clippy::unwrap_used)]
#[expect(dead_code)] #[expect(dead_code)]
#[path = "src/options/args.rs"] #[path = "src/options/args.rs"]
mod args; mod args;

View File

@ -1,3 +1,5 @@
cognitive-complexity-threshold = 100 cognitive-complexity-threshold = 100
type-complexity-threshold = 500 type-complexity-threshold = 500
too-many-arguments-threshold = 8 too-many-arguments-threshold = 8
allow-unwrap-in-consts = true
allow-unwrap-in-tests = true

View File

@ -471,6 +471,12 @@
} }
] ]
}, },
"read_only": {
"type": [
"boolean",
"null"
]
},
"regex": { "regex": {
"type": [ "type": [
"boolean", "boolean",

View File

@ -213,7 +213,7 @@ impl StoredData {
reason = "this is fine since it's done via a static OnceLock. In the future though, separate it out." reason = "this is fine since it's done via a static OnceLock. In the future though, separate it out."
)] )]
if let Some(new_name) = DISK_REGEX if let Some(new_name) = DISK_REGEX
.get_or_init(|| Regex::new(r"disk\d+").unwrap()) .get_or_init(|| Regex::new(r"disk\d+").expect("valid regex"))
.find(checked_name) .find(checked_name)
{ {
io.get(new_name.as_str()) io.get(new_name.as_str())

View File

@ -192,7 +192,7 @@ impl AppSearchState {
self.grapheme_cursor self.grapheme_cursor
.next_boundary(chunk, start_position) .next_boundary(chunk, start_position)
.unwrap(); .expect("another grapheme boundary should exist after the cursor with the provided context");
} }
_ => panic!("{err:?}"), _ => panic!("{err:?}"),
}, },
@ -213,7 +213,9 @@ impl AppSearchState {
self.grapheme_cursor self.grapheme_cursor
.provide_context(&self.current_search_query[0..ctx], 0); .provide_context(&self.current_search_query[0..ctx], 0);
self.grapheme_cursor.prev_boundary(chunk, 0).unwrap(); self.grapheme_cursor
.prev_boundary(chunk, 0)
.expect("another grapheme boundary should exist before the cursor with the provided context");
} }
_ => panic!("{err:?}"), _ => panic!("{err:?}"),
}, },

View File

@ -1,4 +1,8 @@
#![cfg(feature = "generate_schema")] #![cfg(feature = "generate_schema")]
#![expect(
clippy::unwrap_used,
reason = "this is just used to generate jsonschema files"
)]
use bottom::{options::config, widgets}; use bottom::{options::config, widgets};
use clap::Parser; use clap::Parser;

View File

@ -674,17 +674,22 @@ impl<'a> TimeChart<'a> {
&self, buf: &mut Buffer, layout: &ChartLayout, chart_area: Rect, graph_area: Rect, &self, buf: &mut Buffer, layout: &ChartLayout, chart_area: Rect, graph_area: Rect,
) { ) {
let Some(y) = layout.label_x else { return }; let Some(y) = layout.label_x else { return };
let labels = self.x_axis.labels.as_ref().unwrap(); let Some(labels) = self.x_axis.labels.as_ref() else {
return;
};
let labels_len = labels.len() as u16; let labels_len = labels.len() as u16;
if labels_len < 2 { if labels_len < 2 {
return; return;
} }
let first_label = labels.first().expect("must have at least 2 labels");
let last_label = labels.last().expect("must have at least 2 labels");
let width_between_ticks = graph_area.width / labels_len; let width_between_ticks = graph_area.width / labels_len;
let label_area = self.first_x_label_area( let label_area = self.first_x_label_area(
y, y,
labels.first().unwrap().width() as u16, first_label.width() as u16,
width_between_ticks, width_between_ticks,
chart_area, chart_area,
graph_area, graph_area,
@ -696,7 +701,7 @@ impl<'a> TimeChart<'a> {
Alignment::Right => Alignment::Left, Alignment::Right => Alignment::Left,
}; };
Self::render_label(buf, labels.first().unwrap(), label_area, label_alignment); Self::render_label(buf, first_label, label_area, label_alignment);
for (i, label) in labels[1..labels.len() - 1].iter().enumerate() { for (i, label) in labels[1..labels.len() - 1].iter().enumerate() {
// We add 1 to x (and width-1 below) to leave at least one space before each // We add 1 to x (and width-1 below) to leave at least one space before each
@ -710,7 +715,7 @@ impl<'a> TimeChart<'a> {
let x = graph_area.right() - width_between_ticks; let x = graph_area.right() - width_between_ticks;
let label_area = Rect::new(x, y, width_between_ticks, 1); let label_area = Rect::new(x, y, width_between_ticks, 1);
// The last label should be aligned Right to be at the edge of the graph area // The last label should be aligned Right to be at the edge of the graph area
Self::render_label(buf, labels.last().unwrap(), label_area, Alignment::Right); Self::render_label(buf, last_label, label_area, Alignment::Right);
} }
fn first_x_label_area( fn first_x_label_area(
@ -751,8 +756,11 @@ impl<'a> TimeChart<'a> {
// FIXME: Control how many y-axis labels are rendered based on height. // FIXME: Control how many y-axis labels are rendered based on height.
let Some(x) = layout.label_y else { return }; let Some(x) = layout.label_y else { return };
let labels = self.y_axis.labels.as_ref().unwrap(); let Some(labels) = self.y_axis.labels.as_ref() else {
return;
};
let labels_len = labels.len() as u16; let labels_len = labels.len() as u16;
for (i, label) in labels.iter().enumerate() { for (i, label) in labels.iter().enumerate() {
let dy = i as u16 * (graph_area.height - 1) / (labels_len - 1); let dy = i as u16 * (graph_area.height - 1) / (labels_len - 1);
if dy < graph_area.bottom() { if dy < graph_area.bottom() {
@ -836,7 +844,7 @@ impl Widget for TimeChart<'_> {
.render(graph_area, buf); .render(graph_area, buf);
if let Some((x, y)) = layout.title_x { if let Some((x, y)) = layout.title_x {
let title = self.x_axis.title.as_ref().unwrap(); if let Some(title) = self.x_axis.title.as_ref() {
let width = graph_area let width = graph_area
.right() .right()
.saturating_sub(x) .saturating_sub(x)
@ -852,9 +860,10 @@ impl Widget for TimeChart<'_> {
); );
buf.set_line(x, y, title, width); buf.set_line(x, y, title, width);
} }
}
if let Some((x, y)) = layout.title_y { if let Some((x, y)) = layout.title_y {
let title = self.y_axis.title.as_ref().unwrap(); if let Some(title) = self.y_axis.title.as_ref() {
let width = graph_area let width = graph_area
.right() .right()
.saturating_sub(x) .saturating_sub(x)
@ -870,6 +879,7 @@ impl Widget for TimeChart<'_> {
); );
buf.set_line(x, y, title, width); buf.set_line(x, y, title, width);
} }
}
if let Some(legend_area) = layout.legend_area { if let Some(legend_area) = layout.legend_area {
buf.set_style(legend_area, original_style); buf.set_style(legend_area, original_style);

View File

@ -75,7 +75,7 @@ impl Grid for BrailleGrid {
} }
fn save(&self) -> Layer { fn save(&self) -> Layer {
let string = String::from_utf16(&self.utf16_code_points).unwrap(); let string = String::from_utf16(&self.utf16_code_points).expect("valid UTF-16 data");
// the background color is always reset for braille patterns // the background color is always reset for braille patterns
let colors = self.colors.iter().map(|c| (*c, Color::Reset)).collect(); let colors = self.colors.iter().map(|c| (*c, Color::Reset)).collect();
Layer { string, colors } Layer { string, colors }

View File

@ -18,8 +18,8 @@ impl Painter {
let current_table = if let BottomWidgetType::ProcSort = current_table.widget_type { let current_table = if let BottomWidgetType::ProcSort = current_table.widget_type {
current_table current_table
.right_neighbour .right_neighbour
.map(|id| app_state.widget_map.get(&id).unwrap()) .and_then(|id| app_state.widget_map.get(&id))
.unwrap() .expect("id must exist in widget mapping")
} else { } else {
current_table current_table
}; };

View File

@ -94,12 +94,12 @@ pub fn get_amd_name(device_path: &Path) -> Option<String> {
rev_data = rev_data.trim_end().to_string(); rev_data = rev_data.trim_end().to_string();
dev_data = dev_data.trim_end().to_string(); dev_data = dev_data.trim_end().to_string();
if rev_data.starts_with("0x") { if let Some(stripped) = rev_data.strip_prefix("0x") {
rev_data = rev_data.strip_prefix("0x").unwrap().to_string(); rev_data = stripped.to_string();
} }
if dev_data.starts_with("0x") { if let Some(stripped) = dev_data.strip_prefix("0x") {
dev_data = dev_data.strip_prefix("0x").unwrap().to_string(); dev_data = stripped.to_string();
} }
let revision_id = u32::from_str_radix(&rev_data, 16).unwrap_or(0); let revision_id = u32::from_str_radix(&rev_data, 16).unwrap_or(0);
@ -353,9 +353,8 @@ pub fn get_amd_vecs(widgets_to_harvest: &UsedWidgets, prev_time: Instant) -> Opt
if widgets_to_harvest.use_proc { if widgets_to_harvest.use_proc {
if let Some(procs) = get_amd_fdinfo(&device_path) { if let Some(procs) = get_amd_fdinfo(&device_path) {
let mut proc_info = PROC_DATA.lock().unwrap(); let mut proc_info = PROC_DATA.lock().expect("mutex is poisoned");
let _ = proc_info.try_insert(device_path.clone(), HashMap::new()); let prev_fdinfo = proc_info.entry(device_path).or_insert_with(HashMap::new);
let prev_fdinfo = proc_info.get_mut(&device_path).unwrap();
let mut procs_map = HashMap::new(); let mut procs_map = HashMap::new();
for (proc_pid, proc_usage) in procs { for (proc_pid, proc_usage) in procs {

View File

@ -117,11 +117,11 @@ pub(crate) trait UnixProcessExt {
.collect(); .collect();
let cpu_usages = Self::backup_proc_cpu(&cpu_usage_unknown_pids)?; let cpu_usages = Self::backup_proc_cpu(&cpu_usage_unknown_pids)?;
for process in &mut process_vector { for process in &mut process_vector {
if cpu_usages.contains_key(&process.pid) { if let Some(&cpu_usage) = cpu_usages.get(&process.pid) {
process.cpu_usage_percent = if unnormalized_cpu || num_processors == 0 { process.cpu_usage_percent = if unnormalized_cpu || num_processors == 0 {
*cpu_usages.get(&process.pid).unwrap() cpu_usage
} else { } else {
*cpu_usages.get(&process.pid).unwrap() / num_processors as f32 cpu_usage / num_processors as f32
}; };
} }
} }

View File

@ -99,7 +99,7 @@ fn check_if_terminal() {
"Warning: bottom is not being output to a terminal. Things might not work properly." "Warning: bottom is not being output to a terminal. Things might not work properly."
); );
eprintln!("If you're stuck, press 'q' or 'Ctrl-c' to quit the program."); eprintln!("If you're stuck, press 'q' or 'Ctrl-c' to quit the program.");
stderr().flush().unwrap(); stderr().flush().expect("should succeed in flushing stderr");
thread::sleep(Duration::from_secs(1)); thread::sleep(Duration::from_secs(1));
} }
} }

View File

@ -526,7 +526,10 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
basic_table_widget_state, basic_table_widget_state,
}; };
let current_widget = widget_map.get(&initial_widget_id).unwrap().clone(); let current_widget = widget_map
.get(&initial_widget_id)
.expect("widget map should have the initial widget ID")
.clone();
let filters = DataFilters { let filters = DataFilters {
disk_filter: disk_name_filter, disk_filter: disk_name_filter,
mount_filter: disk_mount_filter, mount_filter: disk_mount_filter,
@ -568,14 +571,13 @@ fn get_widget_layout(
let rows = match &config.row { let rows = match &config.row {
Some(r) => r, Some(r) => r,
None => { None => {
// This cannot (like it really shouldn't) fail!
ref_row = toml_edit::de::from_str::<Config>(if get_use_battery(args, config) { ref_row = toml_edit::de::from_str::<Config>(if get_use_battery(args, config) {
DEFAULT_BATTERY_LAYOUT DEFAULT_BATTERY_LAYOUT
} else { } else {
DEFAULT_LAYOUT DEFAULT_LAYOUT
})? })?
.row .row
.unwrap(); .expect("This cannot (like it really shouldn't) fail!");
&ref_row &ref_row
} }
}; };

View File

@ -131,7 +131,7 @@ pub struct Styles {
impl Default for Styles { impl Default for Styles {
fn default() -> Self { fn default() -> Self {
Self::default_style() Self::default_palette()
} }
} }
@ -156,8 +156,8 @@ impl Styles {
fn from_theme(theme: &str) -> anyhow::Result<Self> { fn from_theme(theme: &str) -> anyhow::Result<Self> {
let lower_case = theme.to_lowercase(); let lower_case = theme.to_lowercase();
match lower_case.as_str() { match lower_case.as_str() {
"default" => Ok(Self::default_style()), "default" => Ok(Self::default_palette()),
"default-light" => Ok(Self::default_light_mode()), "default-light" => Ok(Self::default_light_palette()),
"gruvbox" => Ok(Self::gruvbox_palette()), "gruvbox" => Ok(Self::gruvbox_palette()),
"gruvbox-light" => Ok(Self::gruvbox_light_palette()), "gruvbox-light" => Ok(Self::gruvbox_light_palette()),
"nord" => Ok(Self::nord_palette()), "nord" => Ok(Self::nord_palette()),
@ -246,8 +246,9 @@ mod test {
#[test] #[test]
fn default_selected_colour_works() { fn default_selected_colour_works() {
let mut colours = Styles::default(); let mut colours = Styles::default();
let original_selected_text_colour = Styles::default_style().selected_text_style.fg.unwrap(); let original_selected_text_colour =
let original_selected_bg_colour = Styles::default_style().selected_text_style.bg.unwrap(); Styles::default_palette().selected_text_style.fg.unwrap();
let original_selected_bg_colour = Styles::default_palette().selected_text_style.bg.unwrap();
assert_eq!( assert_eq!(
colours.selected_text_style, colours.selected_text_style,

View File

@ -4,18 +4,30 @@ pub(super) mod default;
pub(super) mod gruvbox; pub(super) mod gruvbox;
pub(super) mod nord; pub(super) mod nord;
/// Convert a [`tui::style::Color`] into a [`tui::style::Style`] with the color as the foreground.
macro_rules! color { macro_rules! color {
($value:expr) => { ($value:expr) => {
tui::style::Style::new().fg($value) tui::style::Style::new().fg($value)
}; };
} }
/// Convert a hex string to a [`tui::style::Style`], where the hex string is used as the foreground color.
macro_rules! hex { macro_rules! hex {
($value:literal) => { ($value:literal) => {
tui::style::Style::new() tui::style::Style::new().fg(crate::options::config::style::utils::try_hex_to_colour(
.fg(crate::options::config::style::utils::convert_hex_to_color($value.into()).unwrap()) $value.into(),
)
.expect("valid hex"))
};
}
/// Convert a hex string to a [`tui::style::Color`].
macro_rules! hex_colour {
($value:literal) => {
crate::options::config::style::utils::try_hex_to_colour($value.into()).expect("valid hex")
}; };
} }
pub(super) use color; pub(super) use color;
pub(super) use hex; pub(super) use hex;
pub(super) use hex_colour;

View File

@ -7,7 +7,7 @@ use super::color;
use crate::options::config::style::Styles; use crate::options::config::style::Styles;
impl Styles { impl Styles {
pub(crate) fn default_style() -> Self { pub(crate) fn default_palette() -> Self {
const FIRST_COLOUR: Color = Color::LightMagenta; const FIRST_COLOUR: Color = Color::LightMagenta;
const SECOND_COLOUR: Color = Color::LightYellow; const SECOND_COLOUR: Color = Color::LightYellow;
const THIRD_COLOUR: Color = Color::LightCyan; const THIRD_COLOUR: Color = Color::LightCyan;
@ -72,7 +72,7 @@ impl Styles {
} }
} }
pub fn default_light_mode() -> Self { pub fn default_light_palette() -> Self {
Self { Self {
ram_style: color!(Color::Blue), ram_style: color!(Color::Blue),
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -111,7 +111,15 @@ impl Styles {
graph_style: color!(Color::Black), graph_style: color!(Color::Black),
graph_legend_style: color!(Color::Black), graph_legend_style: color!(Color::Black),
disabled_text_style: color!(Color::Gray), disabled_text_style: color!(Color::Gray),
..Self::default_style() ..Self::default_palette()
} }
} }
} }
mod tests {
#[test]
fn default_palettes_valid() {
let _ = super::Styles::default_palette();
let _ = super::Styles::default_light_palette();
}
}

View File

@ -4,7 +4,7 @@ use tui::{
}; };
use super::{color, hex}; use super::{color, hex};
use crate::options::config::style::{Styles, utils::convert_hex_to_color}; use crate::options::config::style::{Styles, themes::hex_colour};
impl Styles { impl Styles {
pub(crate) fn gruvbox_palette() -> Self { pub(crate) fn gruvbox_palette() -> Self {
@ -56,7 +56,7 @@ impl Styles {
border_style: hex!("#ebdbb2"), border_style: hex!("#ebdbb2"),
highlighted_border_style: hex!("#fe8019"), highlighted_border_style: hex!("#fe8019"),
text_style: hex!("#ebdbb2"), text_style: hex!("#ebdbb2"),
selected_text_style: hex!("#1d2021").bg(convert_hex_to_color("#ebdbb2").unwrap()), selected_text_style: hex!("#1d2021").bg(hex_colour!("#ebdbb2")),
table_header_style: hex!("#83a598").add_modifier(Modifier::BOLD), table_header_style: hex!("#83a598").add_modifier(Modifier::BOLD),
widget_title_style: hex!("#ebdbb2"), widget_title_style: hex!("#ebdbb2"),
graph_style: hex!("#ebdbb2"), graph_style: hex!("#ebdbb2"),
@ -121,7 +121,7 @@ impl Styles {
border_style: hex!("#3c3836"), border_style: hex!("#3c3836"),
highlighted_border_style: hex!("#af3a03"), highlighted_border_style: hex!("#af3a03"),
text_style: hex!("#3c3836"), text_style: hex!("#3c3836"),
selected_text_style: hex!("#ebdbb2").bg(convert_hex_to_color("#3c3836").unwrap()), selected_text_style: hex!("#ebdbb2").bg(hex_colour!("#3c3836")),
table_header_style: hex!("#076678").add_modifier(Modifier::BOLD), table_header_style: hex!("#076678").add_modifier(Modifier::BOLD),
widget_title_style: hex!("#3c3836"), widget_title_style: hex!("#3c3836"),
graph_style: hex!("#3c3836"), graph_style: hex!("#3c3836"),
@ -137,3 +137,12 @@ impl Styles {
} }
} }
} }
#[cfg(test)]
mod tests {
#[test]
fn gruvbox_palettes_valid() {
let _ = super::Styles::gruvbox_palette();
let _ = super::Styles::gruvbox_light_palette();
}
}

View File

@ -4,7 +4,7 @@ use tui::{
}; };
use super::{color, hex}; use super::{color, hex};
use crate::options::config::style::{Styles, utils::convert_hex_to_color}; use crate::options::config::style::{Styles, themes::hex_colour};
impl Styles { impl Styles {
pub(crate) fn nord_palette() -> Self { pub(crate) fn nord_palette() -> Self {
@ -44,7 +44,7 @@ impl Styles {
border_style: hex!("#88c0d0"), border_style: hex!("#88c0d0"),
highlighted_border_style: hex!("#5e81ac"), highlighted_border_style: hex!("#5e81ac"),
text_style: hex!("#e5e9f0"), text_style: hex!("#e5e9f0"),
selected_text_style: hex!("#2e3440").bg(convert_hex_to_color("#88c0d0").unwrap()), selected_text_style: hex!("#2e3440").bg(hex_colour!("#88c0d0")),
table_header_style: hex!("#81a1c1").add_modifier(Modifier::BOLD), table_header_style: hex!("#81a1c1").add_modifier(Modifier::BOLD),
widget_title_style: hex!("#e5e9f0"), widget_title_style: hex!("#e5e9f0"),
graph_style: hex!("#e5e9f0"), graph_style: hex!("#e5e9f0"),
@ -97,7 +97,7 @@ impl Styles {
border_style: hex!("#2e3440"), border_style: hex!("#2e3440"),
highlighted_border_style: hex!("#5e81ac"), highlighted_border_style: hex!("#5e81ac"),
text_style: hex!("#2e3440"), text_style: hex!("#2e3440"),
selected_text_style: hex!("#f5f5f5").bg(convert_hex_to_color("#5e81ac").unwrap()), selected_text_style: hex!("#f5f5f5").bg(hex_colour!("#5e81ac")),
table_header_style: hex!("#5e81ac").add_modifier(Modifier::BOLD), table_header_style: hex!("#5e81ac").add_modifier(Modifier::BOLD),
widget_title_style: hex!("#2e3440"), widget_title_style: hex!("#2e3440"),
graph_style: hex!("#2e3440"), graph_style: hex!("#2e3440"),
@ -113,3 +113,12 @@ impl Styles {
} }
} }
} }
#[cfg(test)]
mod tests {
#[test]
fn nord_palettes_valid() {
let _ = super::Styles::nord_palette();
let _ = super::Styles::nord_light_palette();
}
}

View File

@ -3,7 +3,7 @@ use tui::style::Color;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
/// Convert a hex string to a colour. /// Convert a hex string to a colour.
pub(super) fn convert_hex_to_color(hex: &str) -> Result<Color, String> { pub(super) fn try_hex_to_colour(hex: &str) -> Result<Color, String> {
fn hex_component_to_int(hex: &str, first: &str, second: &str) -> Result<u8, String> { fn hex_component_to_int(hex: &str, first: &str, second: &str) -> Result<u8, String> {
u8::from_str_radix(&concat_string!(first, second), 16) u8::from_str_radix(&concat_string!(first, second), 16)
.map_err(|_| format!("'{hex}' is an invalid hex color, could not decode.")) .map_err(|_| format!("'{hex}' is an invalid hex color, could not decode."))
@ -42,7 +42,7 @@ pub(super) fn convert_hex_to_color(hex: &str) -> Result<Color, String> {
pub fn str_to_colour(input_val: &str) -> Result<Color, String> { pub fn str_to_colour(input_val: &str) -> Result<Color, String> {
if input_val.len() > 1 { if input_val.len() > 1 {
if input_val.starts_with('#') { if input_val.starts_with('#') {
convert_hex_to_color(input_val) try_hex_to_colour(input_val)
} else if input_val.contains(',') { } else if input_val.contains(',') {
convert_rgb_to_color(input_val) convert_rgb_to_color(input_val)
} else { } else {
@ -336,72 +336,66 @@ mod test {
fn valid_hex_colours() { fn valid_hex_colours() {
// Check hex with 6 characters. // Check hex with 6 characters.
assert_eq!( assert_eq!(
convert_hex_to_color("#ffffff").unwrap(), try_hex_to_colour("#ffffff").unwrap(),
Color::Rgb(255, 255, 255) Color::Rgb(255, 255, 255)
); );
assert_eq!(try_hex_to_colour("#000000").unwrap(), Color::Rgb(0, 0, 0));
try_hex_to_colour("#111111").unwrap();
try_hex_to_colour("#11ff11").unwrap();
try_hex_to_colour("#1f1f1f").unwrap();
assert_eq!( assert_eq!(
convert_hex_to_color("#000000").unwrap(), try_hex_to_colour("#123abc").unwrap(),
Color::Rgb(0, 0, 0)
);
convert_hex_to_color("#111111").unwrap();
convert_hex_to_color("#11ff11").unwrap();
convert_hex_to_color("#1f1f1f").unwrap();
assert_eq!(
convert_hex_to_color("#123abc").unwrap(),
Color::Rgb(18, 58, 188) Color::Rgb(18, 58, 188)
); );
// Check hex with 3 characters. // Check hex with 3 characters.
assert_eq!( assert_eq!(
convert_hex_to_color("#fff").unwrap(), try_hex_to_colour("#fff").unwrap(),
Color::Rgb(255, 255, 255) Color::Rgb(255, 255, 255)
); );
assert_eq!(convert_hex_to_color("#000").unwrap(), Color::Rgb(0, 0, 0)); assert_eq!(try_hex_to_colour("#000").unwrap(), Color::Rgb(0, 0, 0));
convert_hex_to_color("#111").unwrap(); try_hex_to_colour("#111").unwrap();
convert_hex_to_color("#1f1").unwrap(); try_hex_to_colour("#1f1").unwrap();
convert_hex_to_color("#f1f").unwrap(); try_hex_to_colour("#f1f").unwrap();
convert_hex_to_color("#ff1").unwrap(); try_hex_to_colour("#ff1").unwrap();
convert_hex_to_color("#1ab").unwrap(); try_hex_to_colour("#1ab").unwrap();
assert_eq!( assert_eq!(try_hex_to_colour("#1ab").unwrap(), Color::Rgb(17, 170, 187));
convert_hex_to_color("#1ab").unwrap(),
Color::Rgb(17, 170, 187)
);
} }
#[test] #[test]
fn invalid_hex_colours() { fn invalid_hex_colours() {
assert!(convert_hex_to_color("ffffff").is_err()); assert!(try_hex_to_colour("ffffff").is_err());
assert!(convert_hex_to_color("111111").is_err()); assert!(try_hex_to_colour("111111").is_err());
assert!(convert_hex_to_color("fff").is_err()); assert!(try_hex_to_colour("fff").is_err());
assert!(convert_hex_to_color("111").is_err()); assert!(try_hex_to_colour("111").is_err());
assert!(convert_hex_to_color("fffffff").is_err()); assert!(try_hex_to_colour("fffffff").is_err());
assert!(convert_hex_to_color("1234567").is_err()); assert!(try_hex_to_colour("1234567").is_err());
assert!(convert_hex_to_color("#fffffff").is_err()); assert!(try_hex_to_colour("#fffffff").is_err());
assert!(convert_hex_to_color("#1234567").is_err()); assert!(try_hex_to_colour("#1234567").is_err());
assert!(convert_hex_to_color("#ff").is_err()); assert!(try_hex_to_colour("#ff").is_err());
assert!(convert_hex_to_color("#12").is_err()); assert!(try_hex_to_colour("#12").is_err());
assert!(convert_hex_to_color("").is_err()); assert!(try_hex_to_colour("").is_err());
assert!(convert_hex_to_color("#pppppp").is_err()); assert!(try_hex_to_colour("#pppppp").is_err());
assert!(convert_hex_to_color("#00000p").is_err()); assert!(try_hex_to_colour("#00000p").is_err());
assert!(convert_hex_to_color("#ppp").is_err()); assert!(try_hex_to_colour("#ppp").is_err());
assert!(convert_hex_to_color("#一").is_err()); assert!(try_hex_to_colour("#一").is_err());
assert!(convert_hex_to_color("#一二").is_err()); assert!(try_hex_to_colour("#一二").is_err());
assert!(convert_hex_to_color("#一二三").is_err()); assert!(try_hex_to_colour("#一二三").is_err());
assert!(convert_hex_to_color("#一二三四").is_err()); assert!(try_hex_to_colour("#一二三四").is_err());
assert!(convert_hex_to_color("#f一f").is_err()); assert!(try_hex_to_colour("#f一f").is_err());
assert!(convert_hex_to_color("#ff一11").is_err()); assert!(try_hex_to_colour("#ff一11").is_err());
assert!(convert_hex_to_color("#🇨🇦").is_err()); assert!(try_hex_to_colour("#🇨🇦").is_err());
assert!(convert_hex_to_color("#🇨🇦🇨🇦").is_err()); assert!(try_hex_to_colour("#🇨🇦🇨🇦").is_err());
assert!(convert_hex_to_color("#🇨🇦🇨🇦🇨🇦").is_err()); assert!(try_hex_to_colour("#🇨🇦🇨🇦🇨🇦").is_err());
assert!(convert_hex_to_color("#🇨🇦🇨🇦🇨🇦🇨🇦").is_err()); assert!(try_hex_to_colour("#🇨🇦🇨🇦🇨🇦🇨🇦").is_err());
assert!(convert_hex_to_color("#हिन्दी").is_err()); assert!(try_hex_to_colour("#हिन्दी").is_err());
} }
#[test] #[test]

View File

@ -27,7 +27,7 @@ pub fn init_logger(
// one "[". See https://time-rs.github.io/book/api/format-description.html // one "[". See https://time-rs.github.io/book/api/format-description.html
"[[[year]-[month]-[day]][[[hour]:[minute]:[second][subsecond digits:9]]" "[[[year]-[month]-[day]][[[hour]:[minute]:[second][subsecond digits:9]]"
)) ))
.unwrap(), .expect("log formatting shouldn't fail"),
record.target(), record.target(),
record.level(), record.level(),
message message

View File

@ -641,7 +641,11 @@ impl ProcWidgetState {
stack.sort_unstable_by_key(|p| p.pid); stack.sort_unstable_by_key(|p| p.pid);
let column = self.table.columns.get(self.table.sort_index()).unwrap(); let column = self
.table
.columns
.get(self.table.sort_index())
.expect("columns should contain the current sort index");
sort_skip_pid_asc(column.inner(), &mut stack, self.table.order()); sort_skip_pid_asc(column.inner(), &mut stack, self.table.order());
let mut length_stack = vec![stack.len()]; let mut length_stack = vec![stack.len()];

View File

@ -1,5 +1,8 @@
//! Integration tests for bottom. //! Integration tests for bottom.
#![allow(clippy::unwrap_used)]
#![allow(missing_docs)]
mod util; mod util;
mod arg_tests; mod arg_tests;