From ed07fbe1ccb4b4f27253b1a642d8a6a663bcbf6b Mon Sep 17 00:00:00 2001 From: Clement Tsang <34804052+ClementTsang@users.noreply.github.com> Date: Thu, 19 Aug 2021 22:16:44 -0400 Subject: [PATCH] other: Make the battery dependency/features optional (#570) Allows disabling of the battery dependency through a feature flag. This also aims to disable all related features. --- .github/workflows/ci.yml | 10 +- .github/workflows/deployment.yml | 2 +- .github/workflows/nightly.yml | 2 +- Cargo.toml | 6 +- docs/content/usage/widgets/battery.md | 4 + src/app/data_farmer.rs | 22 ++++- src/app/data_harvester.rs | 36 ++++--- src/app/layout_manager.rs | 37 ++++++-- src/bin/main.rs | 9 +- src/clap.rs | 132 +++++++++++++++++--------- src/data_conversion.rs | 1 + 11 files changed, 183 insertions(+), 78 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69041fe6..9c12e669 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -205,7 +205,15 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --all-targets --verbose --target=${{ matrix.triple.target }} --no-default-features + args: --all-targets --verbose --target=${{ matrix.triple.target }} --features "battery" + use-cross: ${{ matrix.triple.cross }} + + - name: Check without battery feature on the main 3 + if: matrix.triple.toTest == 'true' + uses: actions-rs/cargo@v1 + with: + command: check + args: --all-targets --verbose --target=${{ matrix.triple.target }} use-cross: ${{ matrix.triple.cross }} - name: Run tests diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index e29d1a9a..90ab9bb3 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -218,7 +218,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --release --verbose --target=${{ matrix.triple.target }} --no-default-features + args: --release --verbose --target=${{ matrix.triple.target }} --features "battery" use-cross: ${{ matrix.triple.cross }} - name: Move autocomplete to working directory diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 817750ad..21beb3b8 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -212,7 +212,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --release --verbose --target=${{ matrix.triple.target }} --no-default-features + args: --release --verbose --target=${{ matrix.triple.target }} --features "battery" use-cross: ${{ matrix.triple.cross }} - name: Move autocomplete to working directory diff --git a/Cargo.toml b/Cargo.toml index e7bdfe3b..ad710d62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,12 +31,11 @@ opt-level = 3 codegen-units = 1 [features] -default = ["fern", "log"] +default = ["fern", "log", "battery"] [dependencies] anyhow = "1.0.40" backtrace = "0.3.59" -battery = "0.7.8" chrono = "0.4.19" crossterm = "0.18.2" ctrlc = { version = "3.1.9", features = ["termination"] } @@ -60,9 +59,10 @@ typed-builder = "0.9.0" unicode-segmentation = "1.7.1" unicode-width = "0.1" -# For debugging only... disable on release builds with --no-default-target for no? TODO: Redo this. +# For debugging only... disable on release builds with for now? TODO: Redo this. fern = { version = "0.6.0", optional = true } log = { version = "0.4.14", optional = true } +battery = { version = "0.7.8", optional = true } [target.'cfg(unix)'.dependencies] libc = "0.2.86" diff --git a/docs/content/usage/widgets/battery.md b/docs/content/usage/widgets/battery.md index c1e62a75..1859a3ba 100644 --- a/docs/content/usage/widgets/battery.md +++ b/docs/content/usage/widgets/battery.md @@ -1,5 +1,9 @@ # Battery Widget +!!! Warning + + The battery features are unavailable if the binary is compiled with the `battery` feature disabled! + The battery widget provides information about batteries on the system.
diff --git a/src/app/data_farmer.rs b/src/app/data_farmer.rs index 931ab96f..578941ef 100644 --- a/src/app/data_farmer.rs +++ b/src/app/data_farmer.rs @@ -16,8 +16,11 @@ use once_cell::sync::Lazy; use std::{time::Instant, vec::Vec}; +#[cfg(feature = "battery")] +use crate::data_harvester::batteries; + use crate::{ - data_harvester::{batteries, cpu, disks, memory, network, processes, temperature, Data}, + data_harvester::{cpu, disks, memory, network, processes, temperature, Data}, utils::gen_util::{get_decimal_bytes, GIGA_LIMIT}, }; use regex::Regex; @@ -60,6 +63,7 @@ pub struct DataCollection { pub io_labels_and_prev: Vec<((u64, u64), (u64, u64))>, pub io_labels: Vec<(String, String)>, pub temp_harvest: Vec, + #[cfg(feature = "battery")] pub battery_harvest: Vec, } @@ -80,6 +84,7 @@ impl Default for DataCollection { io_labels_and_prev: Vec::default(), io_labels: Vec::default(), temp_harvest: Vec::default(), + #[cfg(feature = "battery")] battery_harvest: Vec::default(), } } @@ -97,7 +102,10 @@ impl DataCollection { self.io_harvest = disks::IoHarvest::default(); self.io_labels_and_prev = Vec::default(); self.temp_harvest = Vec::default(); - self.battery_harvest = Vec::default(); + #[cfg(feature = "battery")] + { + self.battery_harvest = Vec::default(); + } } pub fn set_frozen_time(&mut self) { @@ -166,9 +174,12 @@ impl DataCollection { self.eat_proc(list_of_processes); } - // Battery - if let Some(list_of_batteries) = harvested_data.list_of_batteries { - self.eat_battery(list_of_batteries); + #[cfg(feature = "battery")] + { + // Battery + if let Some(list_of_batteries) = harvested_data.list_of_batteries { + self.eat_battery(list_of_batteries); + } } // And we're done eating. Update time and push the new entry! @@ -312,6 +323,7 @@ impl DataCollection { self.process_harvest = list_of_processes; } + #[cfg(feature = "battery")] fn eat_battery(&mut self, list_of_batteries: Vec) { self.battery_harvest = list_of_batteries; } diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs index 32482537..79427a9f 100644 --- a/src/app/data_harvester.rs +++ b/src/app/data_harvester.rs @@ -8,6 +8,7 @@ use fxhash::FxHashMap; #[cfg(not(target_os = "linux"))] use sysinfo::{System, SystemExt}; +#[cfg(feature = "battery")] use battery::{Battery, Manager}; use crate::app::layout_manager::UsedWidgets; @@ -16,6 +17,7 @@ use futures::join; use super::DataFilters; +#[cfg(feature = "battery")] pub mod batteries; pub mod cpu; pub mod disks; @@ -36,6 +38,7 @@ pub struct Data { pub list_of_processes: Option>, pub disks: Option>, pub io: Option, + #[cfg(feature = "battery")] pub list_of_batteries: Option>, } @@ -52,6 +55,7 @@ impl Default for Data { disks: None, io: None, network: None, + #[cfg(feature = "battery")] list_of_batteries: None, } } @@ -95,7 +99,9 @@ pub struct DataCollector { total_tx: u64, show_average_cpu: bool, widgets_to_harvest: UsedWidgets, + #[cfg(feature = "battery")] battery_manager: Option, + #[cfg(feature = "battery")] battery_list: Option>, filters: DataFilters, } @@ -122,7 +128,9 @@ impl DataCollector { total_tx: 0, show_average_cpu: false, widgets_to_harvest: UsedWidgets::default(), + #[cfg(feature = "battery")] battery_manager: None, + #[cfg(feature = "battery")] battery_list: None, filters, } @@ -150,13 +158,16 @@ impl DataCollector { } } - if self.widgets_to_harvest.use_battery { - if let Ok(battery_manager) = Manager::new() { - if let Ok(batteries) = battery_manager.batteries() { - let battery_list: Vec = batteries.filter_map(Result::ok).collect(); - if !battery_list.is_empty() { - self.battery_list = Some(battery_list); - self.battery_manager = Some(battery_manager); + #[cfg(feature = "battery")] + { + if self.widgets_to_harvest.use_battery { + if let Ok(battery_manager) = Manager::new() { + if let Ok(batteries) = battery_manager.batteries() { + let battery_list: Vec = batteries.filter_map(Result::ok).collect(); + if !battery_list.is_empty() { + self.battery_list = Some(battery_list); + self.battery_manager = Some(battery_manager); + } } } } @@ -235,10 +246,13 @@ impl DataCollector { } // Batteries - if let Some(battery_manager) = &self.battery_manager { - if let Some(battery_list) = &mut self.battery_list { - self.data.list_of_batteries = - Some(batteries::refresh_batteries(battery_manager, battery_list)); + #[cfg(feature = "battery")] + { + if let Some(battery_manager) = &self.battery_manager { + if let Some(battery_list) = &mut self.battery_list { + self.data.list_of_batteries = + Some(batteries::refresh_batteries(battery_manager, battery_list)); + } } } diff --git a/src/app/layout_manager.rs b/src/app/layout_manager.rs index d4b9272d..cf23efda 100644 --- a/src/app/layout_manager.rs +++ b/src/app/layout_manager.rs @@ -945,10 +945,12 @@ impl std::str::FromStr for BottomWidgetType { "temp" | "temperature" => Ok(BottomWidgetType::Temp), "disk" => Ok(BottomWidgetType::Disk), "empty" => Ok(BottomWidgetType::Empty), - "battery" | "batt" => Ok(BottomWidgetType::Battery), - _ => Err(BottomError::ConfigError(format!( - "\"{}\" is an invalid widget name. - + "battery" | "batt" if cfg!(feature = "battery") => Ok(BottomWidgetType::Battery), + _ => { + if cfg!(feature = "battery") { + Err(BottomError::ConfigError(format!( + "\"{}\" is an invalid widget name. + Supported widget names: +--------------------------+ | cpu | @@ -966,8 +968,31 @@ Supported widget names: | batt, battery | +--------------------------+ ", - s - ))), + s + ))) + } else { + Err(BottomError::ConfigError(format!( + "\"{}\" is an invalid widget name. + +Supported widget names: ++--------------------------+ +| cpu | ++--------------------------+ +| mem, memory | ++--------------------------+ +| net, network | ++--------------------------+ +| proc, process, processes | ++--------------------------+ +| temp, temperature | ++--------------------------+ +| disk | ++--------------------------+ + ", + s + ))) + } + } } } } diff --git a/src/bin/main.rs b/src/bin/main.rs index 02828ed7..b77900fb 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -217,9 +217,12 @@ fn main() -> Result<()> { } // Battery - if app.used_widgets.use_battery { - app.canvas_data.battery_data = - convert_battery_harvest(&app.data_collection); + #[cfg(feature = "battery")] + { + if app.used_widgets.use_battery { + app.canvas_data.battery_data = + convert_battery_harvest(&app.data_collection); + } } } } diff --git a/src/clap.rs b/src/clap.rs index 7e7ecee1..8604c5a8 100644 --- a/src/clap.rs +++ b/src/clap.rs @@ -14,6 +14,72 @@ FLAGS: const USAGE: &str = " btm [FLAG]"; +const DEFAULT_WIDGET_TYPE_STR: &str = if cfg!(feature = "battery") { + "\ +Sets which widget type to use as the default widget. +For the default layout, this defaults to the 'process' widget. +For a custom layout, it defaults to the first widget it sees. + +For example, suppose we have a layout that looks like: ++-------------------+-----------------------+ +| CPU (1) | CPU (2) | ++---------+---------+-------------+---------+ +| Process | CPU (3) | Temperature | CPU (4) | ++---------+---------+-------------+---------+ + +Setting '--default_widget_type Temp' will make the Temperature +widget selected by default. + +Supported widget names: ++--------------------------+ +| cpu | ++--------------------------+ +| mem, memory | ++--------------------------+ +| net, network | ++--------------------------+ +| proc, process, processes | ++--------------------------+ +| temp, temperature | ++--------------------------+ +| disk | ++--------------------------+ +| batt, battery | ++--------------------------+ +\n\n" +} else { + "\ +Sets which widget type to use as the default widget. +For the default layout, this defaults to the 'process' widget. +For a custom layout, it defaults to the first widget it sees. + +For example, suppose we have a layout that looks like: ++-------------------+-----------------------+ +| CPU (1) | CPU (2) | ++---------+---------+-------------+---------+ +| Process | CPU (3) | Temperature | CPU (4) | ++---------+---------+-------------+---------+ + +Setting '--default_widget_type Temp' will make the Temperature +widget selected by default. + +Supported widget names: ++--------------------------+ +| cpu | ++--------------------------+ +| mem, memory | ++--------------------------+ +| net, network | ++--------------------------+ +| proc, process, processes | ++--------------------------+ +| temp, temperature | ++--------------------------+ +| disk | ++--------------------------+ +\n\n" +}; + pub fn get_matches() -> clap::ArgMatches<'static> { build_app().get_matches() } @@ -66,14 +132,6 @@ disabled via --hide_time then this will have no effect.\n\n\n", Hides graphs and uses a more basic look. Design is largely inspired by htop's.\n\n", ); - let battery = Arg::with_name("battery") - .long("battery") - .help("Shows the battery widget.") - .long_help( - "\ -Shows the battery widget in default or basic mode. No effect on -custom layouts.\n\n", - ); let case_sensitive = Arg::with_name("case_sensitive") .short("S") .long("case_sensitive") @@ -318,40 +376,7 @@ use CPU (3) as the default instead. .takes_value(true) .value_name("WIDGET TYPE") .help("Sets the default widget type, use --help for more info.") - .long_help( - "\ -Sets which widget type to use as the default widget. -For the default layout, this defaults to the 'process' widget. -For a custom layout, it defaults to the first widget it sees. - -For example, suppose we have a layout that looks like: -+-------------------+-----------------------+ -| CPU (1) | CPU (2) | -+---------+---------+-------------+---------+ -| Process | CPU (3) | Temperature | CPU (4) | -+---------+---------+-------------+---------+ - -Setting '--default_widget_type Temp' will make the Temperature -widget selected by default. - -Supported widget names: -+--------------------------+ -| cpu | -+--------------------------+ -| mem, memory | -+--------------------------+ -| net, network | -+--------------------------+ -| proc, process, processes | -+--------------------------+ -| temp, temperature | -+--------------------------+ -| disk | -+--------------------------+ -| batt, battery | -+--------------------------+ -\n\n", - ); + .long_help(DEFAULT_WIDGET_TYPE_STR); let rate = Arg::with_name("rate") .short("r") .long("rate") @@ -408,7 +433,7 @@ Displays the network widget with a log scale. Defaults to a non-log scale.\n\n" Displays the network widget with binary prefixes (i.e. kibibits, mebibits) rather than a decimal prefix (i.e. kilobits, megabits). Defaults to decimal prefixes.\n\n\n", ); - App::new(crate_name!()) + let app = App::new(crate_name!()) .setting(AppSettings::UnifiedHelpMessage) .version(crate_version!()) .author(crate_authors!()) @@ -423,12 +448,10 @@ Displays the network widget with binary prefixes (i.e. kibibits, mebibits) rathe .group(ArgGroup::with_name("TEMPERATURE_TYPE").args(&["kelvin", "fahrenheit", "celsius"])) .arg(autohide_time) .arg(basic) - .arg(battery) .arg(case_sensitive) .arg(process_command) .arg(config_location) .arg(color) - // .arg(debug) .arg(mem_as_value) .arg(default_time_value) .arg(default_widget_count) @@ -442,7 +465,6 @@ Displays the network widget with binary prefixes (i.e. kibibits, mebibits) rathe .arg(show_table_scroll_position) .arg(left_legend) .arg(disable_advanced_kill) - // .arg(no_write) .arg(rate) .arg(regex) .arg(time_delta) @@ -452,5 +474,21 @@ Displays the network widget with binary prefixes (i.e. kibibits, mebibits) rathe .arg(network_use_binary_prefix) .arg(current_usage) .arg(use_old_network_legend) - .arg(whole_word) + .arg(whole_word); + + let app = if cfg!(feature = "battery") { + let battery = Arg::with_name("battery") + .long("battery") + .help("Shows the battery widget.") + .long_help( + "\ +Shows the battery widget in default or basic mode. No effect on +custom layouts.\n\n", + ); + app.arg(battery) + } else { + app + }; + + app } diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 58652370..7e4d214e 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -1362,6 +1362,7 @@ pub fn group_process_data( .collect::>() } +#[cfg(feature = "battery")] pub fn convert_battery_harvest( current_data: &data_farmer::DataCollection, ) -> Vec {