summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2023-06-23 07:42:16 +0000
committerGitHub <noreply@github.com>2023-06-23 03:42:16 -0400
commitcc3833289fa5063efe30c2a16da56a9b04117e1b (patch)
tree5408634129744b9f613f11f35da1b04a07586f0b
parent0b7f4c745dbf5ef93a0d1fbf185fd725995a74bb (diff)
feature: support human times for rate (#1221)
-rw-r--r--CHANGELOG.md4
-rw-r--r--src/app.rs2
-rw-r--r--src/args.rs4
-rw-r--r--src/constants.rs2
-rw-r--r--src/lib.rs2
-rw-r--r--src/options.rs102
-rw-r--r--tests/arg_tests.rs2
7 files changed, 65 insertions, 53 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86841312..67f0c462 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#1216](https://github.com/ClementTsang/bottom/pull/1216): Fix arguments not being sorted alphabetically.
- [#1219](https://github.com/ClementTsang/bottom/pull/1219): Fix overflow/underflow in graph timespan zoom.
+## Features
+
+- [#1221](https://github.com/ClementTsang/bottom/pull/1221): Support human times for `rate`.
+
## [0.9.2] - 2023-06-11
## Bug Fixes
diff --git a/src/app.rs b/src/app.rs
index 5418f615..03782a56 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -45,7 +45,7 @@ pub enum AxisScaling {
/// by config files or launch options.
#[derive(Debug, Default, Eq, PartialEq)]
pub struct AppConfigFields {
- pub update_rate_in_milliseconds: u64,
+ pub update_rate: u64,
pub temperature_type: temperature::TemperatureType,
pub use_dot: bool,
pub left_legend: bool,
diff --git a/src/args.rs b/src/args.rs
index 87035a6a..b384acc0 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -353,8 +353,8 @@ use CPU (3) as the default instead.
.long("rate")
.action(ArgAction::Set)
.value_name("MS")
- .help("Sets a refresh rate in ms.")
- .long_help("Sets a refresh rate in milliseconds. The minimum is 250ms, and defaults to 1000ms. Smaller values may take more computer resources.");
+ .help("Sets the data refresh rate.")
+ .long_help("Sets the data refresh rate. The minimum is 250ms, and defaults to 1000ms. Smaller values may take more computer resources.");
let time_delta = Arg::new("time_delta")
.short('d')
diff --git a/src/constants.rs b/src/constants.rs
index a76c8609..9a0cd04a 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -520,7 +520,7 @@ pub const CONFIG_TEXT: &str = r##"# This is a default config file for bottom. A
# Whether to use dot markers rather than braille.
#dot_marker = false
# The update rate of the application.
-#rate = 1000
+#rate = "1s"
# Whether to put the CPU legend to the left.
#left_legend = false
# Whether to set CPU% on a process to be based on the total CPU or just current usage.
diff --git a/src/lib.rs b/src/lib.rs
index 6424c286..86d36cb7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -484,7 +484,7 @@ pub fn create_collection_thread(
let use_current_cpu_total = app_config_fields.use_current_cpu_total;
let unnormalized_cpu = app_config_fields.unnormalized_cpu;
let show_average_cpu = app_config_fields.show_average_cpu;
- let update_time = app_config_fields.update_rate_in_milliseconds;
+ let update_time = app_config_fields.update_rate;
thread::spawn(move || {
let mut data_state = data_harvester::DataCollector::new(filters);
diff --git a/src/options.rs b/src/options.rs
index 4a4d15f5..412748a6 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -66,45 +66,45 @@ impl From<u64> for StringOrNum {
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct ConfigFlags {
- pub hide_avg_cpu: Option<bool>,
- pub dot_marker: Option<bool>,
- pub temperature_type: Option<String>,
- pub rate: Option<u64>,
- pub left_legend: Option<bool>,
- pub current_usage: Option<bool>,
- pub unnormalized_cpu: Option<bool>,
- pub group_processes: Option<bool>,
- pub case_sensitive: Option<bool>,
- pub whole_word: Option<bool>,
- pub regex: Option<bool>,
- pub basic: Option<bool>,
+ hide_avg_cpu: Option<bool>,
+ dot_marker: Option<bool>,
+ temperature_type: Option<String>,
+ rate: Option<StringOrNum>,
+ left_legend: Option<bool>,
+ current_usage: Option<bool>,
+ unnormalized_cpu: Option<bool>,
+ group_processes: Option<bool>,
+ case_sensitive: Option<bool>,
+ whole_word: Option<bool>,
+ regex: Option<bool>,
+ basic: Option<bool>,
default_time_value: Option<StringOrNum>,
time_delta: Option<StringOrNum>,
- pub autohide_time: Option<bool>,
- pub hide_time: Option<bool>,
- pub default_widget_type: Option<String>,
- pub default_widget_count: Option<u64>,
- pub expanded_on_startup: Option<bool>,
- pub use_old_network_legend: Option<bool>,
- pub hide_table_gap: Option<bool>,
- pub battery: Option<bool>,
- pub disable_click: Option<bool>,
- pub no_write: Option<bool>,
+ autohide_time: Option<bool>,
+ hide_time: Option<bool>,
+ default_widget_type: Option<String>,
+ default_widget_count: Option<u64>,
+ expanded_on_startup: Option<bool>,
+ use_old_network_legend: Option<bool>,
+ hide_table_gap: Option<bool>,
+ battery: Option<bool>,
+ disable_click: Option<bool>,
+ no_write: Option<bool>,
/// For built-in colour palettes.
- pub color: Option<String>,
- pub mem_as_value: Option<bool>,
- pub tree: Option<bool>,
+ color: Option<String>,
+ mem_as_value: Option<bool>,
+ tree: Option<bool>,
show_table_scroll_position: Option<bool>,
- pub process_command: Option<bool>,
- pub disable_advanced_kill: Option<bool>,
- pub network_use_bytes: Option<bool>,
- pub network_use_log: Option<bool>,
- pub network_use_binary_prefix: Option<bool>,
- pub enable_gpu_memory: Option<bool>,
- pub enable_cache_memory: Option<bool>,
+ process_command: Option<bool>,
+ disable_advanced_kill: Option<bool>,
+ network_use_bytes: Option<bool>,
+ network_use_log: Option<bool>,
+ network_use_binary_prefix: Option<bool>,
+ enable_gpu_memory: Option<bool>,
+ enable_cache_memory: Option<bool>,
#[serde(with = "humantime_serde")]
#[serde(default)]
- pub retention: Option<Duration>,
+ retention: Option<Duration>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
@@ -262,7 +262,7 @@ pub fn build_app(
};
let app_config_fields = AppConfigFields {
- update_rate_in_milliseconds: get_update_rate_in_milliseconds(matches, config)
+ update_rate: get_update_rate(matches, config)
.context("Update 'rate' in your config file.")?,
temperature_type: get_temperature(matches, config)
.context("Update 'temperature_type' in your config file.")?,
@@ -549,16 +549,15 @@ pub fn get_widget_layout(
Ok((bottom_layout, default_widget_id, default_widget_type))
}
-fn get_update_rate_in_milliseconds(matches: &ArgMatches, config: &Config) -> error::Result<u64> {
- let update_rate_in_milliseconds = if let Some(update_rate) = matches.get_one::<String>("rate") {
- update_rate.parse::<u64>().map_err(|_| {
- BottomError::ConfigError(
- "could not parse as a valid 64-bit unsigned integer".to_string(),
- )
- })?
+fn get_update_rate(matches: &ArgMatches, config: &Config) -> error::Result<u64> {
+ let update_rate = if let Some(update_rate) = matches.get_one::<String>("rate") {
+ try_parse_ms(update_rate)?
} else if let Some(flags) = &config.flags {
- if let Some(rate) = flags.rate {
- rate
+ if let Some(rate) = &flags.rate {
+ match rate {
+ StringOrNum::String(s) => try_parse_ms(s)?,
+ StringOrNum::Num(n) => *n,
+ }
} else {
DEFAULT_REFRESH_RATE_IN_MILLISECONDS
}
@@ -566,13 +565,13 @@ fn get_update_rate_in_milliseconds(matches: &ArgMatches, config: &Config) -> err
DEFAULT_REFRESH_RATE_IN_MILLISECONDS
};
- if update_rate_in_milliseconds < 250 {
+ if update_rate < 250 {
return Err(BottomError::ConfigError(
- "set your update rate to be at least 250 milliseconds.".to_string(),
+ "set your update rate to be at least 250 ms.".to_string(),
));
}
- Ok(update_rate_in_milliseconds)
+ Ok(update_rate)
}
fn get_temperature(
@@ -914,7 +913,7 @@ mod test {
use crate::{
app::App,
canvas::canvas_styling::CanvasStyling,
- options::{get_default_time_value, try_parse_ms, ConfigFlags},
+ options::{get_default_time_value, get_update_rate, try_parse_ms, ConfigFlags},
};
#[test]
@@ -999,6 +998,7 @@ mod test {
let flags = ConfigFlags {
time_delta: Some("2 min".to_string().into()),
default_time_value: Some("300s".to_string().into()),
+ rate: Some("1s".to_string().into()),
..Default::default()
};
@@ -1013,6 +1013,8 @@ mod test {
get_default_time_value(&matches, &config, 60 * 60 * 1000),
Ok(5 * 60 * 1000)
);
+
+ assert_eq!(get_update_rate(&matches, &config), Ok(1000));
}
#[test]
@@ -1024,6 +1026,7 @@ mod test {
let flags = ConfigFlags {
time_delta: Some("120000".to_string().into()),
default_time_value: Some("300000".to_string().into()),
+ rate: Some("1000".to_string().into()),
..Default::default()
};
@@ -1038,6 +1041,8 @@ mod test {
get_default_time_value(&matches, &config, 60 * 60 * 1000),
Ok(5 * 60 * 1000)
);
+
+ assert_eq!(get_update_rate(&matches, &config), Ok(1000));
}
#[test]
@@ -1049,6 +1054,7 @@ mod test {
let flags = ConfigFlags {
time_delta: Some(120000.into()),
default_time_value: Some(300000.into()),
+ rate: Some(1000.into()),
..Default::default()
};
@@ -1063,6 +1069,8 @@ mod test {
get_default_time_value(&matches, &config, 60 * 60 * 1000),
Ok(5 * 60 * 1000)
);
+
+ assert_eq!(get_update_rate(&matches, &config), Ok(1000));
}
fn create_app(config: Config, matches: ArgMatches) -> App {
diff --git a/tests/arg_tests.rs b/tests/arg_tests.rs
index 0bbddce8..c233c14e 100644
--- a/tests/arg_tests.rs
+++ b/tests/arg_tests.rs
@@ -15,7 +15,7 @@ fn test_small_rate() {
.assert()
.failure()
.stderr(predicate::str::contains(
- "set your update rate to be at least 250 milliseconds.",
+ "set your update rate to be at least 250 ms.",
));
}