summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2020-03-08 21:56:30 -0400
committerClementTsang <cjhtsang@uwaterloo.ca>2020-03-08 22:01:49 -0400
commitf70cf02414a5263c000f06c1b36ee19e11bf23a5 (patch)
tree8f56d975a58143b785b7c6a7cb61d0e8cb86837e
parent3026fbd1bc6ec3d757dba6ad30428812b63190c9 (diff)
Add configurable default time and interval values
Also added documentation both in app and in the README.
-rw-r--r--README.md6
-rw-r--r--src/app.rs78
-rw-r--r--src/app/data_farmer.rs4
-rw-r--r--src/constants.rs43
-rw-r--r--src/data_conversion.rs11
-rw-r--r--src/main.rs12
-rw-r--r--src/options.rs70
-rw-r--r--tests/arg_rate_tests.rs6
8 files changed, 174 insertions, 56 deletions
diff --git a/README.md b/README.md
index a0cf651d..4dda210b 100644
--- a/README.md
+++ b/README.md
@@ -118,7 +118,7 @@ Run using `btm`.
- `-v`, `--version` displays the version number and exits.
-- `-r <RATE>`, `--rate <RATE>` will set the refresh rate in _milliseconds_. Lowest it can go is 250ms, the highest it can go is 2<sup>128</sup> - 1. Defaults to 1000ms, and lower values may take more resources due to more frequent polling of data, and may be less accurate in some circumstances.
+- `-r <RATE>`, `--rate <RATE>` will set the refresh rate in _milliseconds_. Lowest it can go is 250ms, the highest it can go is 2<sup>64</sup> - 1. Defaults to 1000ms, and lower values may take more resources due to more frequent polling of data, and may be less accurate in some circumstances.
- `-l`, `--left_legend` will move external table legends to the left side rather than the right side. Right side is default.
@@ -140,6 +140,10 @@ Run using `btm`.
- `-b`, `--basic` will enable basic mode, removing all graphs from the main interface and condensing data.
+- `-t`, `--default_time_value` will set the default time interval graphs will display to (in milliseconds). Lowest is 30 seconds, defaults to 60 seconds.
+
+- `-i`, `--time_delta` will set the amount each zoom in/out action will change the time interval of a graph (in milliseconds). Lowest is 1 second, defaults to 15 seconds.
+
### Keybindings
#### General
diff --git a/src/app.rs b/src/app.rs
index 8e11f1fa..1b1cffa2 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -209,9 +209,10 @@ impl Default for AppHelpDialogState {
}
/// AppConfigFields is meant to cover basic fields that would normally be set
-/// by config files or launch options. Don't need to be mutable (set and forget).
+/// by config files or launch options.
+#[derive(Default)]
pub struct AppConfigFields {
- pub update_rate_in_milliseconds: u128,
+ pub update_rate_in_milliseconds: u64,
pub temperature_type: temperature::TemperatureType,
pub use_dot: bool,
pub left_legend: bool,
@@ -219,6 +220,8 @@ pub struct AppConfigFields {
pub use_current_cpu_total: bool,
pub show_disabled_data: bool,
pub use_basic_mode: bool,
+ pub default_time_value: u64,
+ pub time_interval: u64,
}
/// Network specific
@@ -227,7 +230,7 @@ pub struct NetworkState {
pub is_showing_rx: bool,
pub is_showing_tx: bool,
pub zoom_level: f64,
- pub display_time: u128,
+ pub display_time: u64,
pub force_update: bool,
}
@@ -238,7 +241,7 @@ impl Default for NetworkState {
is_showing_rx: true,
is_showing_tx: true,
zoom_level: 100.0,
- display_time: constants::DEFAULT_DISPLAY_MILLISECONDS,
+ display_time: constants::DEFAULT_TIME_MILLISECONDS,
force_update: false,
}
}
@@ -249,7 +252,7 @@ pub struct CpuState {
pub is_showing_tray: bool,
pub zoom_level: f64,
pub core_show_vec: Vec<bool>,
- pub display_time: u128,
+ pub display_time: u64,
pub force_update: bool,
}
@@ -259,7 +262,7 @@ impl Default for CpuState {
is_showing_tray: false,
zoom_level: 100.0,
core_show_vec: Vec::new(),
- display_time: constants::DEFAULT_DISPLAY_MILLISECONDS,
+ display_time: constants::DEFAULT_TIME_MILLISECONDS,
force_update: false,
}
}
@@ -271,7 +274,7 @@ pub struct MemState {
pub is_showing_ram: bool,
pub is_showing_swap: bool,
pub zoom_level: f64,
- pub display_time: u128,
+ pub display_time: u64,
pub force_update: bool,
}
@@ -282,7 +285,7 @@ impl Default for MemState {
is_showing_ram: true,
is_showing_swap: true,
zoom_level: 100.0,
- display_time: constants::DEFAULT_DISPLAY_MILLISECONDS,
+ display_time: constants::DEFAULT_TIME_MILLISECONDS,
force_update: false,
}
}
@@ -320,10 +323,19 @@ impl App {
// TODO: [REFACTOR] use builder pattern instead.
pub fn new(
show_average_cpu: bool, temperature_type: temperature::TemperatureType,
- update_rate_in_milliseconds: u128, use_dot: bool, left_legend: bool,
+ update_rate_in_milliseconds: u64, use_dot: bool, left_legend: bool,
use_current_cpu_total: bool, current_widget_selected: WidgetPosition,
- show_disabled_data: bool, use_basic_mode: bool,
+ show_disabled_data: bool, use_basic_mode: bool, default_time_value: u64,
+ time_interval: u64,
) -> App {
+ let mut cpu_state = CpuState::default();
+ let mut mem_state = MemState::default();
+ let mut net_state = NetworkState::default();
+
+ cpu_state.display_time = default_time_value;
+ mem_state.display_time = default_time_value;
+ net_state.display_time = default_time_value;
+
App {
process_sorting_type: processes::ProcessSorting::CPU,
process_sorting_reverse: true,
@@ -365,12 +377,14 @@ impl App {
use_current_cpu_total,
show_disabled_data,
use_basic_mode,
+ default_time_value,
+ time_interval,
},
is_expanded: false,
is_resized: false,
- cpu_state: CpuState::default(),
- mem_state: MemState::default(),
- net_state: NetworkState::default(),
+ cpu_state,
+ mem_state,
+ net_state,
}
}
@@ -947,7 +961,7 @@ impl App {
if current_key_press_inst
.duration_since(self.last_key_press)
.as_millis()
- > constants::MAX_KEY_TIMEOUT_IN_MILLISECONDS
+ > constants::MAX_KEY_TIMEOUT_IN_MILLISECONDS as u128
{
self.reset_multi_tap_keys();
}
@@ -1489,20 +1503,23 @@ impl App {
fn zoom_out(&mut self) {
match self.current_widget_selected {
WidgetPosition::Cpu => {
- if self.cpu_state.display_time < constants::STALE_MAX_MILLISECONDS {
- self.cpu_state.display_time += constants::TIME_CHANGE_MILLISECONDS;
+ let new_time = self.cpu_state.display_time + self.app_config_fields.time_interval;
+ if new_time <= constants::STALE_MAX_MILLISECONDS {
+ self.cpu_state.display_time = new_time;
self.cpu_state.force_update = true;
}
}
WidgetPosition::Mem => {
- if self.mem_state.display_time < constants::STALE_MAX_MILLISECONDS {
- self.mem_state.display_time += constants::TIME_CHANGE_MILLISECONDS;
+ let new_time = self.mem_state.display_time + self.app_config_fields.time_interval;
+ if new_time <= constants::STALE_MAX_MILLISECONDS {
+ self.mem_state.display_time = new_time;
self.mem_state.force_update = true;
}
}
WidgetPosition::Network => {
- if self.net_state.display_time < constants::STALE_MAX_MILLISECONDS {
- self.net_state.display_time += constants::TIME_CHANGE_MILLISECONDS;
+ let new_time = self.net_state.display_time + self.app_config_fields.time_interval;
+ if new_time <= constants::STALE_MAX_MILLISECONDS {
+ self.net_state.display_time = new_time;
self.net_state.force_update = true;
}
}
@@ -1513,20 +1530,23 @@ impl App {
fn zoom_in(&mut self) {
match self.current_widget_selected {
WidgetPosition::Cpu => {
- if self.cpu_state.display_time > constants::STALE_MIN_MILLISECONDS {
- self.cpu_state.display_time -= constants::TIME_CHANGE_MILLISECONDS;
+ let new_time = self.cpu_state.display_time - self.app_config_fields.time_interval;
+ if new_time >= constants::STALE_MIN_MILLISECONDS {
+ self.cpu_state.display_time = new_time;
self.cpu_state.force_update = true;
}
}
WidgetPosition::Mem => {
- if self.mem_state.display_time > constants::STALE_MIN_MILLISECONDS {
- self.mem_state.display_time -= constants::TIME_CHANGE_MILLISECONDS;
+ let new_time = self.mem_state.display_time - self.app_config_fields.time_interval;
+ if new_time >= constants::STALE_MIN_MILLISECONDS {
+ self.mem_state.display_time = new_time;
self.mem_state.force_update = true;
}
}
WidgetPosition::Network => {
- if self.net_state.display_time > constants::STALE_MIN_MILLISECONDS {
- self.net_state.display_time -= constants::TIME_CHANGE_MILLISECONDS;
+ let new_time = self.net_state.display_time - self.app_config_fields.time_interval;
+ if new_time >= constants::STALE_MIN_MILLISECONDS {
+ self.net_state.display_time = new_time;
self.net_state.force_update = true;
}
}
@@ -1537,15 +1557,15 @@ impl App {
fn reset_zoom(&mut self) {
match self.current_widget_selected {
WidgetPosition::Cpu => {
- self.cpu_state.display_time = constants::DEFAULT_DISPLAY_MILLISECONDS;
+ self.cpu_state.display_time = self.app_config_fields.default_time_value;
self.cpu_state.force_update = true;
}
WidgetPosition::Mem => {
- self.mem_state.display_time = constants::DEFAULT_DISPLAY_MILLISECONDS;
+ self.mem_state.display_time = self.app_config_fields.default_time_value;
self.mem_state.force_update = true;
}
WidgetPosition::Network => {
- self.net_state.display_time = constants::DEFAULT_DISPLAY_MILLISECONDS;
+ self.net_state.display_time = self.app_config_fields.default_time_value;
self.net_state.force_update = true;
}
_ => {}
diff --git a/src/app/data_farmer.rs b/src/app/data_farmer.rs
index d3d77ca2..5fa766a5 100644
--- a/src/app/data_farmer.rs
+++ b/src/app/data_farmer.rs
@@ -84,12 +84,12 @@ impl DataCollection {
self.frozen_instant = Some(self.current_instant);
}
- pub fn clean_data(&mut self, max_time_millis: u128) {
+ pub fn clean_data(&mut self, max_time_millis: u64) {
let current_time = Instant::now();
let mut remove_index = 0;
for entry in &self.timed_data_vec {
- if current_time.duration_since(entry.0).as_millis() >= max_time_millis {
+ if current_time.duration_since(entry.0).as_millis() >= max_time_millis as u128 {
remove_index += 1;
} else {
break;
diff --git a/src/constants.rs b/src/constants.rs
index b177d141..f488ccfe 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -1,15 +1,15 @@
// How long to store data.
-pub const STALE_MAX_MILLISECONDS: u128 = 300 * 1000; // Keep 5 minutes of data.
+pub const STALE_MAX_MILLISECONDS: u64 = 300 * 1000; // Keep 5 minutes of data.
// How much data is SHOWN
-pub const DEFAULT_DISPLAY_MILLISECONDS: u128 = 60 * 1000; // Defaults to 1 min.
-pub const STALE_MIN_MILLISECONDS: u128 = 30 * 1000; // Lowest is 30 seconds
-pub const TIME_CHANGE_MILLISECONDS: u128 = 15 * 1000; // How much to increment each time
+pub const DEFAULT_TIME_MILLISECONDS: u64 = 60 * 1000; // Defaults to 1 min.
+pub const STALE_MIN_MILLISECONDS: u64 = 30 * 1000; // Lowest is 30 seconds
+pub const TIME_CHANGE_MILLISECONDS: u64 = 15 * 1000; // How much to increment each time
pub const TICK_RATE_IN_MILLISECONDS: u64 = 200;
// How fast the screen refreshes
-pub const DEFAULT_REFRESH_RATE_IN_MILLISECONDS: u128 = 1000;
-pub const MAX_KEY_TIMEOUT_IN_MILLISECONDS: u128 = 1000;
+pub const DEFAULT_REFRESH_RATE_IN_MILLISECONDS: u64 = 1000;
+pub const MAX_KEY_TIMEOUT_IN_MILLISECONDS: u64 = 1000;
// Number of colours to generate for the CPU chart/table
pub const NUM_COLOURS: i32 = 256;
@@ -30,7 +30,7 @@ lazy_static! {
}
// Help text
-pub const GENERAL_HELP_TEXT: [&str; 15] = [
+pub const GENERAL_HELP_TEXT: [&str; 18] = [
"General Keybindings\n\n",
"q, Ctrl-c Quit bottom\n",
"Esc Close filters, dialog boxes, etc.\n",
@@ -46,6 +46,9 @@ pub const GENERAL_HELP_TEXT: [&str; 15] = [
"G Skip to the last entry of a list\n",
"Enter Maximize the currently selected widget\n",
"/ Filter out graph lines (only CPU at the moment)\n",
+ "+ Zoom in (decrease time range)\n",
+ "- Zoom out (increase time range)\n",
+ "= Reset zoom\n",
];
pub const PROCESS_HELP_TEXT: [&str; 8] = [
@@ -90,15 +93,34 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
# is also set here.
[flags]
+# Whether to display an average cpu entry.
#avg_cpu = true
+
+# Whether to use dot markers rather than braille.
#dot_marker = false
+
+# The update rate of the application.
#rate = 1000
+
+# 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.
#current_usage = false
+
+# Whether to group processes with the same name together by default.
#group_processes = false
+
+# Whether to make process searching case sensitive by default.
#case_sensitive = false
+
+# Whether to make process searching look for matching the entire word by default.
#whole_word = true
+
+# Whether to make process searching use regex by default.
#regex = true
+
+# Whether to show CPU entries in the legend when they are hidden.
#show_disabled_data = true
# Defaults to Celsius. Temperature is one of:
@@ -117,6 +139,11 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
#default_widget = "network_default"
#default_widget = "process_default"
+# The default time interval (in milliseconds).
+#default_time_value = 60000
+
+# The time delta on each zoom in/out action (in milliseconds).
+# time_delta = 15000
# These are all the components that support custom theming. Currently, it only
# supports taking in a string representing a hex colour. Note that colour support
@@ -132,7 +159,7 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
# Represents the colour of the label each widget has.
#widget_title_color="#cc241d"
-# Represents the average CPU color
+# Represents the average CPU color.
#avg_cpu_color="#d3869b"
# Represents the colour the core will use in the CPU legend and graph.
diff --git a/src/data_conversion.rs b/src/data_conversion.rs
index 341ada48..c99bf75f 100644
--- a/src/data_conversion.rs
+++ b/src/data_conversion.rs
@@ -102,7 +102,7 @@ pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec<Vec<S
}
pub fn convert_cpu_data_points(
- show_avg_cpu: bool, current_data: &data_farmer::DataCollection, display_time: u128,
+ show_avg_cpu: bool, current_data: &data_farmer::DataCollection, display_time: u64,
is_frozen: bool,
) -> Vec<ConvertedCpuData> {
let mut cpu_data_vector: Vec<ConvertedCpuData> = Vec::new();
@@ -156,7 +156,7 @@ pub fn convert_cpu_data_points(
}
pub fn convert_mem_data_points(
- current_data: &data_farmer::DataCollection, display_time: u128, is_frozen: bool,
+ current_data: &data_farmer::DataCollection, display_time: u64, is_frozen: bool,
) -> Vec<Point> {
let mut result: Vec<Point> = Vec::new();
let current_time = if is_frozen {
@@ -190,7 +190,7 @@ pub fn convert_mem_data_points(
}
pub fn convert_swap_data_points(
- current_data: &data_farmer::DataCollection, display_time: u128, is_frozen: bool,
+ current_data: &data_farmer::DataCollection, display_time: u64, is_frozen: bool,
) -> Vec<Point> {
let mut result: Vec<Point> = Vec::new();
let current_time = if is_frozen {
@@ -260,7 +260,7 @@ pub fn convert_mem_labels(current_data: &data_farmer::DataCollection) -> (String
}
pub fn get_rx_tx_data_points(
- current_data: &data_farmer::DataCollection, display_time: u128, is_frozen: bool,
+ current_data: &data_farmer::DataCollection, display_time: u64, is_frozen: bool,
) -> (Vec<Point>, Vec<Point>) {
let mut rx: Vec<Point> = Vec::new();
let mut tx: Vec<Point> = Vec::new();
@@ -275,6 +275,7 @@ pub fn get_rx_tx_data_points(
current_data.current_instant
};
+ // TODO: [REFACTOR] Can we use combine on this, CPU, and MEM?
for (time, data) in &current_data.timed_data_vec {
let time_from_start: f64 =
(display_time as f64 - current_time.duration_since(*time).as_millis() as f64).floor();
@@ -302,7 +303,7 @@ pub fn get_rx_tx_data_points(
}
pub fn convert_network_data_points(
- current_data: &data_farmer::DataCollection, display_time: u128, is_frozen: bool,
+ current_data: &data_farmer::DataCollection, display_time: u64, is_frozen: bool,
) -> ConvertedNetworkData {
let (rx, tx) = get_rx_tx_data_points(current_data, display_time, is_frozen);
diff --git a/src/main.rs b/src/main.rs
index adf12e7d..9d09c262 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -85,7 +85,9 @@ fn get_matches() -> clap::ArgMatches<'static> {
(@arg CASE_SENSITIVE: -S --case_sensitive "Match case when searching by default.")
(@arg WHOLE_WORD: -W --whole_word "Match whole word when searching by default.")
(@arg REGEX_DEFAULT: -R --regex "Use regex in searching by default.")
- (@arg SHOW_DISABLED_DATA: -s --show_disabled_data "Show disabled data entries.")
+ (@arg SHOW_DISABLED_DATA: -s --show_disabled_data "Show disabled data entries.")
+ (@arg DEFAULT_TIME_VALUE: -t --default_time_value +takes_value "Default time value for graphs in milliseconds; minimum is 30s, defaults to 60s.")
+ (@arg TIME_DELTA: -i --time_delta +takes_value "The amount changed upon zooming in/out in milliseconds; minimum is 1s, defaults to 15s.")
(@group DEFAULT_WIDGET =>
(@arg CPU_WIDGET: --cpu_default "Selects the CPU widget to be selected by default.")
(@arg MEM_WIDGET: --memory_default "Selects the memory widget to be selected by default.")
@@ -105,7 +107,7 @@ fn main() -> error::Result<()> {
let config: Config = create_config(matches.value_of("CONFIG_LOCATION"))?;
- let update_rate_in_milliseconds: u128 =
+ let update_rate_in_milliseconds: u64 =
get_update_rate_in_milliseconds(&matches.value_of("RATE_MILLIS"), &config)?;
// Set other settings
@@ -117,6 +119,8 @@ fn main() -> error::Result<()> {
let current_widget_selected = get_default_widget(&matches, &config);
let show_disabled_data = get_show_disabled_data_option(&matches, &config);
let use_basic_mode = get_use_basic_mode_option(&matches, &config);
+ let default_time_value = get_default_time_value_option(&matches, &config)?;
+ let time_interval = get_time_interval_option(&matches, &config)?;
// Create "app" struct, which will control most of the program and store settings/state
let mut app = App::new(
@@ -129,6 +133,8 @@ fn main() -> error::Result<()> {
current_widget_selected,
show_disabled_data,
use_basic_mode,
+ default_time_value,
+ time_interval,
);
enable_app_grouping(&matches, &config, &mut app);
@@ -369,9 +375,9 @@ fn handle_key_event_or_break(
app.reset();
}
}
- KeyCode::Char('u') => app.clear_search(),
KeyCode::Char('a') => app.skip_cursor_beginning(),
KeyCode::Char('e') => app.skip_cursor_end(),
+ KeyCode::Char('u') => app.clear_search(),
// KeyCode::Char('j') => {}, // Move down
// KeyCode::Char('k') => {}, // Move up
// KeyCode::Char('h') => {}, // Move right
diff --git a/src/options.rs b/src/options.rs
index 372165bd..77884e78 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -27,6 +27,8 @@ pub struct ConfigFlags {
pub default_widget: Option<String>,
pub show_disabled_data: Option<bool>,
pub basic: Option<bool>,
+ pub default_time_value: Option<u64>,
+ pub time_delta: Option<u64>,
//disabled_cpu_cores: Option<Vec<u64>>, // TODO: [FEATURE] Enable disabling cores in config/flags
}
@@ -52,12 +54,12 @@ pub struct ConfigColours {
pub fn get_update_rate_in_milliseconds(
update_rate: &Option<&str>, config: &Config,
-) -> error::Result<u128> {
+) -> error::Result<u64> {
let update_rate_in_milliseconds = if let Some(update_rate) = update_rate {
- update_rate.parse::<u128>()?
+ update_rate.parse::<u64>()?
} else if let Some(flags) = &config.flags {
if let Some(rate) = flags.rate {
- rate as u128
+ rate
} else {
DEFAULT_REFRESH_RATE_IN_MILLISECONDS
}
@@ -67,11 +69,11 @@ pub fn get_update_rate_in_milliseconds(
if update_rate_in_milliseconds < 250 {
return Err(BottomError::InvalidArg(
- "Please set your update rate to be greater than 250 milliseconds.".to_string(),
+ "Please set your update rate to be at least 250 milliseconds.".to_string(),
));
- } else if update_rate_in_milliseconds > u128::from(std::u64::MAX) {
+ } else if update_rate_in_milliseconds as u128 > std::u64::MAX as u128 {
return Err(BottomError::InvalidArg(
- "Please set your update rate to be less than unsigned INT_MAX.".to_string(),
+ "Please set your update rate to be at most unsigned INT_MAX.".to_string(),
));
}
@@ -178,6 +180,62 @@ pub fn get_use_basic_mode_option(matches: &clap::ArgMatches<'static>, config: &C
false
}
+pub fn get_default_time_value_option(
+ matches: &clap::ArgMatches<'static>, config: &Config,
+) -> error::Result<u64> {
+ let default_time = if let Some(default_time_value) = matches.value_of("DEFAULT_TIME_VALUE") {
+ default_time_value.parse::<u64>()?
+ } else if let Some(flags) = &config.flags {
+ if let Some(default_time_value) = flags.default_time_value {
+ default_time_value
+ } else {
+ DEFAULT_TIME_MILLISECONDS
+ }
+ } else {
+ DEFAULT_TIME_MILLISECONDS
+ };
+
+ if default_time < 30000 {
+ return Err(BottomError::InvalidArg(
+ "Please set your default value to be at least 30 seconds.".to_string(),
+ ));
+ } else if default_time as u128 > std::u64::MAX as u128 {
+ return Err(BottomError::InvalidArg(
+ "Please set your default value to be at most unsigned INT_MAX.".to_string(),
+ ));
+ }
+
+ Ok(default_time)
+}
+
+pub fn get_time_interval_option(
+ matches: &clap::ArgMatches<'static>, config: &Config,
+) -> error::Result<u64> {
+ let time_interval = if let Some(time_interval) = matches.value_of("TIME_DELTA") {
+ time_interval.parse::<u64>()?
+ } else if let Some(flags) = &config.flags {
+ if let Some(time_interval) = flags.time_delta {
+ time_interval
+ } else {
+ TIME_CHANGE_MILLISECONDS
+ }
+ } else {
+ TIME_CHANGE_MILLISECONDS
+ };
+
+ if time_interval < 1000 {
+ return Err(BottomError::InvalidArg(
+ "Please set your time interval to be at least 1 second.".to_string(),
+ ));
+ } else if time_interval as u128 > std::u64::MAX as u128 {
+ return Err(BottomError::InvalidArg(
+ "Please set your time interval to be at most unsigned INT_MAX.".to_string(),
+ ));
+ }
+
+ Ok(time_interval)
+}
+
pub fn enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("GROUP_PROCESSES") {
app.toggle_grouping();
diff --git a/tests/arg_rate_tests.rs b/tests/arg_rate_tests.rs
index 85b3da0f..7f22431c 100644
--- a/tests/arg_rate_tests.rs
+++ b/tests/arg_rate_tests.rs
@@ -28,7 +28,9 @@ fn test_small_rate() -> Result<(), Box<dyn std::error::Error>> {
.arg("249")
.assert()
.failure()
- .stderr(predicate::str::contains("rate to be greater than 250"));
+ .stderr(predicate::str::contains(
+ "Please set your update rate to be at least 250 milliseconds.",
+ ));
Ok(())
}
@@ -40,7 +42,7 @@ fn test_large_rate() -> Result<(), Box<dyn std::error::Error>> {
.assert()
.failure()
.stderr(predicate::str::contains(
- "rate to be less than unsigned INT_MAX.",
+ "Please set your update rate to be at most unsigned INT_MAX.",
));
Ok(())
}