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.
This commit is contained in:
Clement Tsang 2021-08-19 22:16:44 -04:00 committed by GitHub
parent 2c8aea9eef
commit ed07fbe1cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 183 additions and 78 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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.
<figure>

View File

@ -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<temperature::TempHarvest>,
#[cfg(feature = "battery")]
pub battery_harvest: Vec<batteries::BatteryHarvest>,
}
@ -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<batteries::BatteryHarvest>) {
self.battery_harvest = list_of_batteries;
}

View File

@ -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<Vec<processes::ProcessHarvest>>,
pub disks: Option<Vec<disks::DiskHarvest>>,
pub io: Option<disks::IoHarvest>,
#[cfg(feature = "battery")]
pub list_of_batteries: Option<Vec<batteries::BatteryHarvest>>,
}
@ -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<Manager>,
#[cfg(feature = "battery")]
battery_list: Option<Vec<Battery>>,
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<Battery> = 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<Battery> = 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));
}
}
}

View File

@ -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
)))
}
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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
}

View File

@ -1362,6 +1362,7 @@ pub fn group_process_data(
.collect::<Vec<_>>()
}
#[cfg(feature = "battery")]
pub fn convert_battery_harvest(
current_data: &data_farmer::DataCollection,
) -> Vec<ConvertedBatteryData> {