diff --git a/build.rs b/build.rs index 006ab4b2..6c106720 100644 --- a/build.rs +++ b/build.rs @@ -98,8 +98,9 @@ fn nightly_version() { .args(["rev-parse", "--short=8", "HEAD"]) .output() { - // If we're not building in either, we do the lazy thing and fall back to - // manually grabbing info using git as a command. + // If we're not building in either, we do the lazy thing and + // fall back to manually grabbing info using git + // as a command. let hash = String::from_utf8(output.stdout).unwrap(); output_nightly_version(version, &hash); } diff --git a/src/app.rs b/src/app.rs index 2943a663..f0642fc5 100644 --- a/src/app.rs +++ b/src/app.rs @@ -154,10 +154,10 @@ impl App { pub fn update_data(&mut self) { let data_source = self.data_store.get_data(); - // FIXME: (points_rework_v1) maybe separate PR but would it make more sense to - // store references of data? Would it also make more sense to move the - // "data set" step to the draw step, and make it only set if force - // update is set here? + // FIXME: (points_rework_v1) maybe separate PR but would it make more + // sense to store references of data? Would it also make more + // sense to move the "data set" step to the draw step, and make + // it only set if force update is set here? for proc in self.states.proc_state.widget_states.values_mut() { if proc.force_update_data { proc.set_table_data(data_source); @@ -203,7 +203,8 @@ impl App { self.data_store.reset(); // Reset zoom. - // TODO: Make this suck less... should just make it so that calling reset fixes this all (including above too). + // TODO: Make this suck less... should just make it so that calling + // reset fixes this all (including above too). for widget_state in self.states.cpu_state.widget_states.values_mut() { widget_state.graph.state_mut().reset_zoom(); } @@ -299,7 +300,8 @@ impl App { } pub fn is_in_any_search(&self) -> bool { - // TODO: This is really hacky, but is fine until we do some smarter things like putting event catching at a per-widget/dialog state. + // TODO: This is really hacky, but is fine until we do some smarter + // things like putting event catching at a per-widget/dialog state. self.is_in_search_widget() || (self.help_dialog_state.is_help_searching()) } @@ -367,8 +369,8 @@ impl App { pws.is_sort_open = !pws.is_sort_open; pws.force_rerender = true; - // If the sort is now open, move left. Otherwise, if the proc sort was selected, - // force move right. + // If the sort is now open, move left. Otherwise, if the proc sort + // was selected, force move right. if pws.is_sort_open { pws.sort_table.set_position(pws.table.sort_index()); self.move_widget_selection(&WidgetDirection::Left); @@ -997,12 +999,10 @@ impl App { let use_simple_selection = { cfg_select! { - any(target_os = "linux", target_os = "macos", target_os = "freebsd") => { - !self.app_config_fields.is_advanced_kill - } - _ => { - true - } + any(target_os = "linux", target_os = "macos", target_os = "freebsd") => { + !self.app_config_fields.is_advanced_kill + } + _ => true, } }; @@ -1299,8 +1299,8 @@ impl App { // 1. Send a movement signal in `direction`. // 2. Check if this new widget we've landed on is hidden. If not, halt. // 3. If it hidden, loop and either send: - // - A signal equal to the current direction, if it is opposite of the - // reflection. + // - A signal equal to the current direction, if it is opposite of + // the reflection. // - Reflection direction. if !self.ignore_normal_keybinds() && !self.is_expanded { @@ -1359,8 +1359,10 @@ impl App { BottomWidgetType::BasicTables => { match &direction { WidgetDirection::Up => { - // Note this case would fail if it moved up into a hidden - // widget, but it's for basic so whatever, it's all hard-coded + // Note this case would fail if it moved up into + // a hidden + // widget, but it's for basic so whatever, it's + // all hard-coded // right now anyways... if let Some(next_new_widget_id) = new_widget.up_neighbour && let Some(next_new_widget) = @@ -1370,12 +1372,15 @@ impl App { } } WidgetDirection::Down => { - // Assuming we're in basic mode (BasicTables), then - // we want to move DOWN to the currently shown widget. + // Assuming we're in basic mode (BasicTables), + // then + // we want to move DOWN to the currently shown + // widget. if let Some(basic_table_widget_state) = &mut self.states.basic_table_widget_state { - // We also want to move towards Proc if we had set it to + // We also want to move towards Proc if we + // had set it to // ProcSort. if let BottomWidgetType::ProcSort = basic_table_widget_state.currently_displayed_widget_type @@ -1399,7 +1404,8 @@ impl App { // It may be hidden... if let Some((parent_direction, offset)) = &new_widget.parent_reflector { if direction.is_opposite(parent_direction) { - // Keep going in the current direction if hidden... + // Keep going in the current direction if + // hidden... // unless we hit a wall of sorts. let option_next_neighbour_id = match &direction { WidgetDirection::Left => new_widget.left_neighbour, @@ -2048,19 +2054,19 @@ impl App { /// Moves the mouse to the widget that was clicked on, then propagates the /// click down to be handled by the widget specifically. pub fn on_left_mouse_up(&mut self, x: u16, y: u16) { - // Pretty dead simple - iterate through the widget map and go to the widget - // where the click is within. + // Pretty dead simple - iterate through the widget map and go to the + // widget where the click is within. // TODO: [REFACTOR] might want to refactor this, it's really ugly. - // TODO: [REFACTOR] Might wanna refactor ALL state things in general, currently - // everything is grouped up as an app state. We should separate stuff - // like event state and gui state and etc. + // TODO: [REFACTOR] Might wanna refactor ALL state things in general, + // currently everything is grouped up as an app state. We + // should separate stuff like event state and gui state and etc. - // TODO: [MOUSE] double click functionality...? We would do this above all - // other actions and SC if needed. + // TODO: [MOUSE] double click functionality...? We would do this above + // all other actions and SC if needed. - // Short circuit if we're in basic table... we might have to handle the basic - // table arrow case here... + // Short circuit if we're in basic table... we might have to handle the + // basic table arrow case here... if let Some(bt) = &mut self.states.basic_table_widget_state && let ( @@ -2106,7 +2112,8 @@ impl App { } } self.move_widget_selection(&WidgetDirection::Right); - // Bit extra logic to ensure you always land on a proc widget, not the sort + // Bit extra logic to ensure you always land on a proc widget, + // not the sort if let BottomWidgetType::ProcSort = &self.current_widget.widget_type { self.move_widget_selection(&WidgetDirection::Right); } @@ -2114,8 +2121,8 @@ impl App { } } - // Second short circuit --- are we in the dd dialog state? If so, only check - // yes/no/signals and bail after. + // Second short circuit --- are we in the dd dialog state? If so, only + // check yes/no/signals and bail after. if self.process_kill_dialog.is_open() && self.process_kill_dialog.on_click(x, y) { return; } @@ -2163,8 +2170,8 @@ impl App { ) { let border_offset = u16::from(self.is_drawing_border()); - // This check ensures the click isn't actually just clicking on the bottom - // border. + // This check ensures the click isn't actually just clicking on the + // bottom border. if y < (brc_y - border_offset) { match &self.current_widget.widget_type { BottomWidgetType::Proc @@ -2196,9 +2203,11 @@ impl App { self.change_process_position(change); - // If in tree mode, also check to see if this click is + // If in tree mode, also check to see if + // this click is // on - // the same entry as the already selected one - if it + // the same entry as the already + // selected one - if it // is, // then we minimize. if is_tree_mode && change == 0 { @@ -2207,7 +2216,8 @@ impl App { } } BottomWidgetType::ProcSort => { - // TODO: [Feature] This could sort if you double click! + // TODO: [Feature] This could sort if you + // double click! if let Some(proc_widget_state) = self .states .proc_state @@ -2262,7 +2272,8 @@ impl App { _ => {} } } else { - // We might have clicked on a header! Check if we only exceeded the + // We might have clicked on a header! Check if we + // only exceeded the // table + border offset, and it's implied // we exceeded the gap offset. if clicked_entry == border_offset { @@ -2317,7 +2328,8 @@ impl App { let num_batteries = self.data_store.get_data().battery_harvest.len(); if itx >= num_batteries { - // range check to keep within current data + // range check to keep within current + // data battery_widget_state.currently_selected_battery_index = num_batteries - 1; } else { diff --git a/src/app/data/process.rs b/src/app/data/process.rs index 980ba200..9c25eb2a 100644 --- a/src/app/data/process.rs +++ b/src/app/data/process.rs @@ -43,7 +43,8 @@ impl ProcessData { // We collect all processes that either: // - Do not have a parent PID (that is, they are orphan processes) - // - Have a parent PID but we don't have the parent (we promote them as orphans) + // - Have a parent PID but we don't have the parent (we promote them as + // orphans) self.orphan_pids = self .process_harvest .iter() diff --git a/src/app/data/store.rs b/src/app/data/store.rs index c1903ea9..89e21ee4 100644 --- a/src/app/data/store.rs +++ b/src/app/data/store.rs @@ -23,7 +23,8 @@ use crate::{ widgets::{DiskWidgetData, TempWidgetData}, }; -/// Because otherwise you can't do lookups for something like `(String, String)` as a key. +/// Because otherwise you can't do lookups for something like `(String, String)` +/// as a key. trait PairKey { fn pair(&self) -> (&str, &str); } @@ -138,8 +139,8 @@ impl InnerData { ) { let harvested_time = data.collection_time; - // We must adjust all the network values to their selected type (defaults to - // bits). + // We must adjust all the network values to their selected type + // (defaults to bits). if matches!(settings.network_unit_type, DataUnit::Byte) && let Some(network) = &mut data.network { @@ -334,7 +335,8 @@ impl InnerData { io_read_rate_bytes = Some(0); io_write_rate_bytes = Some(0); - // TODO: We probably want to also add some cleanup after a while if unused. + // TODO: We probably want to also add some cleanup after a + // while if unused. self.prev_io.insert( (disk.mount_point.clone(), checked_name.to_string()), (io_device.read_bytes, io_device.write_bytes), diff --git a/src/app/data/time_series.rs b/src/app/data/time_series.rs index 4a3828cf..23826194 100644 --- a/src/app/data/time_series.rs +++ b/src/app/data/time_series.rs @@ -291,13 +291,13 @@ impl TimeSeriesData { .time .partition_point(|then| now.duration_since(*then) > max_age); - // Partition point returns the first index that does not match the predicate, so - // minus one. + // Partition point returns the first index that does not match the + // predicate, so minus one. if partition_point > 0 { partition_point - 1 } else { - // If the partition point was 0, then it means all values are too new to be - // pruned. + // If the partition point was 0, then it means all values are + // too new to be pruned. // crate::info!("Skipping prune."); return; } @@ -330,7 +330,8 @@ impl TimeSeriesData { self.gpu_mem.retain(|_, gpu| { let _ = gpu.prune(end); - // Remove the entry if it is empty. We can always add it again later. + // Remove the entry if it is empty. We can always add it again + // later. if gpu.no_elements() { false } else { @@ -343,7 +344,8 @@ impl TimeSeriesData { self.temperature.retain(|_, data| { let _ = data.prune(end); - // Remove the entry if it is empty. We can always add it again later. + // Remove the entry if it is empty. We can always add it again + // later. if data.no_elements() { false } else { diff --git a/src/app/filter.rs b/src/app/filter.rs index 9318823e..b41a6c8b 100644 --- a/src/app/filter.rs +++ b/src/app/filter.rs @@ -27,9 +27,9 @@ impl Filter { #[inline] pub(crate) fn should_keep(&self, entry: &str) -> bool { if self.has_match(entry) { - // If a match is found, then if we wanted to ignore if we match, return false. - // If we want to keep if we match, return true. Thus, return the - // inverse of `is_list_ignored`. + // If a match is found, then if we wanted to ignore if we match, + // return false. If we want to keep if we match, return + // true. Thus, return the inverse of `is_list_ignored`. !self.is_list_ignored } else { self.is_list_ignored diff --git a/src/app/layout_manager.rs b/src/app/layout_manager.rs index 17c625d3..119d207b 100644 --- a/src/app/layout_manager.rs +++ b/src/app/layout_manager.rs @@ -175,7 +175,8 @@ impl BottomLayout { if let Some(current_row) = layout_mapping .get(&(row_height_percentage_start, row_height_percentage_end)) { - // First check for within the same col_row for left and right + // First check for within the same col_row for left + // and right if let Some(current_col) = current_row .1 .get(&(col_width_percentage_start, col_width_percentage_end)) @@ -316,7 +317,8 @@ impl BottomLayout { ) .next_back() { - // Now check each widget_width and pick the best + // Now check each widget_width and pick the + // best for candidate_widget in &(to_up.1).1 { let mut current_best_distance = 0; let mut current_best_widget_id = widget.widget_id; diff --git a/src/canvas.rs b/src/canvas.rs index c0474394..b097f176 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -111,8 +111,8 @@ impl Painter { self.previous_width = terminal_width; } - // TODO: We should probably remove this or make it done elsewhere, not the - // responsibility of the app. + // TODO: We should probably remove this or make it done elsewhere, + // not the responsibility of the app. if app_state.should_get_widget_bounds() { // If we're force drawing, reset ALL mouse boundaries. for widget in app_state.widget_map.values_mut() { @@ -176,11 +176,13 @@ impl Painter { .constraints([Constraint::Percentage(100)]) .areas(vertical_dialog_chunk) } else { - // We calculate this so that the margins never have to split an odd number. + // We calculate this so that the margins never have to split + // an odd number. let len = if (dialog_width.saturating_sub(MAX_TEXT_LENGTH)) % 2 == 0 { MAX_TEXT_LENGTH } else { - // It can only be 1 if the difference is greater than 1, so this is fine. + // It can only be 1 if the difference is greater than 1, + // so this is fine. MAX_TEXT_LENGTH + 1 }; @@ -197,8 +199,9 @@ impl Painter { f.buffer_mut() .set_style(area, self.styles.general_widget_style); - // FIXME: For width, just limit to a max size or full width. For height, not - // sure. Maybe pass max and let child handle? + // FIXME: For width, just limit to a max size or full width. For + // height, not sure. Maybe pass max and let + // child handle? let horizontal_padding = if terminal_width < 100 { 0 } else { 5 }; let vertical_padding = if terminal_height < 100 { 0 } else { 5 }; @@ -300,8 +303,8 @@ impl Painter { let data = app_state.data_store.get_data(); let actual_cpu_data_len = data.cpu_harvest.len(); - // This fixes #397, apparently if the height is 1, it can't render the CPU - // bars... + // This fixes #397, apparently if the height is 1, it can't + // render the CPU bars... let cpu_height = { let c = (actual_cpu_data_len / 4) as u16 + u16::from(!actual_cpu_data_len.is_multiple_of(4)) @@ -425,9 +428,10 @@ impl Painter { self.draw_frozen_indicator(f, frozen_draw_loc); } - // A two-pass algorithm - get layouts using constraints (first pass), - // then pass each layout to the corresponding widget (second pass). - // Note that layouts are already cached in ratatui, so we don't need + // A two-pass algorithm - get layouts using constraints (first + // pass), then pass each layout to the + // corresponding widget (second pass). Note that + // layouts are already cached in ratatui, so we don't need // to do it manually! let base = Layout::vertical(self.layout.rows.iter().map(|r| r.constraint)) .split(terminal_size); @@ -457,8 +461,8 @@ impl Painter { } })?; - // We also move it back to the origin to try rand avoid wasting CPU cycles for things like kitty's - // `cursor_trail` calculations. + // We also move it back to the origin to try rand avoid wasting CPU + // cycles for things like kitty's `cursor_trail` calculations. let backend = terminal.backend_mut(); backend.set_cursor_position(Position::ORIGIN)?; backend.flush()?; diff --git a/src/canvas/components/data_table/column.rs b/src/canvas/components/data_table/column.rs index 07f24b73..ae6dc3c1 100644 --- a/src/canvas/components/data_table/column.rs +++ b/src/canvas/components/data_table/column.rs @@ -222,8 +222,9 @@ where } else { total_width_left = total_width_left.saturating_sub(new_width + COLUMN_SPACING); - // SAFETY: This is safe as we call `stop_allocating_space` which checks that - // the value pushed is greater than zero. + // SAFETY: This is safe as we call `stop_allocating_space` which + // checks that the value pushed is greater than + // zero. unsafe { calculated_widths.push(NonZeroU16::new_unchecked(new_width)); } @@ -276,8 +277,9 @@ mod test { } } - /// Ensure that the [`DataTableColumn`] implementation for [`Column`] calls the right method. - /// Yes, this is a somewhat meaningless test but it may catch a regression if this happens again in the future + /// Ensure that the [`DataTableColumn`] implementation for [`Column`] calls + /// the right method. Yes, this is a somewhat meaningless test but it + /// may catch a regression if this happens again in the future /// during a refactor. /// /// See for details of the issue. diff --git a/src/canvas/components/data_table/draw.rs b/src/canvas/components/data_table/draw.rs index d921c781..758f838f 100644 --- a/src/canvas/components/data_table/draw.rs +++ b/src/canvas/components/data_table/draw.rs @@ -209,7 +209,8 @@ where if !self.data.is_empty() || !self.first_draw { if self.first_draw { - // TODO: Doing it this way is fine, but it could be done better (e.g. showing + // TODO: Doing it this way is fine, but it could be done + // better (e.g. showing // custom no results/entries message) self.first_draw = false; if let Some(first_index) = self.first_index { diff --git a/src/canvas/components/data_table/sortable.rs b/src/canvas/components/data_table/sortable.rs index 99d522d6..75b20d7b 100644 --- a/src/canvas/components/data_table/sortable.rs +++ b/src/canvas/components/data_table/sortable.rs @@ -124,8 +124,9 @@ impl SortType for Sortable { SortOrder::Ascending => UP_ARROW, SortOrder::Descending => DOWN_ARROW, }; - // TODO: I think I can get away with removing the truncate_to_text call - // since I almost always bind to at least the header + // TODO: I think I can get away with removing the + // truncate_to_text call since I + // almost always bind to at least the header // size... TODO: Or should we instead truncate but // ALWAYS leave the arrow at the end? truncate_to_text(&concat_string!(c.header(), arrow), width.get()) diff --git a/src/canvas/components/data_table/state.rs b/src/canvas/components/data_table/state.rs index 8308b0c0..9a64c002 100644 --- a/src/canvas/components/data_table/state.rs +++ b/src/canvas/components/data_table/state.rs @@ -60,22 +60,26 @@ impl DataTableState { self.display_start_index = match scroll_direction { ScrollDirection::Down => { if current_scroll_position < start_index + num_rows { - // If, using the current scroll position, we can see the element - // (so within that and + num_rows) just reuse the current previously + // If, using the current scroll position, we can see the + // element (so within that and + + // num_rows) just reuse the current previously // scrolled position. start_index } else if current_scroll_position >= num_rows { - // If the current position past the last element visible in the list, - // then skip until we can see that element. + // If the current position past the last element visible in + // the list, then skip until we can see + // that element. current_scroll_position - num_rows + 1 } else { - // Else, if it is not past the last element visible, do not omit anything. + // Else, if it is not past the last element visible, do not + // omit anything. 0 } } ScrollDirection::Up => { if current_scroll_position <= start_index { - // If it's past the first element, then show from that element downwards + // If it's past the first element, then show from that + // element downwards current_scroll_position } else if current_scroll_position >= start_index + num_rows { current_scroll_position - num_rows + 1 diff --git a/src/canvas/components/search_input.rs b/src/canvas/components/search_input.rs index 92c6d08e..7ea06fe5 100644 --- a/src/canvas/components/search_input.rs +++ b/src/canvas/components/search_input.rs @@ -22,7 +22,8 @@ pub struct SearchInputStyles { pub hint_style: Style, } -/// Build a query span from a [`InputFieldState`]. `available_width` is the terminal column width. +/// Build a query span from a [`InputFieldState`]. `available_width` is the +/// terminal column width. pub fn build_query_spans( input_field_state: &InputFieldState, available_width: usize, is_on_widget: bool, cursor_style: Style, text_style: Style, @@ -30,8 +31,9 @@ pub fn build_query_spans( let query = input_field_state.current_query(); if !is_on_widget { - // This is easier - we just need to get a range of graphemes, rather than - // dealing with possibly inserting a cursor (as none is shown!) + // This is easier - we just need to get a range of graphemes, rather + // than dealing with possibly inserting a cursor (as none is + // shown!) return vec![Span::styled(query.to_string(), text_style)]; } diff --git a/src/canvas/components/time_series/base.rs b/src/canvas/components/time_series/base.rs index 3f7a4770..aa35b3f9 100644 --- a/src/canvas/components/time_series/base.rs +++ b/src/canvas/components/time_series/base.rs @@ -109,7 +109,8 @@ pub struct TimeGraph<'a> { impl TimeGraph<'_> { /// Generates the [`Axis`] for the x-axis. fn generate_x_axis(&self) -> Axis<'_> { - // Due to how we display things, we need to adjust the time bound values. + // Due to how we display things, we need to adjust the time bound + // values. let adjusted_x_bounds = AxisBound::Min(self.x_min); if self.hide_x_labels { @@ -155,8 +156,8 @@ impl TimeGraph<'_> { pub fn draw>( &self, f: &mut Frame<'_>, draw_loc: Rect, graph_data: Vec>, ) { - // TODO: (points_rework_v1) can we reduce allocations in the underlying graph by - // saving some sort of state? + // TODO: (points_rework_v1) can we reduce allocations in the underlying + // graph by saving some sort of state? let x_axis = self.generate_x_axis(); let y_axis = self.generate_y_axis(); diff --git a/src/canvas/components/time_series/vendored.rs b/src/canvas/components/time_series/vendored.rs index 08121d71..3da19eed 100644 --- a/src/canvas/components/time_series/vendored.rs +++ b/src/canvas/components/time_series/vendored.rs @@ -400,8 +400,8 @@ pub(crate) enum ChartScaling { impl ChartScaling { /// Scale a value. pub(super) fn scale(&self, value: f64) -> f64 { - // Remember to do saturating log checks as otherwise 0.0 becomes inf, and you - // get gaps! + // Remember to do saturating log checks as otherwise 0.0 becomes inf, + // and you get gaps! match self { ChartScaling::Linear => value, ChartScaling::Log10 => saturating_log10(value), @@ -672,8 +672,9 @@ impl<'a, F: Copy + Default + Into> TimeChart<'a, F> { let first_label_width = first_x_label.content.width() as u16; let width_left_of_y_axis = match self.x_axis.labels_alignment { Alignment::Left => { - // The last character of the label should be below the Y-Axis when it exists, - // not on its left + // The last character of the label should be below the + // Y-Axis when it exists, not on its + // left let y_axis_offset = u16::from(has_y_axis); first_label_width.saturating_sub(y_axis_offset) } @@ -682,8 +683,8 @@ impl<'a, F: Copy + Default + Into> TimeChart<'a, F> { }; max_width = max(max_width, width_left_of_y_axis); } - // labels of y axis and first label of x axis can take at most 1/3rd of the - // total width + // labels of y axis and first label of x axis can take at most 1/3rd of + // the total width max_width.min(area.width / 3) } @@ -721,8 +722,8 @@ impl<'a, F: Copy + Default + Into> TimeChart<'a, F> { Self::render_label(buf, first_label, label_area, label_alignment); 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 - // intermediate labels + // We add 1 to x (and width-1 below) to leave at least one space + // before each intermediate labels let x = graph_area.left() + (i + 1) as u16 * width_between_ticks + 1; let label_area = Rect::new(x, y, width_between_ticks.saturating_sub(1), 1); @@ -731,7 +732,8 @@ impl<'a, F: Copy + Default + Into> TimeChart<'a, F> { let x = graph_area.right() - width_between_ticks; 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, last_label, label_area, Alignment::Right); } @@ -803,9 +805,9 @@ impl> Widget for TimeChart<'_, F> { return; } - // Sample the style of the entire widget. This sample will be used to reset the - // style of the cells that are part of the components put on top of the - // graph area (i.e legend and axis names). + // Sample the style of the entire widget. This sample will be used to + // reset the style of the cells that are part of the components + // put on top of the graph area (i.e legend and axis names). let Some(original_style) = buf.cell((area.left(), area.top())).map(|cell| cell.style()) else { return; @@ -1490,8 +1492,8 @@ mod tests { #[test] fn legend_truncates_entries_by_height() { - // 5 datasets but only room for 3 entries in the legend (height=5, so 5-2=3 - // entries). + // 5 datasets but only room for 3 entries in the legend (height=5, so + // 5-2=3 entries). let datasets: Vec<_> = (0..5) .map(|i| Dataset::default().name(format!("D{i}"))) .collect(); @@ -1591,8 +1593,8 @@ mod tests { assert!(layout.legend_area.is_some()); let legend = layout.legend_area.unwrap(); - // Width should be based on "AB"/"CD" (2 chars) + 2 borders = 4, not the long - // name. + // Width should be based on "AB"/"CD" (2 chars) + 2 borders = 4, not the + // long name. assert_eq!(legend.width, 4); } } diff --git a/src/canvas/components/time_series/vendored/grid.rs b/src/canvas/components/time_series/vendored/grid.rs index 9d0815e0..d550cbc8 100644 --- a/src/canvas/components/time_series/vendored/grid.rs +++ b/src/canvas/components/time_series/vendored/grid.rs @@ -138,22 +138,24 @@ impl Grid for PatternGrid { // The ratatui/tui-rs implementation; this gives a more merged // look, but it also makes it a bit harder to read in some cases. // - // using get_mut here because we are indexing the vector with usize values - // and we want to make sure we don't panic if the index is out of bounds - // if let Some(cell) = self.cells.get_mut(index) { - // cell.pattern |= 1u8 << ((x % W) + W * (y % H)); - // cell.color = Some(color); + // using get_mut here because we are indexing the vector with usize + // values and we want to make sure we don't panic if the index + // is out of bounds if let Some(cell) = + // self.cells.get_mut(index) { cell.pattern |= 1u8 << ((x % + // W) + W * (y % H)); cell.color = Some(color); // } // Custom implementation do distinguish between lines better. if let Some(cell) = self.cells.get_mut(index) { if let Some(curr_color) = &mut cell.color { if *curr_color != color { - // If the colour doesn't match, then reset the colour and cell. + // If the colour doesn't match, then reset the colour and + // cell. *curr_color = color; cell.pattern = 1u8 << ((x % W) + W * (y % H)); } else { - // If it does match, then combine it with the previous underlying cell. + // If it does match, then combine it with the previous + // underlying cell. cell.pattern |= 1u8 << ((x % W) + W * (y % H)); } } else { @@ -306,8 +308,9 @@ impl Grid for CharGrid { fn paint(&mut self, x: usize, y: usize, color: Color) { let index = y.saturating_mul(self.width as usize).saturating_add(x); - // using get_mut here because we are indexing the vector with usize values - // and we want to make sure we don't panic if the index is out of bounds + // using get_mut here because we are indexing the vector with usize + // values and we want to make sure we don't panic if the index + // is out of bounds if let Some(c) = self.cells.get_mut(index) { *c = Some(color); } @@ -380,39 +383,41 @@ impl Grid for HalfBlockGrid { } fn save(&self) -> Layer { - // Given that we store the pixels in a grid, and that we want to use 2 pixels - // arranged vertically to form a single terminal cell, which can be - // either empty, upper half block, lower half block or full block, we - // need examine the pixels in vertical pairs to decide what character to - // print in each cell. So these are the 4 states we use to represent each - // cell: + // Given that we store the pixels in a grid, and that we want to use 2 + // pixels arranged vertically to form a single terminal cell, + // which can be either empty, upper half block, lower half block + // or full block, we need examine the pixels in vertical pairs + // to decide what character to print in each cell. So these are + // the 4 states we use to represent each cell: // // 1. upper: reset, lower: reset => ' ' fg: reset / bg: reset // 2. upper: reset, lower: color => '▄' fg: lower color / bg: reset // 3. upper: color, lower: reset => '▀' fg: upper color / bg: reset - // 4. upper: color, lower: color => '▀' fg: upper color / bg: lower color + // 4. upper: color, lower: color => '▀' fg: upper color / bg: lower + // color // - // Note that because the foreground reset color (i.e. default foreground color) - // is usually not the same as the background reset color (i.e. default - // background color), we need to swap around the colors for that state - // (2 reset/color). + // Note that because the foreground reset color (i.e. default foreground + // color) is usually not the same as the background reset color + // (i.e. default background color), we need to swap around the + // colors for that state (2 reset/color). // - // When the upper and lower colors are the same, we could continue to use an - // upper half block, but we choose to use a full block instead. This - // allows us to write unit tests that treat the cell as a single - // character instead of two half block characters. + // When the upper and lower colors are the same, we could continue to + // use an upper half block, but we choose to use a full block + // instead. This allows us to write unit tests that treat the + // cell as a single character instead of two half block + // characters. - // first we join each adjacent row together to get an iterator that contains - // vertical pairs of pixels, with the lower row being the first element - // in the pair + // first we join each adjacent row together to get an iterator that + // contains vertical pairs of pixels, with the lower row being + // the first element in the pair let vertical_color_pairs = self .pixels .iter() .tuples() .flat_map(|(upper_row, lower_row)| zip(upper_row, lower_row)); - // Then we determine the character to print for each pair, along with the color - // of the foreground and background. + // Then we determine the character to print for each pair, along with + // the color of the foreground and background. let contents = vertical_color_pairs .map(|(upper, lower)| { let (symbol, fg, bg) = match (upper, lower) { diff --git a/src/canvas/components/time_series/vendored/points.rs b/src/canvas/components/time_series/vendored/points.rs index ee99bf1a..de9c899e 100644 --- a/src/canvas/components/time_series/vendored/points.rs +++ b/src/canvas/components/time_series/vendored/points.rs @@ -16,17 +16,19 @@ impl> TimeChart<'_, F> { // - Last point wins for what gets drawn. // - We set _all_ points for all datasets before actually rendering. // - // By doing this, it's a bit more efficient from my experience than looping - // over each dataset and rendering a new layer each time. + // By doing this, it's a bit more efficient from my experience than + // looping over each dataset and rendering a new layer each + // time. // // See https://github.com/ClementTsang/bottom/pull/918 and // https://github.com/ClementTsang/bottom/pull/937 for the original motivation. // - // We also additionally do some interpolation logic because we may get caught - // missing some points when drawing, but we generally want to avoid - // jarring gaps between the edges when there's a point that is off - // screen and so a line isn't drawn (right edge generally won't have this issue - // issue but it can happen in some cases). + // We also additionally do some interpolation logic because we may get + // caught missing some points when drawing, but we generally + // want to avoid jarring gaps between the edges when there's a + // point that is off screen and so a line isn't drawn (right + // edge generally won't have this issue issue but it can happen + // in some cases). for dataset in &self.datasets { let Data::Some { times, values } = dataset.data else { @@ -40,24 +42,27 @@ impl> TimeChart<'_, F> { let color = dataset.style.fg.unwrap_or(Color::Reset); let left_edge = self.x_axis.bounds.get_bounds()[0]; - // TODO: (points_rework_v1) Can we instead modify the range so it's based on the - // epoch rather than having to convert? TODO: (points_rework_v1) Is - // this efficient? Or should I prune using take_while first? + // TODO: (points_rework_v1) Can we instead modify the range so it's + // based on the epoch rather than having to convert? + // TODO: (points_rework_v1) Is this efficient? Or should + // I prune using take_while first? for (curr, next) in values .iter_along_base(times) .rev() .map(|(&time, &val)| { let from_start = -(current_time.duration_since(time).as_millis() as f64); - // XXX: Should this be generic over dataset.graph_type instead? That would allow - // us to move transformations behind a type - however, that + // XXX: Should this be generic over dataset.graph_type + // instead? That would allow us to move + // transformations behind a type - however, that // also means that there's some complexity added. (from_start, self.scaling.scale(val.into())) }) .tuple_windows() { if curr.0 == left_edge { - // The current point hits the left edge. Draw just the current point and halt. + // The current point hits the left edge. Draw just the + // current point and halt. ctx.draw(&Points { coords: &[curr], color, @@ -65,8 +70,8 @@ impl> TimeChart<'_, F> { break; } else if next.0 < left_edge { - // The next point goes past the left edge. Interpolate a point + the line and - // halt. + // The next point goes past the left edge. Interpolate a + // point + the line and halt. let interpolated = interpolate_point(&next, &curr, left_edge); ctx.draw(&CanvasLine { diff --git a/src/canvas/components/widget_carousel.rs b/src/canvas/components/widget_carousel.rs index fbae3b62..0362991c 100644 --- a/src/canvas/components/widget_carousel.rs +++ b/src/canvas/components/widget_carousel.rs @@ -115,8 +115,8 @@ impl Painter { .horizontal_margin(1) .split(draw_loc); - // Done like this for now since it's easier to just manually paint instead of - // dealing with blocks. + // Done like this for now since it's easier to just manually paint + // instead of dealing with blocks. f.buffer_mut() .set_style(draw_loc, self.styles.general_widget_style); @@ -133,18 +133,19 @@ impl Painter { if app_state.should_get_widget_bounds() { // Some explanations for future readers: - // - The "height" as of writing of this entire widget is 2. If it's 1, it - // occasionally doesn't draw. - // - As such, the buttons are only on the lower part of this 2-high widget. - // - So, we want to only check at one location, the `draw_loc.y + 1`, and that's - // it. + // - The "height" as of writing of this entire widget is 2. If + // it's 1, it occasionally doesn't draw. + // - As such, the buttons are only on the lower part of this + // 2-high widget. + // - So, we want to only check at one location, the `draw_loc.y + // + 1`, and that's it. // - But why is it "+2" then? Well, it's because I have a REALLY ugly hack // for mouse button checking, since most button checks are of the form `(draw_loc.y + draw_loc.height)`, // and the same for the x and width. Unfortunately, if you check using >= and <=, the outer bound is // actually too large - so, we assume all of them are one too big and check via < (see // https://github.com/ClementTsang/bottom/pull/459 for details). - // - So in other words, to make it simple, we keep this to a standard and - // overshoot by one here. + // - So in other words, to make it simple, we keep this to a + // standard and overshoot by one here. if let Some(basic_table) = &mut app_state.states.basic_table_widget_state { basic_table.left_tlc = Some((margined_draw_loc[0].x, margined_draw_loc[0].y + 1)); diff --git a/src/canvas/dialogs/help_dialog.rs b/src/canvas/dialogs/help_dialog.rs index baa61765..123e24c1 100644 --- a/src/canvas/dialogs/help_dialog.rs +++ b/src/canvas/dialogs/help_dialog.rs @@ -96,7 +96,8 @@ impl Painter { if !matched_body.is_empty() || header_matches { if let Some(header) = header_str { - // Don't insert the space if there's nothing above anyway. + // Don't insert the space if there's nothing above + // anyway. if !lines.is_empty() { lines.push(Line::from(Span::default())); } @@ -166,14 +167,16 @@ impl Painter { }; if app_state.should_get_widget_bounds() { - // We must also recalculate how many lines are wrapping to properly get - // scrolling to work on small terminal sizes... oh joy. + // We must also recalculate how many lines are wrapping to properly + // get scrolling to work on small terminal sizes... oh + // joy. let inner = block.inner(content_area); app_state.help_dialog_state.height = inner.height; - // The overflow buffer is used to account for lines that wrap onto multiple lines, - // so we can properly calculate the max scroll index later. + // The overflow buffer is used to account for lines that wrap onto + // multiple lines, so we can properly calculate the max + // scroll index later. let mut overflow_buffer = 0; let paragraph_width: usize = max(inner.width, 1).into(); let mut prev_section_len = 0; @@ -422,8 +425,8 @@ mod tests { check_spans(&lines[0], ["Hi 你好!", "🇨🇦", ""]); } - /// Shows that we only match the first occurrence in the line. This is expected behaviour as we're passing - /// in separate strings. + /// Shows that we only match the first occurrence in the line. This is + /// expected behaviour as we're passing in separate strings. #[test] fn test_unicode_3() { let mut lines = Vec::new(); diff --git a/src/canvas/dialogs/process_kill_dialog.rs b/src/canvas/dialogs/process_kill_dialog.rs index c63811d2..45217dd8 100644 --- a/src/canvas/dialogs/process_kill_dialog.rs +++ b/src/canvas/dialogs/process_kill_dialog.rs @@ -269,7 +269,11 @@ impl ProcessKillDialog { for pid in pids { if let Err(err) = process_killer::kill_process_given_pid(pid) { - self.state = ProcessKillDialogState::Error { process_name, pid: Some(pid), err: err.to_string() }; + self.state = ProcessKillDialogState::Error { + process_name, + pid: Some(pid), + err: err.to_string(), + }; break; } } @@ -279,15 +283,26 @@ impl ProcessKillDialog { for pid in pids { // Send a SIGTERM by default. - if let Err(err) = process_killer::kill_process_given_pid(pid, DEFAULT_KILL_SIGNAL) { - self.state = ProcessKillDialogState::Error { process_name, pid: Some(pid), err: err.to_string() }; + if let Err(err) = process_killer::kill_process_given_pid( + pid, + DEFAULT_KILL_SIGNAL, + ) { + self.state = ProcessKillDialogState::Error { + process_name, + pid: Some(pid), + err: err.to_string(), + }; break; } } } _ => { - self.state = ProcessKillDialogState::Error { process_name, pid: None, err: "Killing processes is not supported on this platform.".into() }; - + self.state = ProcessKillDialogState::Error { + process_name, + pid: None, + err: "Killing processes is not supported on this platform." + .into(), + }; } } } @@ -337,7 +352,8 @@ impl ProcessKillDialog { }; if new >= SIGNAL_TEXT.len() { - // If the new value is too large, then just assume we instead + // If the new value is too large, then just + // assume we instead // want the value itself. state.select(Some(value as usize)); self.last_char = Some((c, Instant::now())); @@ -582,11 +598,16 @@ impl ProcessKillDialog { } else { cfg_select! { any(target_os = "linux", target_os = "macos", target_os = "freebsd") => { - ButtonState::Signals { state: ListState::default().with_selected(Some(DEFAULT_KILL_SIGNAL)), last_button_draw_area: Rect::default() } - } - _ => { - ButtonState::Simple { yes: false, last_yes_button_area: Rect::default(), last_no_button_area: Rect::default()} + ButtonState::Signals { + state: ListState::default().with_selected(Some(DEFAULT_KILL_SIGNAL)), + last_button_draw_area: Rect::default(), + } } + _ => ButtonState::Simple { + yes: false, + last_yes_button_area: Rect::default(), + last_no_button_area: Rect::default(), + }, } }; @@ -607,8 +628,8 @@ impl ProcessKillDialog { } pub fn handle_redraw(&mut self) { - // FIXME: Not sure if we need this. We can probably handle this better in the - // draw function later. + // FIXME: Not sure if we need this. We can probably handle this better + // in the draw function later. #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))] { @@ -695,16 +716,17 @@ impl ProcessKillDialog { // A list of options, displayed vertically. const SIGNAL_TEXT_LEN: u16 = SIGNAL_TEXT.len() as u16; - // Make the rect only as big as it needs to be, which is the height of the text, - // the buttons, and up to 2 spaces (margin and space between), and the size of + // Make the rect only as big as it needs to be, which is the + // height of the text, the buttons, and up to 2 + // spaces (margin and space between), and the size of // the block. let [draw_area] = Layout::vertical([Constraint::Max(num_lines + SIGNAL_TEXT_LEN + 2 + 3)]) .flex(Flex::Center) .areas(draw_area); - // Now we need to divide the block into one area for the paragraph, - // and one for the buttons. + // Now we need to divide the block into one area for the + // paragraph, and one for the buttons. let [text_draw_area, button_draw_area] = Layout::vertical([ Constraint::Max(num_lines), Constraint::Max(SIGNAL_TEXT_LEN), @@ -733,7 +755,8 @@ impl ProcessKillDialog { Span::styled(signal, style) })); - // This is kinda dumb how you have to set the constraint, but ok. + // This is kinda dumb how you have to set the constraint, but + // ok. const LONGEST_SIGNAL_TEXT_LENGTH: u16 = const { let mut i = 0; let mut max = 0; @@ -771,14 +794,15 @@ impl ProcessKillDialog { last_yes_button_area, last_no_button_area, } => { - // Make the rect only as big as it needs to be, which is the height of the text, - // the buttons, and up to 3 spaces (margin and space between) + 2 for block. + // Make the rect only as big as it needs to be, which is the + // height of the text, the buttons, and up to 3 + // spaces (margin and space between) + 2 for block. let [draw_area] = Layout::vertical([Constraint::Max(num_lines + 1 + 3 + 2)]) .flex(Flex::Center) .areas(draw_area); - // Now we need to divide the block into one area for the paragraph, - // and one for the buttons. + // Now we need to divide the block into one area for the + // paragraph, and one for the buttons. let [text_area, button_area] = Layout::vertical([Constraint::Max(num_lines), Constraint::Length(1)]) .flex(Flex::SpaceEvenly) @@ -849,8 +873,8 @@ impl ProcessKillDialog { pub fn draw(&mut self, f: &mut Frame<'_>, draw_area: Rect, styles: &Styles) { // The idea is: // - Use as big of a dialog box as needed (within the maximal draw loc) - // - So the non-button ones are going to be smaller... probably whatever the - // height of the text is. + // - So the non-button ones are going to be smaller... probably + // whatever the height of the text is. // - Meanwhile for the button one, it'll likely be full height if it's // "advanced" kill. @@ -863,7 +887,8 @@ impl ProcessKillDialog { match &mut self.state { ProcessKillDialogState::NotEnabled => {} ProcessKillDialogState::Selecting(state) => { - // Draw a text box. If buttons are yes/no, fit it, otherwise, use max space. + // Draw a text box. If buttons are yes/no, fit it, otherwise, + // use max space. Self::draw_selecting(f, draw_area, styles, state); } ProcessKillDialogState::Error { diff --git a/src/canvas/widgets/battery_display.rs b/src/canvas/widgets/battery_display.rs index 0d53b9a1..c032b121 100644 --- a/src/canvas/widgets/battery_display.rs +++ b/src/canvas/widgets/battery_display.rs @@ -110,7 +110,8 @@ impl Painter { tab_click_locs .push(((current_x, current_y), (current_x + width, current_y))); - // +4 because we want to go one space, then one space past to get to the + // +4 because we want to go one space, then one space + // past to get to the // '|', then 2 more to start at the blank space // before the tab label. current_x += width + 4; diff --git a/src/canvas/widgets/cpu_basic.rs b/src/canvas/widgets/cpu_basic.rs index 31785683..2c8190b0 100644 --- a/src/canvas/widgets/cpu_basic.rs +++ b/src/canvas/widgets/cpu_basic.rs @@ -28,10 +28,11 @@ impl Painter { // of columns to draw all CPUs. Ideally, as well, we want to not have // to ever scroll. // - // **General logic** - count number of elements in cpu_data. Then see how - // many rows and columns we have in draw_loc (-2 on both sides for border?). - // I think what we can do is try to fit in as many in one column as possible. - // If not, then add a new column. Then, from this, split the row space across + // **General logic** - count number of elements in cpu_data. Then see + // how many rows and columns we have in draw_loc (-2 on both + // sides for border?). I think what we can do is try to fit in + // as many in one column as possible. If not, then add a new + // column. Then, from this, split the row space across // ALL columns. From there, generate the desired lengths. f.render_widget( @@ -59,8 +60,8 @@ impl Painter { let [cores_loc, mut avg_loc] = Layout::vertical([Constraint::Min(0), Constraint::Length(1)]).areas(draw_loc); - // The cores section all have horizontal margin, so to line up with the cores we - // need to add some margin ourselves. + // The cores section all have horizontal margin, so to line up with + // the cores we need to add some margin ourselves. avg_loc.x += 1; avg_loc.width -= 2; diff --git a/src/canvas/widgets/cpu_graph.rs b/src/canvas/widgets/cpu_graph.rs index 273af59a..a4ddf17a 100644 --- a/src/canvas/widgets/cpu_graph.rs +++ b/src/canvas/widgets/cpu_graph.rs @@ -127,7 +127,8 @@ impl Painter { let time = &data.time_series_data.time; if current_scroll_position == ALL_POSITION { - // This case ensures the other cases cannot have the position be equal to 0. + // This case ensures the other cases cannot have the position be + // equal to 0. cpu_points .iter() @@ -145,9 +146,9 @@ impl Painter { .rev() .collect() } else if let Some(CpuData { .. }) = cpu_entries.get(current_scroll_position - 1) { - // We generally subtract one from current scroll position because of the all - // entry. TODO: Do this a bit better (e.g. we can just do if let - // Some(_) = cpu_points.get()) + // We generally subtract one from current scroll position because of + // the all entry. TODO: Do this a bit better (e.g. we + // can just do if let Some(_) = cpu_points.get()) let style = if show_avg_cpu && current_scroll_position == AVG_POSITION { self.styles.avg_cpu_colour @@ -241,8 +242,8 @@ impl Painter { .widget_states .get_mut(&(widget_id - 1)) { - // TODO: This line (and the one above, see caller) is pretty dumb but I guess - // needed for now. Refactor if possible! + // TODO: This line (and the one above, see caller) is pretty dumb + // but I guess needed for now. Refactor if possible! cpu_widget_state.is_legend_hidden = false; let is_on_widget = widget_id == app_state.current_widget.widget_id; diff --git a/src/canvas/widgets/disk_io_graph.rs b/src/canvas/widgets/disk_io_graph.rs index a4116338..caf8b55d 100644 --- a/src/canvas/widgets/disk_io_graph.rs +++ b/src/canvas/widgets/disk_io_graph.rs @@ -67,8 +67,9 @@ impl Painter { .is_some_and(|d| has_data_in_window(d, times, current_display_time)) }; - // If there is a mount point and we're in mount legend mode, it must be non-empty - // (i.e. actually mounted), or we will short-circuit and ignore it. + // If there is a mount point and we're in mount legend mode, + // it must be non-empty (i.e. actually + // mounted), or we will short-circuit and ignore it. if let Some(mount_point) = mount_map.get(name.as_str()) { match legend_type { DiskGraphLegend::Disk => true, @@ -77,11 +78,14 @@ impl Painter { } else { match legend_type { DiskGraphLegend::Disk => { - // Otherwise, it may have _previously_ been a valid mount point, so keep showing it until it ages out. + // Otherwise, it may have _previously_ been a + // valid mount point, so keep showing it until + // it ages out. has_read_data() } DiskGraphLegend::Mount => { - // Since it would be misleading in this case, just skip it in mount mode. + // Since it would be misleading in this case, + // just skip it in mount mode. false } } @@ -114,12 +118,14 @@ impl Painter { }; // Removed devices still visible in the window show "N/A". - // TODO: Maybe should make it so the colour is based on entry name? As then it may shift. + // TODO: Maybe should make it so the colour is based on entry name? + // As then it may shift. let read_colours = &self.styles.disk_io_read_colour_styles; let write_colours = &self.styles.disk_io_write_colour_styles; - // Pad the device/mount labels to the widest visible one so the rate columns - // line up in the legend (the rate itself is already fixed-width). + // Pad the device/mount labels to the widest visible one so the rate + // columns line up in the legend (the rate itself is + // already fixed-width). let name_width = device_names .iter() .map(|name| match legend_type { @@ -140,7 +146,8 @@ impl Painter { DiskGraphLegend::Disk => name.as_str(), DiskGraphLegend::Mount => match mount_map.get(name.as_str()).copied() { Some(mount) => mount, - // This wouldn't trigger anyway, we filter out devices without mount points in mount legend mode. + // This wouldn't trigger anyway, we filter out devices without mount points + // in mount legend mode. None => continue, }, }; @@ -161,7 +168,8 @@ impl Painter { write_colours[idx % write_colours.len()] }; - // TODO: Combine into one line; probably need to add some kind of multi-styled GraphData. + // TODO: Combine into one line; probably need to add some kind + // of multi-styled GraphData. if let Some(values) = read_values { let rate = if is_active { format_rate_fixed(values.last().copied().unwrap_or(0.0)) @@ -237,8 +245,8 @@ impl Painter { } /// Returns true if `data` has at least one real (non-gap) data point within the -/// visible time window defined by `current_display_time` milliseconds from the end -/// of `times`. +/// visible time window defined by `current_display_time` milliseconds from the +/// end of `times`. fn has_data_in_window>( data: &ChunkedData, times: &[Instant], current_display_time: u64, ) -> bool { @@ -252,8 +260,9 @@ fn has_data_in_window>( .is_some_and(|(t, _)| *t >= oldest) } -/// Format a byte/s rate as a fixed-width string (always 11 chars, right-aligned) -/// to keep legend labels a stable width and prevent legend box shifting between frames. +/// Format a byte/s rate as a fixed-width string (always 11 chars, +/// right-aligned) to keep legend labels a stable width and prevent legend box +/// shifting between frames. fn format_rate_fixed(bytes_per_sec: f64) -> String { let (val, unit) = if bytes_per_sec < KIBI_LIMIT_F64 { (bytes_per_sec, "B/s") diff --git a/src/canvas/widgets/mem_graph.rs b/src/canvas/widgets/mem_graph.rs index fcc42075..2900818c 100644 --- a/src/canvas/widgets/mem_graph.rs +++ b/src/canvas/widgets/mem_graph.rs @@ -68,8 +68,9 @@ impl Painter { let mut size = 1; let data = app_state.data_store.get_data(); - // TODO: is this optimization really needed...? This just pre-allocates a vec, - // but it'll probably never be that big... + // TODO: is this optimization really needed...? This just + // pre-allocates a vec, but it'll probably never + // be that big... if data.swap_harvest.is_some() { size += 1; // add capacity for SWAP @@ -89,7 +90,8 @@ impl Painter { let time_series = &data.time_series_data; let time = &time_series.time; - // TODO: Add a "no data" option here/to time graph if there is no entries + // TODO: Add a "no data" option here/to time graph if there is + // no entries graph_data( &mut points, "RAM", diff --git a/src/canvas/widgets/network_basic.rs b/src/canvas/widgets/network_basic.rs index 383aef59..0aff1da9 100644 --- a/src/canvas/widgets/network_basic.rs +++ b/src/canvas/widgets/network_basic.rs @@ -56,8 +56,9 @@ impl Painter { avg_tx_packet_size, } = calculate_packet_info(network_data, use_binary_prefix); - // TODO: Stylize packet stuff later with something else? Or maybe make it so - // total is now (by default) just bolded RX/TX? I doubt anyone cares... + // TODO: Stylize packet stuff later with something else? Or maybe + // make it so total is now (by default) just bolded + // RX/TX? I doubt anyone cares... let rx_packet_rate_label = format!("RX Pkt: {}pkt/s", rx_packet_rate); let tx_packet_rate_label = format!("TX Pkt: {}pkt/s", tx_packet_rate); let avg_rx_packet_size_label = format!( @@ -72,7 +73,8 @@ impl Painter { if draw_loc.width < 60 { // 4 rows x 2 columns layout // Column 1: RX, TX, Total RX, Total TX (top to bottom) - // Column 2: RX Packets, TX Packets, AVG RX, AVG TX (top to bottom) + // Column 2: RX Packets, TX Packets, AVG RX, AVG TX (top to + // bottom) let grid_loc = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) diff --git a/src/canvas/widgets/network_graph.rs b/src/canvas/widgets/network_graph.rs index 18a3d6f5..0067215d 100644 --- a/src/canvas/widgets/network_graph.rs +++ b/src/canvas/widgets/network_graph.rs @@ -45,8 +45,8 @@ impl Painter { if app_state.should_get_widget_bounds() { // Update draw loc in widget map - // Note that in both cases, we always go to the same widget id so it's fine to - // do it like this lol. + // Note that in both cases, we always go to the same widget id so + // it's fine to do it like this lol. if let Some(network_widget) = app_state.widget_map.get_mut(&widget_id) { network_widget.top_left_corner = Some((draw_loc.x, draw_loc.y)); network_widget.bottom_right_corner = @@ -84,8 +84,8 @@ impl Painter { let use_old_network_legend = app_state.app_config_fields.use_old_network_legend; let legend_constraints = if use_old_network_legend { - // Always hide it. Note that I could pass in `None` to the position as well but - // eh this works. + // Always hide it. Note that I could pass in `None` to the + // position as well but eh this works. LegendConstraints { width: Constraint::Length(0), height: Constraint::Length(0), @@ -99,7 +99,8 @@ impl Painter { } }; - // TODO: Add support for clicking on legend to only show that value on chart. + // TODO: Add support for clicking on legend to only show that value + // on chart. let use_binary_prefix = app_state.app_config_fields.network_use_binary_prefix; let unit_type = app_state.app_config_fields.network_unit_type; let unit = match unit_type { @@ -140,9 +141,10 @@ impl Painter { const MAX_LEGEND_WIDTH: u16 = 70; let approx_legend_width = draw_loc.width * 3 / 4; - // FIXME: I'm not really a huge fan of this - I think it may be better to just - // not support this and allow for more easily spawning a - // separate legend table (basically old legend). + // FIXME: I'm not really a huge fan of this - I think it may be + // better to just not support this and allow for + // more easily spawning a separate legend table + // (basically old legend). if app_state.app_config_fields.network_show_packets && approx_legend_width > MAX_LEGEND_WIDTH { @@ -329,20 +331,21 @@ impl Painter { fn adjust_network_data_point(max_entry: f64, config: &AppConfigFields) -> (f64, Vec) { // So, we're going with an approach like this for linear data: // - Main goal is to maximize the amount of information displayed given a - // specific height. We don't want to drown out some data if the ranges are too - // far though! Nor do we want to filter out too much data... - // - Change the y-axis unit (kilo/kibi, mega/mebi...) dynamically based on max - // load. + // specific height. We don't want to drown out some data if the ranges are + // too far though! Nor do we want to filter out too much data... + // - Change the y-axis unit (kilo/kibi, mega/mebi...) dynamically based on + // max load. // - // The idea is we take the top value, build our scale such that each "point" is - // a scaled version of that. So for example, let's say I use 390 Mb/s. If I - // drew 4 segments, it would be 97.5, 195, 292.5, 390, and + // The idea is we take the top value, build our scale such that each "point" + // is a scaled version of that. So for example, let's say I use 390 + // Mb/s. If I drew 4 segments, it would be 97.5, 195, 292.5, 390, and // probably something like 438.75? // - // So, how do we do this in ratatui? Well, if we are using intervals that tie - // in perfectly to the max value we want... then it's actually not that - // hard. Since ratatui accepts a vector as labels and will properly space - // them all out... we just work with that and space it out properly. + // So, how do we do this in ratatui? Well, if we are using intervals that + // tie in perfectly to the max value we want... then it's actually not + // that hard. Since ratatui accepts a vector as labels and will properly + // space them all out... we just work with that and space it out + // properly. // // Dynamic chart idea based off of FreeNAS's chart design. // @@ -382,8 +385,9 @@ fn adjust_network_data_point(max_entry: f64, config: &AppConfigFields) -> (f64, }; let max_entry_upper = if max_entry == 0.0 { - // If it's 0, then just use a very low value so the labels aren't just "0.0" 4 - // times. This _also_ prevents the y-axis height range ever + // If it's 0, then just use a very low value so the labels + // aren't just "0.0" 4 times. This _also_ + // prevents the y-axis height range ever // being 0. 1.0 } else { @@ -420,9 +424,10 @@ fn adjust_network_data_point(max_entry: f64, config: &AppConfigFields) -> (f64, } }; - // Finally, build an acceptable range starting from there, using the given - // height! Note we try to put more of a weight on the bottom section - // vs. the top, since the top has less data. + // Finally, build an acceptable range starting from there, using the + // given height! Note we try to put more of a weight on + // the bottom section vs. the top, since the top has + // less data. let base_unit = max_value_scaled; let labels: Vec = vec![ format!("0{unit_prefix}{unit_type}"), @@ -432,8 +437,9 @@ fn adjust_network_data_point(max_entry: f64, config: &AppConfigFields) -> (f64, ] .into_iter() .map(|s| { - // Pull 5 as the longest legend value is generally going to be 5 digits (if they - // somehow hit over 5 terabits per second) + // Pull 5 as the longest legend value is generally going to be 5 + // digits (if they somehow hit over 5 terabits + // per second) format!("{s:>5}") }) .collect(); @@ -447,8 +453,8 @@ fn adjust_network_data_point(max_entry: f64, config: &AppConfigFields) -> (f64, (LOG_MEGA_LIMIT, LOG_GIGA_LIMIT, LOG_TERA_LIMIT) }; - // Remember to do saturating log checks as otherwise 0.0 becomes inf, and you - // get gaps! + // Remember to do saturating log checks as otherwise 0.0 becomes + // inf, and you get gaps! let max_entry = if use_binary_prefix { saturating_log2(max_entry) } else { @@ -534,7 +540,8 @@ fn adjust_network_data_point(max_entry: f64, config: &AppConfigFields) -> (f64, ], ) } else { - // I really doubt anyone's transferring beyond petabyte speeds... + // I really doubt anyone's transferring beyond petabyte + // speeds... ( if use_binary_prefix { LOG_PEBI_LIMIT diff --git a/src/canvas/widgets/process_table.rs b/src/canvas/widgets/process_table.rs index 3d47e65d..5f1b08e5 100644 --- a/src/canvas/widgets/process_table.rs +++ b/src/canvas/widgets/process_table.rs @@ -177,12 +177,8 @@ impl Painter { // TODO: [MOVEMENT] Movement support for these in search let (case, whole, regex) = { cfg_select! { - target_os = "macos" => { - ("Case(F1)", "Whole(F2)", "Regex(F3)") - } - _ => { - ("Case(Alt+C)", "Whole(Alt+W)", "Regex(Alt+R)") - } + target_os = "macos" => ("Case(F1)", "Whole(F2)", "Regex(F3)"), + _ => ("Case(Alt+C)", "Whole(Alt+W)", "Regex(Alt+R)"), } }; let option_text = Line::from(vec![ diff --git a/src/collection.rs b/src/collection.rs index 16fc21c7..dca17ef9 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -314,8 +314,8 @@ impl DataCollector { /// - Disk (Windows, FreeBSD) /// - Temperatures (non-Linux) fn refresh_sysinfo_data(&mut self) { - // Refresh the list of objects once every minute. If it's too frequent it can - // cause segfaults. + // Refresh the list of objects once every minute. If it's too frequent + // it can cause segfaults. if self.widgets_to_harvest.use_cpu || self.widgets_to_harvest.use_proc { self.sys.system.refresh_cpu_all(); @@ -480,9 +480,10 @@ impl DataCollector { if self.widgets_to_harvest.use_proc && let Ok(mut process_list) = self.get_processes() { - // NB: To avoid duplicate sorts on rerenders/events, we sort the processes by - // PID here. We also want to avoid re-sorting *again* later on - // if we're sorting by PID, since we already did it here! + // NB: To avoid duplicate sorts on rerenders/events, we sort the + // processes by PID here. We also want to avoid + // re-sorting *again* later on if we're sorting by PID, + // since we already did it here! process_list.sort_unstable_by_key(|p| p.pid); self.data.list_of_processes = Some(process_list); } @@ -524,7 +525,8 @@ impl DataCollector { if arc.0.used_bytes > arc.1 { #[cfg(target_os = "linux")] { - // Keep arc min like htop; the subtraction below won't underflow because of + // Keep arc min like htop; the subtraction + // below won't underflow because of // the above check. mem.used_bytes = mem.used_bytes.saturating_sub(arc.0.used_bytes - arc.1); diff --git a/src/collection/amd.rs b/src/collection/amd.rs index 910185f0..742b5855 100644 --- a/src/collection/amd.rs +++ b/src/collection/amd.rs @@ -70,8 +70,8 @@ fn get_amd_devs() -> Option> { continue; } - // This will exist for GPUs but not others, this is how we find their kernel - // name. + // This will exist for GPUs but not others, this is how we find their + // kernel name. let test_path = device_path.join("drm"); if test_path.as_path().exists() { devices.push(device_path); diff --git a/src/collection/cpu/sysinfo.rs b/src/collection/cpu/sysinfo.rs index 27abaa62..7c1e3967 100644 --- a/src/collection/cpu/sysinfo.rs +++ b/src/collection/cpu/sysinfo.rs @@ -14,15 +14,16 @@ pub fn get_cpu_data_list(collector: &DataCollector) -> CollectionResult { cpus.push(CpuData { data_type: CpuDataType::Avg, - usage: collector.cgroup_cpu_data.avg_cpu_percent.unwrap_or_else(|| sys.global_cpu_usage()), + usage: collector + .cgroup_cpu_data + .avg_cpu_percent + .unwrap_or_else(|| sys.global_cpu_usage()), }); } - _ => { - cpus.push(CpuData { - data_type: CpuDataType::Avg, - usage: sys.global_cpu_usage(), - }) - } + _ => cpus.push(CpuData { + data_type: CpuDataType::Avg, + usage: sys.global_cpu_usage(), + }), } } @@ -42,8 +43,8 @@ pub fn get_cpu_data_list(collector: &DataCollector) -> CollectionResult crate::collection::cpu::LoadAvgHarvest { - // The API for sysinfo apparently wants you to call it like this, rather than - // using a &System. + // The API for sysinfo apparently wants you to call it like this, rather + // than using a &System. let sysinfo::LoadAvg { one, five, fifteen } = sysinfo::System::load_average(); [one as f32, five as f32, fifteen as f32] diff --git a/src/collection/disks.rs b/src/collection/disks.rs index ab76950d..88c42ef8 100644 --- a/src/collection/disks.rs +++ b/src/collection/disks.rs @@ -9,6 +9,7 @@ cfg_select! { mod zfs_io_counters; #[cfg(feature = "zfs")] pub use io_counters::IoCounters; + pub(crate) use self::freebsd::*; } target_os = "windows" => { @@ -64,13 +65,13 @@ cfg_select! { any(target_os = "linux", target_os = "macos", target_os = "windows") => { mod io_counters; pub use io_counters::IoCounters; + use crate::collection::DataCollector; /// Returns the I/O usage of certain mount points. pub fn get_io_usage(_collector: &DataCollector) -> anyhow::Result { let mut io_hash: HashMap> = HashMap::default(); - // TODO: Maybe rewrite this to not do a result of vec of result... for io in io_stats()?.into_iter() { let mount_point = io.device_name().to_string_lossy(); diff --git a/src/collection/disks/unix.rs b/src/collection/disks/unix.rs index aa7d5e16..84c53c7d 100644 --- a/src/collection/disks/unix.rs +++ b/src/collection/disks/unix.rs @@ -49,21 +49,21 @@ pub fn get_disk_usage(collector: &DataCollector) -> anyhow::Result anyhow::Result anyhow::Result> { let mut reader = BufReader::new(File::open(PROC_DISKSTATS)?); let mut line = String::new(); - // This saves us from doing a string allocation on each iteration compared to - // `lines()`. + // This saves us from doing a string allocation on each iteration compared + // to `lines()`. while let Ok(bytes) = reader.read_line(&mut line) { if bytes > 0 { if let Ok(counters) = IoCounters::from_str(&line) { diff --git a/src/collection/disks/unix/linux/partition.rs b/src/collection/disks/unix/linux/partition.rs index bd69414d..08bc829c 100644 --- a/src/collection/disks/unix/linux/partition.rs +++ b/src/collection/disks/unix/linux/partition.rs @@ -43,8 +43,8 @@ impl Partition { /// Returns the device name for the partition. pub fn get_device_name(&self) -> String { if let Some(device) = self.device() { - // See if this disk is actually mounted elsewhere on Linux. This is a workaround - // properly map I/O in some cases (i.e. disk encryption, https://github.com/ClementTsang/bottom/issues/419). + // See if this disk is actually mounted elsewhere on Linux. This is + // a workaround properly map I/O in some cases (i.e. disk encryption, https://github.com/ClementTsang/bottom/issues/419). if let Ok(path) = std::fs::read_link(device) { if path.is_absolute() { path.into_os_string() @@ -88,8 +88,8 @@ impl Partition { let mut vfs = mem::MaybeUninit::::uninit(); - // SAFETY: libc call, `path` is a valid C string and buf is a valid pointer to - // write to. + // SAFETY: libc call, `path` is a valid C string and buf is a valid + // pointer to write to. let result = unsafe { libc::statvfs(path.as_ptr(), vfs.as_mut_ptr()) }; if result == 0 { @@ -161,8 +161,8 @@ pub(crate) fn partitions() -> anyhow::Result> { let mut reader = BufReader::new(File::open(PROC_MOUNTS)?); let mut line = String::new(); - // This saves us from doing a string allocation on each iteration compared to - // `lines()`. + // This saves us from doing a string allocation on each iteration compared + // to `lines()`. while let Ok(bytes) = reader.read_line(&mut line) { if bytes > 0 { if let Ok(partition) = Partition::from_str(&line) { @@ -187,8 +187,8 @@ pub(crate) fn physical_partitions() -> anyhow::Result> { let mut reader = BufReader::new(File::open(PROC_MOUNTS)?); let mut line = String::new(); - // This saves us from doing a string allocation on each iteration compared to - // `lines()`. + // This saves us from doing a string allocation on each iteration compared + // to `lines()`. while let Ok(bytes) = reader.read_line(&mut line) { if bytes > 0 { if let Ok(partition) = Partition::from_str(&line) diff --git a/src/collection/disks/unix/linux/unmounted.rs b/src/collection/disks/unix/linux/unmounted.rs index 0085f1d5..01220903 100644 --- a/src/collection/disks/unix/linux/unmounted.rs +++ b/src/collection/disks/unix/linux/unmounted.rs @@ -14,9 +14,9 @@ const PARTITION_BLOCK_SIZE: u64 = 1024; /// Returns [`DiskHarvest`] entries for block devices that aren't in `mounted`. /// /// These come from `/proc/partitions`, which lists every block device (so even -/// devices with no I/O activity are covered) along with its size in terms of blocks. -/// Note this also filters out some devices, like `loop*`, `ram*`, `zram*`, etc., as -/// these are not "disks". +/// devices with no I/O activity are covered) along with its size in terms of +/// blocks. Note this also filters out some devices, like `loop*`, `ram*`, +/// `zram*`, etc., as these are not "disks". pub(crate) fn unmounted_disks(mounted: &HashSet) -> Vec { const PROC_PARTITIONS: &str = "/proc/partitions"; @@ -27,7 +27,8 @@ pub(crate) fn unmounted_disks(mounted: &HashSet) -> Vec { parse_unmounted_disks(BufReader::new(file), mounted) } -/// Parses `/proc/partitions` into [`DiskHarvest`] entries for block devices not present in `mounted`. +/// Parses `/proc/partitions` into [`DiskHarvest`] entries for block devices not +/// present in `mounted`. fn parse_unmounted_disks(mut reader: R, mounted: &HashSet) -> Vec { let mut disks = Vec::new(); let mut line = String::new(); @@ -37,8 +38,8 @@ fn parse_unmounted_disks(mut reader: R, mounted: &HashSet) - break; } - // Format: `major minor #blocks name`. The header line and the blank line - // after it simply fail to parse here and get skipped. + // Format: `major minor #blocks name`. The header line and the blank + // line after it simply fail to parse here and get skipped. let mut parts = line.split_whitespace(); let blocks = parts.nth(2).and_then(|b| b.parse::().ok()); let name = parts.next(); diff --git a/src/collection/disks/unix/macos/counters.rs b/src/collection/disks/unix/macos/counters.rs index 81b6c707..89496da9 100644 --- a/src/collection/disks/unix/macos/counters.rs +++ b/src/collection/disks/unix/macos/counters.rs @@ -10,8 +10,8 @@ fn get_device_io(device: io_kit::IoObject) -> anyhow::Result { // // Okay, so this is weird. // - // The problem is that if I have this check - this is what sources like psutil - // use, for example (see https://github.com/giampaolo/psutil/blob/7eadee31db2f038763a3a6f978db1ea76bbc4674/psutil/_psutil_osx.c#LL1422C20-L1422C20) + // The problem is that if I have this check - this is what sources like + // psutil use, for example (see https://github.com/giampaolo/psutil/blob/7eadee31db2f038763a3a6f978db1ea76bbc4674/psutil/_psutil_osx.c#LL1422C20-L1422C20) // then this will only return stuff like disk0. // // The problem with this is that there is *never* a disk0 *disk* entry to @@ -19,15 +19,15 @@ fn get_device_io(device: io_kit::IoObject) -> anyhow::Result { // Someone's done some digging on the gopsutil repo (https://github.com/shirou/gopsutil/issues/855#issuecomment-610016435), and it seems // like this is a consequence of how Apple does logical volumes. // - // So with all that said, what I've found is that I *can* still get a mapping - - // but I have to disable the conform check, which... is weird. I'm not sure - // if this is valid at all. But it *does* seem to match Activity Monitor - // with regards to disk activity, so... I guess we can leave this for - // now...? + // So with all that said, what I've found is that I *can* still get a + // mapping - but I have to disable the conform check, which... is weird. + // I'm not sure if this is valid at all. But it *does* seem to match + // Activity Monitor with regards to disk activity, so... I guess we can + // leave this for now...? // if !parent.conforms_to_block_storage_driver() { - // anyhow::bail!("{parent:?}, the parent of {device:?} does not conform to - // IOBlockStorageDriver") } + // anyhow::bail!("{parent:?}, the parent of {device:?} does not conform + // to IOBlockStorageDriver") } let disk_props = device.properties()?; let parent_props = parent.properties()?; diff --git a/src/collection/disks/unix/macos/io_kit/io_disks.rs b/src/collection/disks/unix/macos/io_kit/io_disks.rs index 0bb13ab6..3414b943 100644 --- a/src/collection/disks/unix/macos/io_kit/io_disks.rs +++ b/src/collection/disks/unix/macos/io_kit/io_disks.rs @@ -6,7 +6,8 @@ use super::{IoIterator, bindings::*}; pub fn get_disks() -> anyhow::Result { let mut media_iter: io_iterator_t = 0; - // SAFETY: This is a safe syscall via IOKit, all the arguments should be safe. + // SAFETY: This is a safe syscall via IOKit, all the arguments should be + // safe. let result = unsafe { IOServiceGetMatchingServices( kIOMasterPortDefault, diff --git a/src/collection/disks/unix/macos/io_kit/io_iterator.rs b/src/collection/disks/unix/macos/io_kit/io_iterator.rs index b1b1f6a7..b43a78f1 100644 --- a/src/collection/disks/unix/macos/io_kit/io_iterator.rs +++ b/src/collection/disks/unix/macos/io_kit/io_iterator.rs @@ -37,8 +37,8 @@ impl Iterator for IoIterator { fn next(&mut self) -> Option { // Basically, we just stop when we hit 0. - // SAFETY: IOKit call, the passed argument (an `io_iterator_t`) is what is - // expected. + // SAFETY: IOKit call, the passed argument (an `io_iterator_t`) is what + // is expected. match unsafe { IOIteratorNext(self.0) } { 0 => None, io_object => Some(IoObject::from(io_object)), @@ -48,8 +48,8 @@ impl Iterator for IoIterator { impl Drop for IoIterator { fn drop(&mut self) { - // SAFETY: IOKit call, the passed argument (an `io_iterator_t`) is what is - // expected. + // SAFETY: IOKit call, the passed argument (an `io_iterator_t`) is what + // is expected. let result = unsafe { IOObjectRelease(self.0) }; assert_eq!(result, kern_return::KERN_SUCCESS); } diff --git a/src/collection/disks/unix/macos/io_kit/io_object.rs b/src/collection/disks/unix/macos/io_kit/io_object.rs index 0b64504e..ecde01de 100644 --- a/src/collection/disks/unix/macos/io_kit/io_object.rs +++ b/src/collection/disks/unix/macos/io_kit/io_object.rs @@ -81,8 +81,8 @@ impl From for IoObject { impl Drop for IoObject { fn drop(&mut self) { - // SAFETY: IOKit call, the argument here (an `io_object_t`) should be safe and - // expected. + // SAFETY: IOKit call, the argument here (an `io_object_t`) should be + // safe and expected. let result = unsafe { IOObjectRelease(self.0) }; assert_eq!(result, kern_return::KERN_SUCCESS); } @@ -95,12 +95,14 @@ pub fn get_dict( dict.find(&key) .map(|value_ref| { - // SAFETY: Only used for debug asserts, system API call that should be safe. + // SAFETY: Only used for debug asserts, system API call that should + // be safe. unsafe { debug_assert!(value_ref.type_of() == CFDictionaryGetTypeID()); } - // "Casting" `CFDictionary<*const void, *const void>` into a needed dict type + // "Casting" `CFDictionary<*const void, *const void>` into a needed + // dict type let ptr = value_ref.to_void() as CFDictionaryRef; // SAFETY: System API call, it should be safe? @@ -116,7 +118,8 @@ pub fn get_i64( dict.find(&key) .and_then(|value_ref| { - // SAFETY: Only used for debug asserts, system API call that should be safe. + // SAFETY: Only used for debug asserts, system API call that should + // be safe. unsafe { debug_assert!(value_ref.type_of() == CFNumberGetTypeID()); } @@ -133,7 +136,8 @@ pub fn get_string( dict.find(&key) .and_then(|value_ref| { - // SAFETY: Only used for debug asserts, system API call that should be safe. + // SAFETY: Only used for debug asserts, system API call that should + // be safe. unsafe { debug_assert!(value_ref.type_of() == CFStringGetTypeID()); } diff --git a/src/collection/disks/unix/other/bindings.rs b/src/collection/disks/unix/other/bindings.rs index 3b81c193..5ff8c162 100644 --- a/src/collection/disks/unix/other/bindings.rs +++ b/src/collection/disks/unix/other/bindings.rs @@ -35,9 +35,9 @@ pub(crate) fn mounts() -> anyhow::Result> { "Expected {expected_len} statfs entries, but instead got {result} entries", ); - // SAFETY: We have a debug assert check, and if `result` is not correct (-1), we - // check against it. Otherwise, getfsstat64 should return the number of - // statfs structures if it succeeded. + // SAFETY: We have a debug assert check, and if `result` is not correct + // (-1), we check against it. Otherwise, getfsstat64 should + // return the number of statfs structures if it succeeded. // // Source: https://man.freebsd.org/cgi/man.cgi?query=getfsstat&sektion=2&format=html unsafe { diff --git a/src/collection/disks/unix/other/partition.rs b/src/collection/disks/unix/other/partition.rs index d3461e80..18f30ff4 100644 --- a/src/collection/disks/unix/other/partition.rs +++ b/src/collection/disks/unix/other/partition.rs @@ -38,8 +38,8 @@ impl Partition { let result = unsafe { libc::statvfs(path.as_ptr(), vfs.as_mut_ptr()) }; if result == 0 { - // SAFETY: We check that it succeeded (result is 0), which means vfs should be - // populated. + // SAFETY: We check that it succeeded (result is 0), which means vfs + // should be populated. Ok(Usage::new(unsafe { vfs.assume_init() })) } else { bail!("statvfs failed to get the disk usage for disk {path:?}") diff --git a/src/collection/disks/windows/bindings.rs b/src/collection/disks/windows/bindings.rs index 5ec9c136..165211a9 100644 --- a/src/collection/disks/windows/bindings.rs +++ b/src/collection/disks/windows/bindings.rs @@ -41,8 +41,8 @@ fn volume_io(volume: &Path) -> anyhow::Result { wide_path }; - // SAFETY: API call, arguments should be correct. We must also check after the - // call to ensure it is valid. + // SAFETY: API call, arguments should be correct. We must also check after + // the call to ensure it is valid. let h_device = unsafe { CreateFileW( windows::core::PCWSTR(volume.as_ptr()), @@ -114,8 +114,8 @@ pub(crate) fn all_volume_io() -> anyhow::Result anyhow::Result anyhow::Result { - // According to winapi docs 50 is a reasonable length to accommodate the volume - // path https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumenameforvolumemountpointw + // According to winapi docs 50 is a reasonable length to accommodate the + // volume path https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumenameforvolumemountpointw const VOLUME_MAX_LEN: usize = 50; let mount = { let mount_path = Path::new(mount); let mut wide_path = mount_path.as_os_str().encode_wide().collect::>(); - // Always push on a \0 character, without this it will occasionally break. + // Always push on a \0 character, without this it will occasionally + // break. wide_path.push(0x0000); wide_path diff --git a/src/collection/linux/cgroups.rs b/src/collection/linux/cgroups.rs index 7065b0f8..e2297fa9 100644 --- a/src/collection/linux/cgroups.rs +++ b/src/collection/linux/cgroups.rs @@ -44,7 +44,8 @@ pub(crate) struct CgroupMemCollector { pub swap: Option, } -/// Computes the cgroup v1 swap limit. Calculated by getting memsw and subtracting the memory limits. +/// Computes the cgroup v1 swap limit. Calculated by getting memsw and +/// subtracting the memory limits. #[inline] fn cgroup_v1_swap_limit( memsw_limit: u64, mem_limit: Option, total_memory: u64, total_swap: u64, @@ -68,7 +69,8 @@ impl CgroupMemCollector { } } - /// Try and update the memory using cgroup v1 semantics. If successful, returns `true`. + /// Try and update the memory using cgroup v1 semantics. If successful, + /// returns `true`. fn try_update_memory_cgroup_v1(&mut self, total_memory: u64, total_swap: u64) -> bool { if let Some(mem_usage) = read_u64("/sys/fs/cgroup/memory/memory.usage_in_bytes") { // --- Memory --- @@ -80,7 +82,8 @@ impl CgroupMemCollector { }; // Technically if it's some insanely high value (https://unix.stackexchange.com/a/421182), - // then it's "unlimited", but we can just make it so we take the max of the main and this anyway. + // then it's "unlimited", but we can just make it so we take the max + // of the main and this anyway. let mem_limit_raw = read_u64("/sys/fs/cgroup/memory/memory.limit_in_bytes"); let mem_limit = mem_limit_raw.map(CgroupMemLimit::Bytes); @@ -90,7 +93,8 @@ impl CgroupMemCollector { }); // --- Swap --- - // Since swap is dependent on the normal memory usage, we couple it together. + // Since swap is dependent on the normal memory usage, we couple it + // together. if let Some(memsw_usage) = read_u64("/sys/fs/cgroup/memory/memory.memsw.usage_in_bytes") { let used_bytes = memsw_usage.saturating_sub(mem_usage); @@ -114,7 +118,8 @@ impl CgroupMemCollector { } } - /// Try and update the memory using cgroup v2 semantics. If successful, returns `true`. + /// Try and update the memory using cgroup v2 semantics. If successful, + /// returns `true`. fn try_update_memory_cgroup_v2(&mut self) -> bool { let mut could_update = false; @@ -186,13 +191,15 @@ fn parse_cpu_quota(cpu_max: String) -> Option { /// Gathers CPU data from cgroup sources. #[derive(Default, Debug)] pub(crate) struct CgroupCpuCollector { - /// A maximum number of CPUs (cores) that can be used, as defined by the cgroup. + /// A maximum number of CPUs (cores) that can be used, as defined by the + /// cgroup. pub cpu_quota: Option, /// Computed average CPU usage percent (only set when a quota is active). pub avg_cpu_percent: Option, - /// The previous CPU microsecond time (usage) and when it was last updated. Used to compute average cgroup CPU usage. + /// The previous CPU microsecond time (usage) and when it was last updated. + /// Used to compute average cgroup CPU usage. prev_cpu: Option<(u64, Instant)>, } @@ -205,7 +212,8 @@ impl CgroupCpuCollector { } } - /// Try to update CPU data using cgroup v1 semantics. Returns `true` on success. + /// Try to update CPU data using cgroup v1 semantics. Returns `true` on + /// success. fn try_update_cpu_cgroup_v1(&mut self) -> bool { let quota_raw: i64 = { let quota_str = match fs::read_to_string("/sys/fs/cgroup/cpu/cpu.cfs_quota_us") { @@ -230,11 +238,13 @@ impl CgroupCpuCollector { } }) } else { - // If it's less than 0 (-1) then it's representing "unlimited" quota (AKA use the full CPU). + // If it's less than 0 (-1) then it's representing "unlimited" quota + // (AKA use the full CPU). None }; - // cpuacct.usage is in nanoseconds; convert to microseconds for consistency with v2 + // cpuacct.usage is in nanoseconds; convert to microseconds for + // consistency with v2 if let Some(usage_nsec) = read_u64("/sys/fs/cgroup/cpuacct/cpuacct.usage") { self.try_compute_avg_and_update(usage_nsec / 1000); } else { @@ -244,7 +254,8 @@ impl CgroupCpuCollector { true } - /// Try to update CPU data using cgroup v2 semantics. Returns `true` on success. + /// Try to update CPU data using cgroup v2 semantics. Returns `true` on + /// success. fn try_update_cpu_cgroup_v2(&mut self) -> bool { let cpu_max = match fs::read_to_string("/sys/fs/cgroup/cpu.max") { Ok(s) => s, @@ -263,9 +274,10 @@ impl CgroupCpuCollector { true } - /// Try and compute average CPU usage based on the current microseconds. Note that this requires _two_ invocations - /// to compute a value, as the first invocation just sets the baseline for the next CPU time and timestamp to - /// compare with. + /// Try and compute average CPU usage based on the current microseconds. + /// Note that this requires _two_ invocations to compute a value, as the + /// first invocation just sets the baseline for the next CPU time and + /// timestamp to compare with. fn try_compute_avg_and_update(&mut self, current_microseconds: u64) { let now = Instant::now(); diff --git a/src/collection/linux/utils.rs b/src/collection/linux/utils.rs index a87cf1a2..63000361 100644 --- a/src/collection/linux/utils.rs +++ b/src/collection/linux/utils.rs @@ -4,7 +4,8 @@ use std::{fs, path::Path}; /// Will return false if the state is not D0/unknown, or if it does not support /// `device/power_state` (e.g. the path does not exist). /// -/// `path` is a path to the device itself (e.g. `/sys/class/hwmon/hwmon1/device`). +/// `path` is a path to the device itself (e.g. +/// `/sys/class/hwmon/hwmon1/device`). #[inline] pub fn is_device_awake(device: &Path) -> bool { // Whether the temperature should *actually* be read during enumeration. @@ -14,12 +15,12 @@ pub fn is_device_awake(device: &Path) -> bool { if power_state.exists() { if let Ok(state) = fs::read_to_string(power_state) { let state = state.trim(); - // The zenpower3 kernel module (incorrectly?) reports "unknown", causing this - // check to fail and temperatures to appear as zero instead of - // having the file not exist. + // The zenpower3 kernel module (incorrectly?) reports "unknown", + // causing this check to fail and temperatures to appear + // as zero instead of having the file not exist. // - // Their self-hosted git instance has disabled sign up, so this bug can't be - // reported either. + // Their self-hosted git instance has disabled sign up, so this bug + // can't be reported either. state == "D0" || state == "unknown" } else { true diff --git a/src/collection/memory/arc.rs b/src/collection/memory/arc.rs index ad4b0cb1..bb2d890e 100644 --- a/src/collection/memory/arc.rs +++ b/src/collection/memory/arc.rs @@ -32,7 +32,8 @@ pub(crate) fn get_arc_usage() -> Option<(MemData, u64)> { // Parse the value, remember it's in bytes! if let Ok(number) = number.parse::() { *to_write = number; - // We only need a few keys, so we can bail early. + // We only need a few keys, so we can bail + // early. zfs_keys_read += 1; if zfs_keys_read == ZFS_KEYS_NEEDED { break; @@ -53,9 +54,15 @@ pub(crate) fn get_arc_usage() -> Option<(MemData, u64)> { sysctl::Ctl::new("kstat.zfs.misc.arcstats.c_max"), sysctl::Ctl::new("kstat.zfs.misc.arcstats.c_min"), ) { - if let (Ok(sysctl::CtlValue::U64(arc)), Ok(sysctl::CtlValue::U64(mem)), Ok(sysctl::CtlValue::U64(min))) = - (mem_arc_value.value(), mem_sys_value.value(), mem_min_value.value()) - { + if let ( + Ok(sysctl::CtlValue::U64(arc)), + Ok(sysctl::CtlValue::U64(mem)), + Ok(sysctl::CtlValue::U64(min)), + ) = ( + mem_arc_value.value(), + mem_sys_value.value(), + mem_min_value.value(), + ) { (mem, arc, min) } else { (0, 0, 0) @@ -64,9 +71,7 @@ pub(crate) fn get_arc_usage() -> Option<(MemData, u64)> { (0, 0, 0) } } - _ => { - (0, 0, 0) - } + _ => (0, 0, 0), } }; diff --git a/src/collection/memory/sysinfo.rs b/src/collection/memory/sysinfo.rs index e7d6e3d9..99b39b4a 100644 --- a/src/collection/memory/sysinfo.rs +++ b/src/collection/memory/sysinfo.rs @@ -14,11 +14,12 @@ fn get_usage(used: u64, total: u64) -> Option { }) } -/// Resolves the total memory to report given an optional cgroup limit and the physical total. +/// Resolves the total memory to report given an optional cgroup limit and the +/// physical total. /// -/// cgroup v1 reports an "unlimited" limit as a very large value, which causes problems if taken -/// literally. This function caps it to the minimum of the cgroup total or the actual total to -/// avoid this problem. +/// cgroup v1 reports an "unlimited" limit as a very large value, which causes +/// problems if taken literally. This function caps it to the minimum of the +/// cgroup total or the actual total to avoid this problem. #[cfg(target_os = "linux")] #[inline] fn resolve_cgroup_total(limit: Option<&CgroupMemLimit>, base_total: u64) -> u64 { @@ -51,9 +52,7 @@ pub(crate) fn get_ram_usage(collector: &DataCollector) -> Option { get_usage(used, total) } - _ => { - get_usage(sys.used_memory(), sys.total_memory()) - } + _ => get_usage(sys.used_memory(), sys.total_memory()), } } @@ -81,9 +80,7 @@ pub(crate) fn get_swap_usage(collector: &DataCollector) -> Option { get_usage(used, total) } - _ => { - get_usage(sys.used_swap(), sys.total_swap()) - } + _ => get_usage(sys.used_swap(), sys.total_swap()), } } diff --git a/src/collection/memory/windows.rs b/src/collection/memory/windows.rs index a0756d29..13697f93 100644 --- a/src/collection/memory/windows.rs +++ b/src/collection/memory/windows.rs @@ -36,8 +36,8 @@ fn get_swap_usage_inner(sys: &System) -> Option { // See https://kennykerr.ca/rust-getting-started/string-tutorial.html let query = w!("\\Paging File(_Total)\\% Usage"); - // SAFETY: Hits a few Windows APIs; this should be safe as we check each step, - // and we clean up at the end. + // SAFETY: Hits a few Windows APIs; this should be safe as we check each + // step, and we clean up at the end. unsafe { let mut query_handle: PDH_HQUERY = zeroed(); let mut counter_handle: PDH_HCOUNTER = zeroed(); @@ -92,8 +92,8 @@ mod tests { let swap_usage = get_swap_usage_inner(&sys); if sys.total_swap() > 0 { - // Not sure if we can guarantee this to always pass on a machine, so I'll just - // print out. + // Not sure if we can guarantee this to always pass on a machine, so + // I'll just print out. println!("swap: {swap_usage:?}"); } else { println!("No swap, skipping."); diff --git a/src/collection/nvidia.rs b/src/collection/nvidia.rs index f8a204b4..a2666f3c 100644 --- a/src/collection/nvidia.rs +++ b/src/collection/nvidia.rs @@ -64,9 +64,10 @@ fn is_gpu_class(class_code: &str) -> bool { class_code.starts_with(PCI_BASE_CLASS_DISPLAY) } -/// Get a list of PCI bus IDs for Linux. This will handle whether the device is awake or not. -/// We do this separately to avoid the possibility of NVML waking up the device at all; -/// this is particularly useful for things like laptops with hybrid graphics (e.g. NVIDIA Optimus). +/// Get a list of PCI bus IDs for Linux. This will handle whether the device is +/// awake or not. We do this separately to avoid the possibility of NVML waking +/// up the device at all; this is particularly useful for things like laptops +/// with hybrid graphics (e.g. NVIDIA Optimus). /// /// Note this is somewhat expensive, so it may be worth caching this result. /// @@ -77,9 +78,10 @@ fn is_gpu_class(class_code: &str) -> bool { /// - #[cfg(target_os = "linux")] fn get_active_pci_bus_ids() -> Vec { - use crate::collection::linux::utils::is_device_awake; use std::fs; + use crate::collection::linux::utils::is_device_awake; + let Ok(entries) = fs::read_dir("/sys/bus/pci/devices") else { return Vec::new(); }; @@ -154,24 +156,38 @@ pub fn get_nvidia_gpu_data(collector: &mut DataCollector) -> Option { use itertools::Either; // Refresh every ~10 seconds. - if let Some((cached_list, cached_time)) = &collector.nvidia_gpu_list_cache && cached_time.elapsed().as_secs() < 10 { - let devices = Either::Left(cached_list.iter().filter_map(|id| nvml.device_by_pci_bus_id(id.as_str()).ok())); + if let Some((cached_list, cached_time)) = &collector.nvidia_gpu_list_cache + && cached_time.elapsed().as_secs() < 10 + { + let devices = Either::Left( + cached_list + .iter() + .filter_map(|id| nvml.device_by_pci_bus_id(id.as_str()).ok()), + ); (devices, cached_list.len()) - } - else { + } else { let pci_bus_ids = get_active_pci_bus_ids(); let num_gpus = pci_bus_ids.len(); - collector.nvidia_gpu_list_cache = Some((pci_bus_ids.clone(), std::time::Instant::now())); + collector.nvidia_gpu_list_cache = + Some((pci_bus_ids.clone(), std::time::Instant::now())); - let devices = Either::Right(pci_bus_ids.into_iter().filter_map(|id| nvml.device_by_pci_bus_id(id).ok())); + let devices = Either::Right( + pci_bus_ids + .into_iter() + .filter_map(|id| nvml.device_by_pci_bus_id(id).ok()), + ); (devices, num_gpus) } - }, + } _ => { - // The fallback behaviour (the old one) is to just list all nvml devices blindly. - // Note this has the risk of waking up sleeping devices. + // The fallback behaviour (the old one) is to just list all nvml + // devices blindly. Note this has the risk of + // waking up sleeping devices. let num_gpus = nvml.device_count().ok()?; - ((0..num_gpus).flat_map(|i| nvml.device_by_index(i)), num_gpus as usize) + ( + (0..num_gpus).flat_map(|i| nvml.device_by_index(i)), + num_gpus as usize, + ) } } }; diff --git a/src/collection/processes.rs b/src/collection/processes.rs index ff7950f3..90fe6c81 100644 --- a/src/collection/processes.rs +++ b/src/collection/processes.rs @@ -172,21 +172,22 @@ impl DataCollector { pub(crate) fn get_processes(&mut self) -> CollectionResult> { cfg_select! { target_os = "linux" => { - let time_diff = self.data.collection_time + let time_diff = self + .data + .collection_time .duration_since(self.last_collection_time) .as_secs(); - linux_process_data( - self, - time_diff, - ) - } - any(target_os = "freebsd", target_os = "macos", target_os = "windows", target_os = "android", target_os = "ios") => { - sysinfo_process_data(self) - } - _ => { - Err(crate::collection::error::CollectionError::Unsupported) + linux_process_data(self, time_diff) } + any( + target_os = "freebsd", + target_os = "macos", + target_os = "windows", + target_os = "android", + target_os = "ios" + ) => sysinfo_process_data(self), + _ => Err(crate::collection::error::CollectionError::Unsupported), } } } @@ -194,52 +195,42 @@ impl DataCollector { /// Pulled from [`ProcessStatus::to_string`] to avoid an alloc. pub(super) fn process_status_str(status: ProcessStatus) -> &'static str { cfg_select! { - target_os = "linux" => { - match status { - ProcessStatus::Idle => "Idle", - ProcessStatus::Run => "Runnable", - ProcessStatus::Sleep => "Sleeping", - ProcessStatus::Stop => "Stopped", - ProcessStatus::Zombie => "Zombie", - ProcessStatus::Tracing => "Tracing", - ProcessStatus::Dead => "Dead", - ProcessStatus::Wakekill => "Wakekill", - ProcessStatus::Waking => "Waking", - ProcessStatus::Parked => "Parked", - ProcessStatus::UninterruptibleDiskSleep => "UninterruptibleDiskSleep", - _ => "Unknown", - } - } - target_os = "windows" => { - match status { - ProcessStatus::Run => "Runnable", - _ => "Unknown", - } - } - target_os = "macos" => { - match status { - ProcessStatus::Idle => "Idle", - ProcessStatus::Run => "Runnable", - ProcessStatus::Sleep => "Sleeping", - ProcessStatus::Stop => "Stopped", - ProcessStatus::Zombie => "Zombie", - _ => "Unknown", - } - } - target_os = "freebsd" => { - match status { - ProcessStatus::Idle => "Idle", - ProcessStatus::Run => "Runnable", - ProcessStatus::Sleep => "Sleeping", - ProcessStatus::Stop => "Stopped", - ProcessStatus::Zombie => "Zombie", - ProcessStatus::Dead => "Dead", - ProcessStatus::LockBlocked => "LockBlocked", - _ => "Unknown", - } - } - _ => { - "Unknown" - } + target_os = "linux" => match status { + ProcessStatus::Idle => "Idle", + ProcessStatus::Run => "Runnable", + ProcessStatus::Sleep => "Sleeping", + ProcessStatus::Stop => "Stopped", + ProcessStatus::Zombie => "Zombie", + ProcessStatus::Tracing => "Tracing", + ProcessStatus::Dead => "Dead", + ProcessStatus::Wakekill => "Wakekill", + ProcessStatus::Waking => "Waking", + ProcessStatus::Parked => "Parked", + ProcessStatus::UninterruptibleDiskSleep => "UninterruptibleDiskSleep", + _ => "Unknown", + }, + target_os = "windows" => match status { + ProcessStatus::Run => "Runnable", + _ => "Unknown", + }, + target_os = "macos" => match status { + ProcessStatus::Idle => "Idle", + ProcessStatus::Run => "Runnable", + ProcessStatus::Sleep => "Sleeping", + ProcessStatus::Stop => "Stopped", + ProcessStatus::Zombie => "Zombie", + _ => "Unknown", + }, + target_os = "freebsd" => match status { + ProcessStatus::Idle => "Idle", + ProcessStatus::Run => "Runnable", + ProcessStatus::Sleep => "Sleeping", + ProcessStatus::Stop => "Stopped", + ProcessStatus::Zombie => "Zombie", + ProcessStatus::Dead => "Dead", + ProcessStatus::LockBlocked => "LockBlocked", + _ => "Unknown", + }, + _ => "Unknown", } } diff --git a/src/collection/processes/linux/mod.rs b/src/collection/processes/linux/mod.rs index ce107125..ae84ac80 100644 --- a/src/collection/processes/linux/mod.rs +++ b/src/collection/processes/linux/mod.rs @@ -222,19 +222,21 @@ fn read_proc( (concat_string!("[", comm, "]"), comm) } else { // If the comm fits then we'll default to whatever is set. - // If it doesn't, we need to do some magic to determine what it's - // supposed to be. + // If it doesn't, we need to do some magic to determine what + // it's supposed to be. - // TODO: We might want to re-evaluate if we want to do it like this, - // as it turns out I was dumb and sometimes comm != process name... + // TODO: We might want to re-evaluate if we want to do it like + // this, as it turns out I was dumb and + // sometimes comm != process name... // // What we should do is store: - // - basename (what we're kinda doing now, except we're gating on comm length) + // - basename (what we're kinda doing now, except we're gating + // on comm length) // - command (full thing) // - comm (as a separate thing) // - // Stuff like htop also offers the option to "highlight" basename and comm in - // command. Might be neat? + // Stuff like htop also offers the option to "highlight" + // basename and comm in command. Might be neat? let name = if comm.len() >= MAX_STAT_NAME_LEN { binary_name_from_cmdline(&cmdline) } else { @@ -249,8 +251,8 @@ fn read_proc( }; // We have moved command processing here. - // SAFETY: We are only replacing a single char (NUL) with another single char - // (space). + // SAFETY: We are only replacing a single char (NUL) with another single + // char (space). let mut command = command; let buf_mut = unsafe { command.as_mut_vec() }; @@ -389,13 +391,14 @@ pub(crate) fn linux_process_data( .cpu_quota .unwrap_or_else(|| collector.sys.system.cpus().len() as f64); - // Note we *divide* here because the later calculation divides `cpu_usage` - in - // effect, multiplying over the number of cores. + // Note we *divide* here because the later calculation divides + // `cpu_usage` - in effect, multiplying over the number of + // cores. cpu_usage /= num_processors; } - // TODO: Could maybe use a double buffer hashmap to avoid allocating this each - // time? e.g. we swap which is prev and which is new. + // TODO: Could maybe use a double buffer hashmap to avoid allocating this + // each time? e.g. we swap which is prev and which is new. let mut seen_pids: HashSet = HashSet::default(); // Note this will only return PIDs of _processes_, not threads. You can get @@ -497,8 +500,8 @@ pub(crate) fn linux_process_data( prev_process_details.shrink_to_fit(); } - // TODO: This might be more efficient to just separate threads into their own - // list, but for now this works so it fits with existing code. + // TODO: This might be more efficient to just separate threads into their + // own list, but for now this works so it fits with existing code. Ok(process_vector) } diff --git a/src/collection/processes/linux/process.rs b/src/collection/processes/linux/process.rs index 615f9a80..410628a9 100644 --- a/src/collection/processes/linux/process.rs +++ b/src/collection/processes/linux/process.rs @@ -76,24 +76,26 @@ impl Stat { /// `/proc//stat`. For documentation, see /// [here](https://manpages.ubuntu.com/manpages/noble/man5/proc_pid_stat.5.html) as a reference. fn from_file(mut f: File, buffer: &mut String) -> anyhow::Result { - // Since this is just one line, we can read it all at once. However, since it - // (technically) might have non-utf8 characters, we can't just use - // read_to_string. + // Since this is just one line, we can read it all at once. However, + // since it (technically) might have non-utf8 characters, we + // can't just use read_to_string. f.read_to_end(unsafe { buffer.as_mut_vec() })?; // TODO: Is this needed? let line = buffer.trim(); - // Comm is represented by a string in parentheses (e.g. `(foo)`, `((bar))`). - // To handle that second case, we need to find the "last" closing parentheses. + // Comm is represented by a string in parentheses (e.g. `(foo)`, + // `((bar))`). To handle that second case, we need to find the + // "last" closing parentheses. let (comm, rest) = { let start_paren = line .find('(') .ok_or_else(|| anyhow!("start paren missing"))?; - // So, we _could_ try and be smart and only parse a limited slice of the string - however, - // there appears to be no ABI guarantees of comm length anymore, so we just take the hit and do an rsplit - // over the full string. + // So, we _could_ try and be smart and only parse a limited slice of + // the string - however, there appears to be no ABI + // guarantees of comm length anymore, so we just take the hit and do + // an rsplit over the full string. // // Sources/discussion: // - https://man.archlinux.org/man/proc_pid_stat.5.en @@ -189,8 +191,8 @@ impl Io { let mut read_bytes = 0; let mut write_bytes = 0; - // This saves us from doing a string allocation on each iteration compared to - // `lines()`. + // This saves us from doing a string allocation on each iteration + // compared to `lines()`. while let Ok(bytes) = reader.read_line(buffer) { if bytes > 0 { if buffer.is_empty() { @@ -225,7 +227,8 @@ impl Io { } } - // Quick short circuit if we have already read all the required fields. + // Quick short circuit if we have already read all the required + // fields. if read_fields == NUM_FIELDS { break; } @@ -307,8 +310,8 @@ impl Process { let mut root = pid_path; - // NB: Whenever you add a new stat, make sure to pop the root and clear the - // buffer! + // NB: Whenever you add a new stat, make sure to pop the root and clear + // the buffer! // Stat is pretty long, do this first to pre-allocate up-front. let stat = @@ -316,8 +319,8 @@ impl Process { reset(&mut root, buffer); let cmdline = if cmdline(&mut root, &pid_dir, buffer).is_ok() { - // The clone will give a string with the capacity of the length of buffer, don't - // worry. + // The clone will give a string with the capacity of the length of + // buffer, don't worry. Some(buffer.clone()) } else { None diff --git a/src/collection/processes/macos/sysctl_bindings.rs b/src/collection/processes/macos/sysctl_bindings.rs index fce86e4b..5eef3678 100644 --- a/src/collection/processes/macos/sysctl_bindings.rs +++ b/src/collection/processes/macos/sysctl_bindings.rs @@ -288,8 +288,8 @@ pub(crate) fn kinfo_process(pid: Pid) -> Result { bail!("failed to get process for pid {pid}"); } - // SAFETY: info is initialized if result succeeded and returned a non-negative - // result. If sysctl failed, it returns -1 with errno set. + // SAFETY: info is initialized if result succeeded and returned a + // non-negative result. If sysctl failed, it returns -1 with errno set. // // Source: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysctl.3.html unsafe { Ok(info.assume_init()) } diff --git a/src/collection/processes/unix.rs b/src/collection/processes/unix.rs index 10084407..9d92a2bd 100644 --- a/src/collection/processes/unix.rs +++ b/src/collection/processes/unix.rs @@ -10,11 +10,11 @@ cfg_select! { pub(crate) use process_ext::*; use super::ProcessHarvest; + use crate::collection::{DataCollector, error::CollectionResult, processes::*}; - use crate::collection::{DataCollector, processes::*}; - use crate::collection::error::CollectionResult; - - pub fn sysinfo_process_data(collector: &mut DataCollector) -> CollectionResult> { + pub fn sysinfo_process_data( + collector: &mut DataCollector, + ) -> CollectionResult> { let sys = &collector.sys.system; let use_current_cpu_total = collector.use_current_cpu_total; let unnormalized_cpu = collector.unnormalized_cpu; @@ -22,18 +22,29 @@ cfg_select! { let user_table = &mut collector.user_table; cfg_select! { - target_os = "macos" => { - MacOSProcessExt::sysinfo_process_data(sys, use_current_cpu_total, unnormalized_cpu, total_memory, user_table) - } - target_os = "freebsd" => { - FreeBSDProcessExt::sysinfo_process_data(sys, use_current_cpu_total, unnormalized_cpu, total_memory, user_table) - } - _ => { - GenericProcessExt::sysinfo_process_data(sys, use_current_cpu_total, unnormalized_cpu, total_memory, user_table) - } + target_os = "macos" => MacOSProcessExt::sysinfo_process_data( + sys, + use_current_cpu_total, + unnormalized_cpu, + total_memory, + user_table, + ), + target_os = "freebsd" => FreeBSDProcessExt::sysinfo_process_data( + sys, + use_current_cpu_total, + unnormalized_cpu, + total_memory, + user_table, + ), + _ => GenericProcessExt::sysinfo_process_data( + sys, + use_current_cpu_total, + unnormalized_cpu, + total_memory, + user_table, + ), } } - } _ => {} } diff --git a/src/collection/processes/unix/process_ext.rs b/src/collection/processes/unix/process_ext.rs index c3fb438a..2f6925ee 100644 --- a/src/collection/processes/unix/process_ext.rs +++ b/src/collection/processes/unix/process_ext.rs @@ -17,15 +17,9 @@ fn get_nice(pid: Pid) -> i32 { // SAFETY: getpriority takes no user pointers; pid is passed as a value // and errors are reported via the return value. cfg_select! { - target_os = "freebsd" => { - unsafe { libc::getpriority(libc::PRIO_PROCESS, pid) } - } - target_os = "macos" => { - unsafe { libc::getpriority(libc::PRIO_PROCESS, pid as u32) } - } - _ => { - 0 - } + target_os = "freebsd" => unsafe { libc::getpriority(libc::PRIO_PROCESS, pid) }, + target_os = "macos" => unsafe { libc::getpriority(libc::PRIO_PROCESS, pid as u32) }, + _ => 0, } } @@ -39,10 +33,16 @@ fn get_priority(pid: Pid) -> i32 { } } target_os = "freebsd" => { - use libc::{c_int, c_void}; use std::{mem, ptr}; - let mib = [libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_PID, pid as c_int]; + use libc::{c_int, c_void}; + + let mib = [ + libc::CTL_KERN, + libc::KERN_PROC, + libc::KERN_PROC_PID, + pid as c_int, + ]; let mut kp: libc::kinfo_proc = unsafe { mem::zeroed() }; let mut size = mem::size_of::(); @@ -61,11 +61,13 @@ fn get_priority(pid: Pid) -> i32 { ) }; - if ret == 0 { kp.ki_pri.pri_level as i32 } else { 0 } - } - _ => { - 0 + if ret == 0 { + kp.ki_pri.pri_level as i32 + } else { + 0 + } } + _ => 0, } } @@ -230,12 +232,16 @@ fn convert_process_status_to_char(status: ProcessStatus) -> char { ProcessStatus::Sleep => SSLEEP, ProcessStatus::Stop => SSTOP, ProcessStatus::Zombie => SZOMB, - _ => '?' + _ => '?', } } target_os = "freebsd" => { const fn assert_u8(val: libc::c_char) -> u8 { - if val < 0 { panic!("there was an invalid i8 constant that is supposed to be a char") } else { val as u8 } + if val < 0 { + panic!("there was an invalid i8 constant that is supposed to be a char") + } else { + val as u8 + } } const SIDL: u8 = assert_u8(libc::SIDL); @@ -254,11 +260,9 @@ fn convert_process_status_to_char(status: ProcessStatus) -> char { ProcessStatus::Zombie => SZOMB as char, ProcessStatus::Dead => SWAIT as char, ProcessStatus::LockBlocked => SLOCK as char, - _ => '?' + _ => '?', } } - _ => { - '?' - } + _ => '?', } } diff --git a/src/collection/processes/unix/user_table.rs b/src/collection/processes/unix/user_table.rs index 6fee461e..331b1c9a 100644 --- a/src/collection/processes/unix/user_table.rs +++ b/src/collection/processes/unix/user_table.rs @@ -16,8 +16,8 @@ impl UserTable { if let Some(user) = self.uid_user_mapping.get(&uid) { Ok(user.clone()) } else { - // SAFETY: getpwuid returns a null pointer if no passwd entry is found for the - // uid which we check. + // SAFETY: getpwuid returns a null pointer if no passwd entry is + // found for the uid which we check. let passwd = unsafe { libc::getpwuid(uid) }; if passwd.is_null() { diff --git a/src/collection/processes/windows.rs b/src/collection/processes/windows.rs index ba2ba126..5318da96 100644 --- a/src/collection/processes/windows.rs +++ b/src/collection/processes/windows.rs @@ -16,8 +16,8 @@ use crate::collection::{DataCollector, error::CollectionResult}; /// for more information on the core Windows API being called and the meaning of /// the priorities, as well as the access rights needed. fn get_priority(pid: u32) -> anyhow::Result { - // SAFETY: We check validity of each step and bail on errors. We also close the - // handle. + // SAFETY: We check validity of each step and bail on errors. We also close + // the handle. unsafe { let process_handle: HANDLE = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid)?; if process_handle.is_invalid() { @@ -146,9 +146,10 @@ pub fn sysinfo_process_data( .user_id() .and_then(|uid| users.get_user_by_id(uid).map(|user| user.name().into())), time: if process.start_time() == 0 { - // Workaround for sysinfo occasionally returning a start time equal to UNIX - // epoch, giving a run time in the range of 50+ years. We just - // return a time of zero in this case for simplicity. + // Workaround for sysinfo occasionally returning a start time + // equal to UNIX epoch, giving a run time in the + // range of 50+ years. We just return a time of + // zero in this case for simplicity. // // TODO: Maybe return an option instead? Duration::ZERO diff --git a/src/collection/temperature/linux.rs b/src/collection/temperature/linux.rs index 629d33d7..24b59e55 100644 --- a/src/collection/temperature/linux.rs +++ b/src/collection/temperature/linux.rs @@ -37,9 +37,10 @@ fn get_hwmon_candidates() -> (HashSet, usize) { for entry in read_dir.flatten() { let mut path = entry.path(); - // hwmon includes many sensors, we only want ones with at least one temperature - // sensor Reading this file will wake the device, but we're only - // checking existence, so it should be fine. + // hwmon includes many sensors, we only want ones with at least one + // temperature sensor Reading this file will wake the + // device, but we're only checking existence, so it + // should be fine. if !path.join("temp1_input").exists() { // Note we also check for a `device` subdirectory (e.g. // `/sys/class/hwmon/hwmon*/device/`). This is needed for @@ -48,7 +49,8 @@ fn get_hwmon_candidates() -> (HashSet, usize) { // - https://github.com/giampaolo/psutil/issues/971 // - https://github.com/giampaolo/psutil/blob/642438375e685403b4cd60b0c0e25b80dd5a813d/psutil/_pslinux.py#L1316 // - // If it does match, then add the `device/` directory to the path. + // If it does match, then add the `device/` directory to the + // path. if path.join("device/temp1_input").exists() { path.push("device"); } @@ -69,8 +71,9 @@ fn get_hwmon_candidates() -> (HashSet, usize) { let path = entry.path(); if path.join("temp1_input").exists() { - // It's possible that there are dupes (represented by symlinks) - the - // easy way is to just substitute the parent + // It's possible that there are dupes (represented by + // symlinks) - the easy way is + // to just substitute the parent // directory and check if the hwmon // variant exists already in a set. // @@ -212,8 +215,8 @@ fn hwmon_temperatures(filter: &Option, graph_filter: &Option) -> // `/sys/class/hwmon/hwmon*/device/power_state` == `D3cold` will // wake the device up, and will block until it initializes. // - // Reading the `hwmon*/device/power_state` or `hwmon*/temp*_label` properties - // will not wake the device, and thus not block, + // Reading the `hwmon*/device/power_state` or `hwmon*/temp*_label` + // properties will not wake the device, and thus not block, // and meaning no sensors have to be hidden depending on `power_state` // // It would probably be more ideal to use a proper async runtime; this would @@ -247,21 +250,25 @@ fn hwmon_temperatures(filter: &Option, graph_filter: &Option) -> let sensor_label_path = file_path.join(name.replace("input", "label")); let sensor_label = read_to_string_lossy(sensor_label_path); - // Do some messing around to get a more sensible name for sensors: + // Do some messing around to get a more sensible name for + // sensors: // - For GPUs, this will use the kernel device name, ex `card0` - // - For nvme drives, this will also use the kernel name, ex `nvme0`. This is - // found differently than for GPUs - // - For whatever acpitz is, on my machine this is now `thermal_zone0`. - // - For k10temp, this will still be k10temp, but it has to be handled special. + // - For nvme drives, this will also use the kernel name, ex + // `nvme0`. This is found differently than for GPUs + // - For whatever acpitz is, on my machine this is now + // `thermal_zone0`. + // - For k10temp, this will still be k10temp, but it has to be + // handled special. let hwmon_name = { let device = file_path.join("device"); - // This will exist for GPUs but not others, this is how we find their kernel - // name. + // This will exist for GPUs but not others, this is how we + // find their kernel name. let drm = device.join("drm"); if drm.exists() { - // This should never actually be empty. If it is though, we'll fall back to - // the sensor name later on. + // This should never actually be empty. If it is though, + // we'll fall back to the sensor + // name later on. #[cfg(feature = "gpu")] { @@ -295,11 +302,13 @@ fn hwmon_temperatures(filter: &Option, graph_filter: &Option) -> } } } else { - // This little mess is to account for stuff like k10temp. This is needed + // This little mess is to account for stuff like + // k10temp. This is needed // because the `device` symlink points to `nvme*` // for nvme drives, but to PCI buses for anything - // else. If the first character is alphabetic, it's an actual name like - // k10temp or nvme0, not a PCI bus. + // else. If the first character is alphabetic, it's an + // actual name like k10temp or + // nvme0, not a PCI bus. fs::read_link(device).ok().and_then(|link| { let link = link.file_name().and_then(|f| f.to_str()).map(|s| s.trim()); @@ -317,8 +326,9 @@ fn hwmon_temperatures(filter: &Option, graph_filter: &Option) -> let name = finalize_name(hwmon_name, sensor_label, &sensor_name, &mut seen_names); - // TODO: It's possible we may want to move the filter check further up to avoid - // probing hwmon if not needed? + // TODO: It's possible we may want to move the filter check + // further up to avoid probing hwmon if not + // needed? if (Filter::optional_should_keep(filter, &name) || Filter::optional_should_keep(graph_filter, &name)) && let Ok(temp_celsius) = parse_temp(&temp_path) diff --git a/src/components/time_series.rs b/src/components/time_series.rs index ae873595..5d846676 100644 --- a/src/components/time_series.rs +++ b/src/components/time_series.rs @@ -17,7 +17,8 @@ use crate::canvas::components::time_series::{ const STALE_MIN_MILLISECONDS: u64 = Duration::from_secs(30).as_millis() as u64; -/// Configuration values for a [`TimeseriesState`], sourced from [`crate::app::AppConfigFields`]. +/// Configuration values for a [`TimeseriesState`], sourced from +/// [`crate::app::AppConfigFields`]. #[derive(Copy, Clone, Debug)] pub struct TimeseriesConfig { pub time_interval: u64, @@ -34,7 +35,8 @@ pub struct TimeseriesState { } impl TimeseriesState { - /// Create a new [`TimeseriesState`] using the given config and `autohide_timer` setting. + /// Create a new [`TimeseriesState`] using the given config and + /// `autohide_timer` setting. pub fn new(config: TimeseriesConfig, autohide_timer: Option) -> Self { Self { current_display_time: config.default_time_value, diff --git a/src/components/time_series/auto_y.rs b/src/components/time_series/auto_y.rs index d2449d09..53815e2c 100644 --- a/src/components/time_series/auto_y.rs +++ b/src/components/time_series/auto_y.rs @@ -47,13 +47,15 @@ impl GraphHeightCache { let visible_left_bound = match last_time.checked_sub(visible_duration) { Some(v) => v, None => { - // On some systems (like Windows) it can be possible that the - // current display time causes subtraction to fail if, for example, - // the uptime of the system is too low and current_display_time is - // too high. See https://github.com/ClementTsang/bottom/issues/1825. + // On some systems (like Windows) it can be possible that + // the current display time causes + // subtraction to fail if, for example, + // the uptime of the system is too low and + // current_display_time is too high. See https://github.com/ClementTsang/bottom/issues/1825. // - // As such, we instead take the oldest visible time. This is a bit - // inefficient, but since it should only happen rarely, it's fine. + // As such, we instead take the oldest visible time. This is + // a bit inefficient, but since it + // should only happen rarely, it's fine. times .iter() .take_while(|t| last_time.duration_since(**t) < visible_duration) @@ -90,7 +92,8 @@ impl GraphHeightCache { } } -/// A time series graph that automatically adjusts the y-axis based on the data provided. +/// A time series graph that automatically adjusts the y-axis based on the data +/// provided. pub struct AutoYAxisTimeGraph { state: TimeseriesState, height_cache: GraphHeightCache, diff --git a/src/constants.rs b/src/constants.rs index e795d97c..3ed9f5f4 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -766,7 +766,8 @@ mod test { #[test] fn help_menu_matches_entry_len() { - // Subtract 2 to account for the extra newline + search instructions at the bottom. + // Subtract 2 to account for the extra newline + search instructions at + // the bottom. const HELP_CONTENTS_TEXT_LEN: usize = HELP_CONTENTS_TEXT.len() - 2; assert_eq!( @@ -800,8 +801,8 @@ mod test { .unwrap() .replace_all(CONFIG_TEXT, "$1"); - // Then, trim off anything that has more than 2 spaces + alphabetical character - // or '[' following a "#". + // Then, trim off anything that has more than 2 spaces + alphabetical + // character or '[' following a "#". let default_config = Regex::new(r"(?m)^#(\s\s+)([a-zA-Z\[])") .unwrap() .replace_all(&default_config, "$2"); diff --git a/src/lib.rs b/src/lib.rs index 55d16f13..763a4824 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,9 +136,9 @@ fn panic_hook(panic_info: &PanicHookInfo<'_>) { println!("thread '' panicked at '{msg}', {panic_info}\n\r{backtrace}") } - // TODO: Might be cleaner in the future to use a cancellation token, but that - // causes some fun issues with lifetimes; for now if it panics then shut - // down the main program entirely ASAP. + // TODO: Might be cleaner in the future to use a cancellation token, but + // that causes some fun issues with lifetimes; for now if it panics then + // shut down the main program entirely ASAP. std::process::exit(1); } @@ -166,9 +166,10 @@ fn create_input_thread( { match event { Event::Resize(_, _) => { - // TODO: Might want to debounce this in the future, or take into - // account the actual resize values. - // Maybe we want to keep the current implementation in case the + // TODO: Might want to debounce this in the future, or + // take into account the actual + // resize values. Maybe we want + // to keep the current implementation in case the // resize event might not fire... // not sure. @@ -182,8 +183,8 @@ fn create_input_thread( } } Event::Key(key) if !keys_disabled && key.kind == KeyEventKind::Press => { - // For now, we only care about key down events. This may change in - // the future. + // For now, we only care about key down events. This may + // change in the future. if sender.send(BottomEvent::KeyInput(key)).is_err() { break; } @@ -244,8 +245,8 @@ fn create_collection_thread( data_collector.update_data(); data_collector.data = Data::default(); - // Tiny sleep I guess? To go between the first update above and the first update - // in the loop. + // Tiny sleep I guess? To go between the first update above and the + // first update in the loop. std::thread::sleep(Duration::from_millis(5)); loop { @@ -371,8 +372,9 @@ pub fn start_bottom(enable_error_hook: &mut bool) -> anyhow::Result<()> { let mut terminal = Terminal::new(CrosstermBackend::new(stdout_val))?; - // This may fail in some environments, like tests, since it may fail to get the cursor position. - // In that case, fall back to just manually clearing it with backend. + // This may fail in some environments, like tests, since it may fail to get + // the cursor position. In that case, fall back to just manually + // clearing it with backend. if terminal.clear().is_err() { terminal.backend_mut().clear()?; } @@ -422,8 +424,9 @@ pub fn start_bottom(enable_error_hook: &mut bool) -> anyhow::Result<()> { BottomEvent::Update(data) => { app.data_store.eat_data(data, &app.app_config_fields); - // This thing is required as otherwise, some widgets can't draw correctly w/o - // some data (or they need to be re-drawn). + // This thing is required as otherwise, some widgets can't + // draw correctly w/o some data (or they + // need to be re-drawn). if first_run { first_run = false; app.is_force_redraw = true; diff --git a/src/options.rs b/src/options.rs index 7c1b69d6..be9d90fa 100644 --- a/src/options.rs +++ b/src/options.rs @@ -39,7 +39,8 @@ use crate::{ widgets::*, }; -/// Macro to check whether a flag is enabled, either as an arg or in the config file. +/// Macro to check whether a flag is enabled, either as an arg or in the config +/// file. macro_rules! is_flag_enabled { ($flag_name:ident, $arg:expr, $config:expr) => { if $arg.$flag_name { @@ -77,7 +78,8 @@ macro_rules! is_flag_enabled_in { }; } -/// A version of [`is_flag_enabled`] which should be used to deprecate old config flags. +/// A version of [`is_flag_enabled`] which should be used to deprecate old +/// config flags. macro_rules! enabled_option_with_deprecated { ($arg:expr, $config:expr, $section:ident . $field:ident, $flags:ident . $deprecated_flag:ident $(,)?) => { if $arg { @@ -117,7 +119,8 @@ macro_rules! enabled_option_with_deprecated { }; } -/// Get the value of a field for a specific section in the config file if set. If not set, the default is used. +/// Get the value of a field for a specific section in the config file if set. +/// If not set, the default is used. macro_rules! config_or_default { ($config:expr, $section:ident . $field:ident) => { $config @@ -128,8 +131,8 @@ macro_rules! config_or_default { }; } -/// Get the value of a field for a specific section in the config file if set. If not set, -/// the provided default is used. +/// Get the value of a field for a specific section in the config file if set. +/// If not set, the provided default is used. macro_rules! config_or { ($config:expr, $section:ident . $field:ident, $default:expr) => { $config @@ -165,9 +168,10 @@ fn get_config_path(override_config_path: Option<&Path>) -> Option { if let Ok(res) = old_home_path.try_exists() && res { - // We used to create it at `/DEFAULT_CONFIG_FILE_PATH`, but changed it - // to be more correct later. However, for legacy reasons, if it already exists, - // use the old one. + // We used to create it at `/DEFAULT_CONFIG_FILE_PATH`, but + // changed it to be more correct later. However, for + // legacy reasons, if it already exists, use the old + // one. return Some(old_home_path); } } @@ -181,9 +185,9 @@ fn get_config_path(override_config_path: Option<&Path>) -> Option { && let Ok(xdg_config_path) = std::env::var("XDG_CONFIG_HOME") && !xdg_config_path.is_empty() { - // If XDG_CONFIG_HOME exists and is non-empty, _but_ we previously used the - // Library-based path for a config and it exists, then use that - // instead for backwards-compatibility. + // If XDG_CONFIG_HOME exists and is non-empty, _but_ we previously used + // the Library-based path for a config and it exists, then use + // that instead for backwards-compatibility. if let Some(old_macos_path) = &config_path && let Ok(res) = old_macos_path.try_exists() && res @@ -257,11 +261,11 @@ pub(crate) fn get_or_create_config(config_path: Option<&Path>) -> anyhow::Result } } None => { - // If we somehow don't have any config path, then just assume the default config - // but don't write to any file. + // If we somehow don't have any config path, then just assume the + // default config but don't write to any file. // - // TODO: For now, just print a message to stderr indicating this. In the future, - // probably show in-app (too). + // TODO: For now, just print a message to stderr indicating this. In + // the future, probably show in-app (too). eprintln!( "Note: bottom couldn't find a location to create or read a config file, so \ @@ -395,7 +399,8 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL let network_unit_type = get_network_unit_type(args, config); let network_scale_type = get_network_scale_type(args, config); // Use + update this again after deprecation - // let network_use_binary_prefix = is_flag_enabled!(network_use_binary_prefix, args.network, config); + // let network_use_binary_prefix = + // is_flag_enabled!(network_use_binary_prefix, args.network, config); let network_use_binary_prefix = enabled_option_with_deprecated!( args.network.network_use_binary_prefix, config, @@ -998,7 +1003,8 @@ fn deprecated_warning(deprecated_field: &str, new_field: &str) { ); } -/// Mark a config option field as deprecated, and what to use instead with an alias. +/// Mark a config option field as deprecated, and what to use instead with an +/// alias. #[inline] fn deprecated_warning_with_alias(deprecated_field: &str, new_field: &str, alias: &str) { eprintln!( @@ -1151,8 +1157,8 @@ fn get_default_widget_and_count( #[cfg(feature = "battery")] fn get_use_battery(args: &BottomArgs, config: &Config) -> bool { - // TODO: Move this so it's dynamic in the app itself and automatically hide if - // there are no batteries? + // TODO: Move this so it's dynamic in the app itself and automatically hide + // if there are no batteries? if let Ok(battery_manager) = Manager::new() && let Ok(batteries) = battery_manager.batteries() && batteries.count() == 0 @@ -1348,7 +1354,8 @@ fn parse_legend_position( } else if let Some(s) = cfg { parse_position_or_err(s, setting, OptionError::invalid_config_value) } else if let Some((s, name)) = deprecated_cfg { - // Remove the deprecated args/code paths and copy back to the function above later. + // Remove the deprecated args/code paths and copy back to the function + // above later. if let Some(alias) = alias { deprecated_warning_with_alias(name, setting, alias); } else { @@ -1655,17 +1662,17 @@ mod test { super::init_app(args, config).unwrap().0 } - // TODO: There's probably a better way to create clap options AND unify together - // to avoid the possibility of typos/mixing up. Use proc macros to unify on - // one struct? + // TODO: There's probably a better way to create clap options AND unify + // together to avoid the possibility of typos/mixing up. Use proc macros + // to unify on one struct? #[test] fn verify_cli_options_build() { let app = crate::args::build_cmd(); let default_app = create_app(BottomArgs::parse_from(["btm"])); - // Skip battery since it's tricky to test depending on the platform/features - // we're testing with. + // Skip battery since it's tricky to test depending on the + // platform/features we're testing with. let skip = ["help", "version", "celsius", "battery", "generate_schema"]; for arg in app.get_arguments().collect::>() { @@ -1710,8 +1717,8 @@ mod test { use super::{DEFAULT_CONFIG_FILE_LOCATION, get_config_path}; // Case three: no previous config, no XDG var. - // SAFETY: This is fine, this is just a test, and no other test affects env - // vars. + // SAFETY: This is fine, this is just a test, and no other test affects + // env vars. unsafe { std::env::remove_var("XDG_CONFIG_HOME"); } @@ -1729,8 +1736,8 @@ mod test { } // Case two: no previous config, XDG var exists. - // SAFETY: This is fine, this is just a test, and no other test affects env - // vars. + // SAFETY: This is fine, this is just a test, and no other test affects + // env vars. unsafe { std::env::set_var("XDG_CONFIG_HOME", "/tmp"); } diff --git a/src/options/config/disk.rs b/src/options/config/disk.rs index 2bfb0827..b2e095a7 100644 --- a/src/options/config/disk.rs +++ b/src/options/config/disk.rs @@ -14,7 +14,8 @@ pub(crate) struct DiskConfig { /// A filter over the mount names. pub(crate) mount_filter: Option, - /// Whether to include block devices that aren't currently mounted (currently Linux only). Defaults to false. + /// Whether to include block devices that aren't currently mounted + /// (currently Linux only). Defaults to false. pub(crate) include_unmounted: Option, /// A list of disk widget columns. @@ -62,7 +63,8 @@ mod test { toml_edit::de::from_str::(config).expect_err("Should error out!"); } - /// Test that disk enum variants that are advertised in the schema are valid. + /// Test that disk enum variants that are advertised in the schema are + /// valid. #[cfg(feature = "generate_schema")] #[test] fn ensure_disk_column_schema_is_accepted() { diff --git a/src/options/config/disk_io_graph.rs b/src/options/config/disk_io_graph.rs index eecbe141..609eeff2 100644 --- a/src/options/config/disk_io_graph.rs +++ b/src/options/config/disk_io_graph.rs @@ -25,7 +25,8 @@ pub(crate) struct DiskIoGraphConfig { /// Whether to show the write rate line. Defaults to true. pub(crate) show_write: Option, - /// Whether to label legend entries by device name or mount point. Defaults to disk name. + /// Whether to label legend entries by device name or mount point. Defaults + /// to disk name. pub(crate) legend: Option, /// Whether to use a logarithmic scale on the y-axis. Defaults to false. @@ -37,6 +38,7 @@ pub(crate) struct DiskIoGraphConfig { /// An optional list of device names to include or exclude. pub(crate) name_filter: Option, - /// Whether to include block devices that aren't currently mounted (currently Linux only). Defaults to false. + /// Whether to include block devices that aren't currently mounted + /// (currently Linux only). Defaults to false. pub(crate) include_unmounted: Option, } diff --git a/src/options/config/layout.rs b/src/options/config/layout.rs index 573d2004..af64e0dc 100644 --- a/src/options/config/layout.rs +++ b/src/options/config/layout.rs @@ -353,7 +353,8 @@ mod test { Some(3) ); - // Test disk -> processes, processes -> process sort, process sort -> network + // Test disk -> processes, processes -> process sort, process sort -> + // network assert_eq!( ret_bottom_layout.rows[1].children[1].children[1].children[0].down_neighbour, Some(7) diff --git a/src/options/config/memory_graph.rs b/src/options/config/memory_graph.rs index 2a6c8216..6a414659 100644 --- a/src/options/config/memory_graph.rs +++ b/src/options/config/memory_graph.rs @@ -12,7 +12,8 @@ pub struct MemoryGraphConfig { /// Where to place the legend for the memory chart widget. pub(crate) legend_position: Option, - /// Whether to collect and display cache and buffer memory. Not available on Windows. + /// Whether to collect and display cache and buffer memory. Not available on + /// Windows. #[cfg_attr(target_os = "windows", allow(dead_code))] pub(crate) cache_memory: Option, diff --git a/src/options/config/network_graph.rs b/src/options/config/network_graph.rs index aa297acf..a12e961e 100644 --- a/src/options/config/network_graph.rs +++ b/src/options/config/network_graph.rs @@ -21,14 +21,16 @@ pub(crate) struct NetworkGraphConfig { /// Displays the network widget using bytes. Defaults to bits. pub(crate) use_bytes: Option, - /// Displays the network widget with a log scale. Defaults to a non-log scale. + /// Displays the network widget with a log scale. Defaults to a non-log + /// scale. pub(crate) use_log: Option, - /// Displays the network widget with a binary prefix (e.g. kibibits) rather than a decimal - /// prefix (e.g. kilobits). Defaults to decimal prefixes. + /// Displays the network widget with a binary prefix (e.g. kibibits) rather + /// than a decimal prefix (e.g. kilobits). Defaults to decimal prefixes. pub(crate) use_binary_prefix: Option, - /// Zeroes out the total network usage ("All") counters so it shows the total usage - /// since the app is started, rather than the total usage since boot. + /// Zeroes out the total network usage ("All") counters so it shows the + /// total usage since the app is started, rather than the total usage + /// since boot. pub(crate) start_zeroed: Option, } diff --git a/src/options/config/process.rs b/src/options/config/process.rs index 2426e41a..2913e148 100644 --- a/src/options/config/process.rs +++ b/src/options/config/process.rs @@ -9,7 +9,8 @@ use crate::{canvas::components::data_table::SortOrder, widgets::ProcColumn}; pub(crate) struct ProcessesConfig { /// A list of process widget columns. #[serde(default)] - pub columns: Vec, // TODO: make this more composable(?) in the future, we might need to rethink how it's done for custom widgets + pub columns: Vec, /* TODO: make this more composable(?) in the future, we might + * need to rethink how it's done for custom widgets */ /// The default sort column. #[serde(default)] @@ -37,7 +38,8 @@ pub(crate) struct ProcessesConfig { // across platforms. // // #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))] - /// Disable the advanced kill dialog and just show the basic one with no options. + /// Disable the advanced kill dialog and just show the basic one with no + /// options. #[cfg_attr( not(any(target_os = "linux", target_os = "macos", target_os = "freebsd")), allow(dead_code) @@ -47,7 +49,8 @@ pub(crate) struct ProcessesConfig { /// Defaults to showing process memory usage by value. pub default_memory_value: Option, - /// Groups processes with the same name by default. No effect if `--tree` is set. + /// Groups processes with the same name by default. No effect if `--tree` is + /// set. pub default_grouped: Option, /// Enables regex by default while searching. @@ -62,7 +65,8 @@ pub(crate) struct ProcessesConfig { /// Makes the process widget use tree mode by default. pub default_tree: Option, - /// Calculates process CPU usage as a percentage of current usage rather than total usage. + /// Calculates process CPU usage as a percentage of current usage rather + /// than total usage. pub current_usage: Option, /// Show process CPU% usage without averaging over the number of CPU cores. @@ -181,7 +185,8 @@ mod test { ); } - /// Test that process enum variants that are advertised in the schema are valid. + /// Test that process enum variants that are advertised in the schema are + /// valid. #[cfg(feature = "generate_schema")] #[test] fn ensure_process_column_schema_is_accepted() { diff --git a/src/options/config/style.rs b/src/options/config/style.rs index 49a8f534..40d4f634 100644 --- a/src/options/config/style.rs +++ b/src/options/config/style.rs @@ -281,8 +281,8 @@ mod test { #[test] fn color_spelling_aliases_work() { - // Parse all_styling_color.toml (which uses the "color" alias spelling throughout) - // and assert every field was actually parsed. + // Parse all_styling_color.toml (which uses the "color" alias spelling + // throughout) and assert every field was actually parsed. let toml_str = include_str!("../../../tests/valid_configs/all_styling_color.toml"); let config = toml_edit::de::from_str::(toml_str) .expect("config file should parse") diff --git a/src/options/config/style/themes.rs b/src/options/config/style/themes.rs index 44d562a6..641ce84b 100644 --- a/src/options/config/style/themes.rs +++ b/src/options/config/style/themes.rs @@ -4,8 +4,8 @@ pub(super) mod default; pub(super) mod gruvbox; pub(super) mod nord; -/// Convert a [`ratatui::style::Color`] into a [`ratatui::style::Style`] with the colour -/// as the foreground. +/// Convert a [`ratatui::style::Color`] into a [`ratatui::style::Style`] with +/// the colour as the foreground. macro_rules! colour { ($value:expr) => { ratatui::style::Style::new().fg($value) diff --git a/src/options/config/temperature.rs b/src/options/config/temperature.rs index 74666568..4a2a3f35 100644 --- a/src/options/config/temperature.rs +++ b/src/options/config/temperature.rs @@ -22,7 +22,8 @@ pub(crate) struct TempConfig { #[cfg(test)] mod tests { - /// Test that temp enum variants that are advertised in the schema are valid. + /// Test that temp enum variants that are advertised in the schema are + /// valid. #[cfg(feature = "generate_schema")] #[test] fn ensure_temp_column_schema_is_accepted() { diff --git a/src/options/config/temperature_graph.rs b/src/options/config/temperature_graph.rs index 215de474..cf8daf87 100644 --- a/src/options/config/temperature_graph.rs +++ b/src/options/config/temperature_graph.rs @@ -14,8 +14,8 @@ pub(crate) struct TempGraphConfig { #[serde(default)] pub(crate) legend_position: Option, - /// An upper temperature value for the graph; entries higher than this will be hidden. If not set, - /// there is no limit. + /// An upper temperature value for the graph; entries higher than this will + /// be hidden. If not set, there is no limit. /// /// Is in the configured temperature unit. #[serde(default)] diff --git a/src/utils/input.rs b/src/utils/input.rs index 0f8e9629..e363611b 100644 --- a/src/utils/input.rs +++ b/src/utils/input.rs @@ -74,8 +74,8 @@ impl InputFieldState { /// such that this is clear this only matters for drawing... but it also /// changes states... pub(crate) fn get_start_position(&mut self, available_width: usize, is_force_redraw: bool) { - // Remember - the number of columns != the number of grapheme slots/sizes, you - // cannot use index to determine this reliably! + // Remember - the number of columns != the number of grapheme + // slots/sizes, you cannot use index to determine this reliably! let start_index = if is_force_redraw { 0 @@ -100,7 +100,8 @@ impl InputFieldState { // - The current start index can show the cursor's word. // - The current start index cannot show the cursor's word. // - // What differs is how we "scroll" based on the cursor movement direction. + // What differs is how we "scroll" based on the cursor movement + // direction. self.display_start_index = match self.cursor_direction { CursorDirection::Right => { @@ -108,7 +109,8 @@ impl InputFieldState { // Use the current index. start_index } else if cursor_range.end >= available_width { - // If the current position is past the last visible element, skip until we + // If the current position is past the last visible + // element, skip until we // see it. let mut index = 0; @@ -159,8 +161,8 @@ impl InputFieldState { Ok(_) => {} Err(err) => match err { GraphemeIncomplete::PreContext(ctx) => { - // Provide the entire string as context. Not efficient but should resolve - // failures. + // Provide the entire string as context. Not efficient but + // should resolve failures. self.grapheme_cursor .provide_context(&self.current_query[0..ctx], 0); @@ -182,8 +184,8 @@ impl InputFieldState { Ok(_) => {} Err(err) => match err { GraphemeIncomplete::PreContext(ctx) => { - // Provide the entire string as context. Not efficient but should resolve - // failures. + // Provide the entire string as context. Not efficient but + // should resolve failures. self.grapheme_cursor .provide_context(&self.current_query[0..ctx], 0); @@ -717,18 +719,19 @@ mod tests { /// producing the wrong result or panicking. #[test] fn delete_previous_word_unicode() { - // "你好 world" - '你'=3 bytes, '好'=3 bytes, ' '=1, "world"=5, so 12 bytes - // total + // "你好 world" - '你'=3 bytes, '好'=3 bytes, ' '=1, "world"=5, so 12 + // bytes total let mut state = InputFieldState::default(); state.insert_string("你好 world".to_string()); - // Cursor is at the end (byte 12). Deleting the previous word should remove - // "world", leaving "你好 " (7 bytes). + // Cursor is at the end (byte 12). Deleting the previous word should + // remove "world", leaving "你好 " (7 bytes). state.delete_previous_word(); assert_eq!(state.current_query(), "你好 "); assert_eq!(state.cursor_index(), 7); - // Deleting again skips the trailing space then removes "你好", leaving "". + // Deleting again skips the trailing space then removes "你好", leaving + // "". state.delete_previous_word(); assert_eq!(state.current_query(), ""); assert_eq!(state.cursor_index(), 0); @@ -821,7 +824,8 @@ mod tests { assert_eq!(state.grapheme_cursor.cur_cursor(), 12); assert_eq!(state.display_start_index, 10); - // Move past the flag emoji (🇨🇦 = 8 bytes) to the end of string (byte 20). + // Move past the flag emoji (🇨🇦 = 8 bytes) to the end of string (byte + // 20). state.move_right(); state.get_start_position(4, false); assert_eq!(state.grapheme_cursor.cur_cursor(), 20); diff --git a/src/utils/process_killer.rs b/src/utils/process_killer.rs index 38546592..9234f63b 100644 --- a/src/utils/process_killer.rs +++ b/src/utils/process_killer.rs @@ -27,7 +27,8 @@ impl Process { } fn kill(self) -> anyhow::Result<()> { - // SAFETY: Windows API call, this is safe as we are passing in the handle. + // SAFETY: Windows API call, this is safe as we are passing in the + // handle. let result = unsafe { TerminateProcess(self.0, 1) }; if result.is_err() { bail!("process may have already been terminated."); @@ -40,7 +41,8 @@ impl Process { #[cfg(target_os = "windows")] impl Drop for Process { fn drop(&mut self) { - // SAFETY: Windows API call, this is safe as we are passing in the handle. + // SAFETY: Windows API call, this is safe as we are passing in the + // handle. unsafe { let _ = CloseHandle(self.0); } diff --git a/src/widgets/cpu_graph.rs b/src/widgets/cpu_graph.rs index 8f38cea2..5b3b42eb 100644 --- a/src/widgets/cpu_graph.rs +++ b/src/widgets/cpu_graph.rs @@ -53,13 +53,14 @@ impl DataToCell for CpuWidgetTableData { let calculated_width = calculated_width.get(); - // This is a bit of a hack, but apparently we can avoid having to do any fancy - // checks of showing the "All" on a specific column if the other is - // hidden by just always showing it on the CPU (first) column - if there - // isn't room for it, it will just collapse down. + // This is a bit of a hack, but apparently we can avoid having to do any + // fancy checks of showing the "All" on a specific column if the + // other is hidden by just always showing it on the CPU (first) + // column - if there isn't room for it, it will just collapse + // down. // - // This is the same for the use percentages - we just *always* show them, and - // *always* hide the CPU column if it is too small. + // This is the same for the use percentages - we just *always* show + // them, and *always* hide the CPU column if it is too small. match &self { CpuWidgetTableData::All => match column { CpuWidgetColumn::Cpu => Some("All".into()), diff --git a/src/widgets/disk_table.rs b/src/widgets/disk_table.rs index c3441eaf..75020258 100644 --- a/src/widgets/disk_table.rs +++ b/src/widgets/disk_table.rs @@ -333,7 +333,8 @@ impl DiskTableWidget { }, sort_index: match &config.default_disk_sort_column { Some(column) => { - // Must check that the column used exists. If not, fall back to 0. + // Must check that the column used exists. If not, fall back + // to 0. let existing_columns = match columns { Some(c) => c, @@ -377,8 +378,9 @@ impl DiskTableWidget { /// Update the current table data. pub fn set_table_data(&mut self, data: &InnerData) { - // Note that the data may contain unmounted disks (e.g. we enable it for another disk widget), - // so we have to potentially filter it out here too. + // Note that the data may contain unmounted disks (e.g. we enable it for + // another disk widget), so we have to potentially filter it out + // here too. let mut data: Vec = if self.show_unmounted { data.disk_harvest.clone() } else { diff --git a/src/widgets/process_table.rs b/src/widgets/process_table.rs index f1aa0eae..91eea3d2 100644 --- a/src/widgets/process_table.rs +++ b/src/widgets/process_table.rs @@ -581,7 +581,8 @@ impl ProcWidgetState { let filtered_tree = { let mut filtered_tree: IntHashMap> = IntHashMap::default(); - // We do a simple DFS traversal to build our filtered parent-to-tree mappings. + // We do a simple DFS traversal to build our filtered parent-to-tree + // mappings. let mut visited_pids: IntHashMap = IntHashMap::default(); let mut stack = orphan_pids .iter() @@ -603,8 +604,8 @@ impl ProcWidgetState { // Show the entry if it is: // - Matches the filter. - // - Has at least one child (doesn't have to be direct) that matches the - // filter. + // - Has at least one child (doesn't have to be direct) + // that matches the filter. // - Is the child of a shown process. let is_shown = is_process_matching || !shown_children.is_empty() @@ -711,8 +712,8 @@ impl ProcWidgetState { has_children = !children_pids.is_empty(); } - // This is so that if an entry is "collapsed" but there are no children, avoid - // drawing the "+". + // This is so that if an entry is "collapsed" but there are no + // children, avoid drawing the "+". let prefix = if has_children { if prefixes.is_empty() { "+ ".to_string() diff --git a/src/widgets/process_table/process_columns.rs b/src/widgets/process_table/process_columns.rs index 4c93cc5d..f13c0b8f 100644 --- a/src/widgets/process_table/process_columns.rs +++ b/src/widgets/process_table/process_columns.rs @@ -169,8 +169,8 @@ impl SortsRow for ProcColumn { } } ProcColumn::User => { - // FIXME: Is there a better way here to keep the to_lowercase? Usually it - // shouldn't matter but... + // FIXME: Is there a better way here to keep the to_lowercase? + // Usually it shouldn't matter but... if descending { data.sort_by_cached_key(|pd| Reverse(pd.user.clone())); } else { diff --git a/src/widgets/process_table/process_data.rs b/src/widgets/process_table/process_data.rs index f24950f4..77e02886 100644 --- a/src/widgets/process_table/process_data.rs +++ b/src/widgets/process_table/process_data.rs @@ -351,8 +351,8 @@ impl DataToCell for ProcWidgetData { &self, column: &ProcColumn, calculated_width: NonZeroU16, ) -> Option> { // TODO: Optimize the string allocations here... - // TODO: Also maybe just pull in the to_string call but add a variable for the - // differences. + // TODO: Also maybe just pull in the to_string call but add a variable + // for the differences. Some(match column { #[cfg(unix)] ProcColumn::Nice => self.nice.to_string().into(), diff --git a/src/widgets/process_table/query.rs b/src/widgets/process_table/query.rs index 460ee770..021b250a 100644 --- a/src/widgets/process_table/query.rs +++ b/src/widgets/process_table/query.rs @@ -127,7 +127,8 @@ pub(crate) fn parse_query(search_query: &str, options: &QueryOptions) -> QueryRe let mut last = 0; for (index, matched) in s.match_indices(|x| DELIMITER_LIST.contains(&x)) { if matched == "\"" { - // Always split on quote delimiters to open/close quoted sections. + // Always split on quote delimiters to open/close quoted + // sections. if last != index { split_query.push_back(s[last..index].to_owned()); } @@ -211,7 +212,8 @@ impl std::str::FromStr for PrefixType { // TODO: Didn't add mem_bytes, total_read, and total_write // for now as it causes help to be clogged. - // TODO: Add a `name` keyword alias so something like `name = blah` is valid. + // TODO: Add a `name` keyword alias so something like `name = blah` is + // valid. let mut result = Name; if multi_eq_ignore_ascii_case!(s, "cpu" | "cpu%") { @@ -940,7 +942,8 @@ mod tests { assert!(query.check(&other, false)); } - /// Test state queries with the non-equality operator. This also tests that string comparisons. + /// Test state queries with the non-equality operator. This also tests that + /// string comparisons. #[test] fn state_not_equal_query() { let query = parse_query_no_options("state != sleeping").unwrap(); @@ -1084,8 +1087,8 @@ mod tests { assert!(!query.check(&other, false)); } - /// A quoted `"!"` as the RHS of a prefixed string query with "!=" should not match the - /// literal `!`, nor should it be treated as an operator. + /// A quoted `"!"` as the RHS of a prefixed string query with "!=" should + /// not match the literal `!`, nor should it be treated as an operator. #[test] fn user_negated_equals_quoted_bang() { let query = parse_query_no_options("user != \"!\"").unwrap(); @@ -1112,7 +1115,8 @@ mod tests { assert!(!query.check(&without, false)); } - /// Quoted angle brackets should be treated as literal characters in name matches. + /// Quoted angle brackets should be treated as literal characters in name + /// matches. #[test] fn quoted_angle_brackets_match_literal() { let query = parse_query_no_options("\"Thread<15>\"").unwrap(); @@ -1136,7 +1140,8 @@ mod tests { assert!(!query.check(&non_matching, false)); } - /// A quoted `!=` should be treated as a literal character sequence in name matches. + /// A quoted `!=` should be treated as a literal character sequence in name + /// matches. #[test] fn quoted_not_equals_matches_literal() { let query = parse_query_no_options("\"a!=b\"").unwrap(); @@ -1148,7 +1153,8 @@ mod tests { assert!(!query.check(&non_matching, false)); } - /// Quoted parentheses should be treated as literal characters in name matches. + /// Quoted parentheses should be treated as literal characters in name + /// matches. #[test] fn quoted_parens_match_literal() { let query = parse_query_no_options("\"a(b)\"").unwrap(); @@ -1168,7 +1174,8 @@ mod tests { parse_query_no_options("time !=").unwrap_err(); } - /// Some miscellaneous invalid string searches involving negation (`!`) parsing. + /// Some miscellaneous invalid string searches involving negation (`!`) + /// parsing. #[test] fn misc_invalid_bang_search() { parse_query_no_options("user = !").unwrap_err(); diff --git a/src/widgets/process_table/query/prefix.rs b/src/widgets/process_table/query/prefix.rs index 9c4f273e..ac2b6c9c 100644 --- a/src/widgets/process_table/query/prefix.rs +++ b/src/widgets/process_table/query/prefix.rs @@ -82,17 +82,18 @@ impl Prefix { ) -> QueryResult { if let Some(queue_top) = query.pop_front() { if queue_top == "\"" { - // This means we hit something like "". Return an empty prefix, and to deal - // with the close quote checker, add one to the top of the - // stack. Ugly fix but whatever. + // This means we hit something like "". Return an empty prefix, + // and to deal with the close quote checker, add + // one to the top of the stack. Ugly fix but + // whatever. query.push_front("\"".to_string()); Ok(Prefix::Attribute(ProcessAttribute::Empty)) } else { let mut intern_string = vec![queue_top]; - // TODO: I think this should consume the quote...? Might need to check the other - // spot we process quotes. + // TODO: I think this should consume the quote...? Might need to + // check the other spot we process quotes. while let Some(next_str) = query.front() { if next_str == "\"" { break; @@ -110,7 +111,8 @@ impl Prefix { )?)) } } else { - // Uh oh, there's nothing left in the stack, but we're inside quotes! + // Uh oh, there's nothing left in the stack, but we're inside + // quotes! Err(QueryError::new("Missing closing quotation")) } } @@ -195,9 +197,9 @@ impl QueryProcessor for Prefix { let inner = Prefix::process(query, options)?; return Ok(Prefix::Negate(Box::new(inner))); } else if curr == "\"" { - // Similar to parentheses, trap and check for missing closing quotes. Note, - // however, that we will DIRECTLY call another process_prefix - // call... + // Similar to parentheses, trap and check for missing closing + // quotes. Note, however, that we will DIRECTLY + // call another process_prefix call... let prefix = Prefix::process_in_quotes(query, options)?; return if let Some(close_quote) = query.pop_front() { @@ -230,7 +232,8 @@ impl QueryProcessor for Prefix { )?)); } PrefixType::Pid | PrefixType::State | PrefixType::User => { - // We have to check if someone put an (in)equality check... + // We have to check if someone put an (in)equality + // check... if content == "=" || content == "!=" { let negate = content.starts_with('!'); @@ -241,22 +244,27 @@ impl QueryProcessor for Prefix { "`!` is reserved; use `\"!\"` to match the literal character", )); } - // TODO: [Query] Need to consider the following cases: + // TODO: [Query] Need to consider the + // following cases: // - (test) // - (test // - test) - // These are split into 2 to 3 different strings due to + // These are split into 2 to 3 different + // strings due to // parentheses being // delimiters in our query system. // - // Do we want these to be valid? They should, as a string, + // Do we want these to be valid? They + // should, as a string, // right? - // We also must check if this value is wrapped in quotes! + // We also must check if this value is + // wrapped in quotes! let final_value = if string_value == "\"" { let mut intern_string = vec![]; - // Keep parsing until we either hit another quotation or we + // Keep parsing until we either hit + // another quotation or we // error. while let Some(next_string) = query.pop_front() { if next_string == "\"" { @@ -343,13 +351,16 @@ impl QueryProcessor for Prefix { } } _ => { - // Assume it's some numerical value. Now we gotta parse the content... yay. - // Note that for numerical parsing, we handle unit parsing later, not here. + // Assume it's some numerical value. Now we gotta + // parse the content... yay. + // Note that for numerical parsing, we handle unit + // parsing later, not here. let mut condition: Option = None; let mut value: Option = None; - // TODO: Jeez, what the heck did I write here... add some tests and + // TODO: Jeez, what the heck did I write here... add + // some tests and // clean this up in the future. if content == "=" { condition = Some(QueryComparison::Equal); @@ -366,7 +377,8 @@ impl QueryProcessor for Prefix { return Err(QueryError::missing_value()); } } else if content == ">" || content == "<" { - // We also have to check if the next string is an "="... + // We also have to check if the next string is + // an "="... if let Some(queue_next) = query.pop_front() { if queue_next == "=" { condition = Some(if content == ">" { @@ -395,7 +407,8 @@ impl QueryProcessor for Prefix { if let Some(condition) = condition && let Some(read_value) = value { - // Note that the values *might* have a unit or need to be parsed + // Note that the values *might* have a unit or + // need to be parsed // differently based on the // prefix type! @@ -431,8 +444,8 @@ impl QueryProcessor for Prefix { } } - // TODO: Give more information here (e.g. closest query?), though this is moreso - // meant as a fallback. + // TODO: Give more information here (e.g. closest query?), though this + // is moreso meant as a fallback. Err(QueryError::new("Invalid query")) } } diff --git a/tests/integration/valid_config_tests.rs b/tests/integration/valid_config_tests.rs index a51743b8..51f57bee 100644 --- a/tests/integration/valid_config_tests.rs +++ b/tests/integration/valid_config_tests.rs @@ -243,25 +243,29 @@ fn test_network_alias() { run_and_kill_cfg("./tests/valid_configs/network_alias.toml"); } -/// This uses deprecated network settings - once they are removed, this test file should be moved to invalid configs. +/// This uses deprecated network settings - once they are removed, this test +/// file should be moved to invalid configs. #[test] fn test_deprecated_network() { run_and_kill_cfg("./tests/valid_configs/deprecated/network.toml"); } -/// This uses deprecated process settings - once they are removed, this test file should be moved to invalid configs. +/// This uses deprecated process settings - once they are removed, this test +/// file should be moved to invalid configs. #[test] fn test_deprecated_processes() { run_and_kill_cfg("./tests/valid_configs/deprecated/processes.toml"); } -/// This uses deprecated CPU settings - once they are removed, this test file should be moved to invalid configs. +/// This uses deprecated CPU settings - once they are removed, this test file +/// should be moved to invalid configs. #[test] fn test_deprecated_cpu() { run_and_kill_cfg("./tests/valid_configs/deprecated/cpu.toml"); } -/// This uses deprecated memory settings - once they are removed, this test file should be moved to invalid configs. +/// This uses deprecated memory settings - once they are removed, this test file +/// should be moved to invalid configs. #[test] fn test_deprecated_memory() { run_and_kill_cfg("./tests/valid_configs/deprecated/memory.toml"); @@ -277,14 +281,15 @@ fn test_disk_io_graph() { run_and_kill_cfg("./tests/valid_configs/widget/disk_io_graph.toml"); } -/// This uses deprecated temperature settings - once they are removed, this test file should be moved to invalid configs. +/// This uses deprecated temperature settings - once they are removed, this test +/// file should be moved to invalid configs. #[test] fn test_deprecated_temperature() { run_and_kill_cfg("./tests/valid_configs/deprecated/temperature.toml"); } -/// Test that deprecated warnings are not shown for config options that are not actually set, -/// even when a `[flags]` section is present. +/// Test that deprecated warnings are not shown for config options that are not +/// actually set, even when a `[flags]` section is present. #[test] fn test_no_spurious_deprecated_warnings() { let mut child = btm_command(&["-C", "./tests/valid_configs/empty_flags.toml"])