diff options
-rw-r--r-- | Cargo.toml | 5 | ||||
-rw-r--r-- | src/bin/main.rs | 12 | ||||
-rw-r--r-- | src/lib.rs | 6 | ||||
-rw-r--r-- | src/options.rs | 31 | ||||
-rw-r--r-- | src/options/args.rs | 714 |
5 files changed, 141 insertions, 627 deletions
@@ -19,7 +19,9 @@ exclude = [ "desktop/", "docs/", "sample_configs/", + "schema", "scripts/", + "wix/", ".all-contributorsrc", ".cirrus.yml", ".gitignore", @@ -29,6 +31,9 @@ exclude = [ "codecov.yml", "CONTRIBUTING.md", "Cross.toml", + "debug.log", + "flamegraph.svg", + "perf.data", "rustfmt.toml", ] rust-version = "1.74.0" # The oldest version I've tested that should still build - note this is not an official MSRV! diff --git a/src/bin/main.rs b/src/bin/main.rs index c7841b4d..3589c1d7 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -37,7 +37,7 @@ use tui::{backend::CrosstermBackend, Terminal}; fn main() -> Result<()> { // let _profiler = dhat::Profiler::new_heap(); - let matches = args::get_matches(); + let args = args::get_args(); #[cfg(feature = "logging")] { @@ -51,27 +51,29 @@ fn main() -> Result<()> { // Read from config file. let config = { - let config_path = read_config(matches.get_one::<String>("config_location")) + let config_path = read_config(args.general.config_location.as_deref()) .context("Unable to access the given config file location.")?; create_or_get_config(&config_path) .context("Unable to properly parse or create the config file.")? }; + // TODO: merge config and args + // Get widget layout separately let (widget_layout, default_widget_id, default_widget_type_option) = - get_widget_layout(&matches, &config) + get_widget_layout(&args, &config) .context("Found an issue while trying to build the widget layout.")?; // FIXME: Should move this into build app or config let styling = { - let colour_scheme = get_color_scheme(&matches, &config)?; + let colour_scheme = get_color_scheme(&args, &config)?; CanvasStyling::new(colour_scheme, &config)? }; // Create an "app" struct, which will control most of the program and store settings/state let mut app = init_app( - matches, + args, config, &widget_layout, default_widget_id, @@ -35,7 +35,7 @@ use std::{ fs, io::{stderr, stdout, Write}, panic::PanicInfo, - path::PathBuf, + path::{Path, PathBuf}, sync::{ mpsc::{Receiver, Sender}, Arc, Condvar, Mutex, @@ -202,9 +202,9 @@ pub fn handle_key_event_or_break( false } -pub fn read_config(config_location: Option<&String>) -> error::Result<Option<PathBuf>> { +pub fn read_config(config_location: Option<&Path>) -> error::Result<Option<PathBuf>> { let config_path = if let Some(conf_loc) = config_location { - Some(PathBuf::from(conf_loc.as_str())) + Some(conf_loc.to_path_buf()) } else if cfg!(target_os = "windows") { if let Some(home_path) = dirs::config_dir() { let mut path = home_path; diff --git a/src/options.rs b/src/options.rs index 7cf2fbaf..d70ef288 100644 --- a/src/options.rs +++ b/src/options.rs @@ -22,7 +22,10 @@ use regex::Regex; #[cfg(feature = "battery")] use starship_battery::Manager; -use self::config::{layout::Row, IgnoreList, StringOrNum}; +use self::{ + args::BottomArgs, + config::{layout::Row, IgnoreList, StringOrNum}, +}; use crate::{ app::{filter::Filter, layout_manager::*, *}, canvas::{components::time_chart::LegendPosition, styling::CanvasStyling, ColourScheme}, @@ -46,6 +49,16 @@ macro_rules! is_flag_enabled { } }; + ($arg:expr, $config:expr, $cfg_flag:ident) => { + if let Some(flag) = $arg { + flag + } else if let Some(flags) = &$config.flags { + flags.$cfg_flag.unwrap_or(false) + } else { + false + } + }; + ($cmd_flag:literal, $cfg_flag:ident, $matches:expr, $config:expr) => { if $matches.get_flag($cmd_flag) { true @@ -360,9 +373,9 @@ pub fn init_app( } pub fn get_widget_layout( - matches: &ArgMatches, config: &Config, + args: &BottomArgs, config: &Config, ) -> error::Result<(BottomLayout, u64, Option<BottomWidgetType>)> { - let cpu_left_legend = is_flag_enabled!(cpu_left_legend, matches, config); + let cpu_left_legend = is_flag_enabled!(args.cpu.left_legend, config, cpu_left_legend); let (default_widget_type, mut default_widget_count) = get_default_widget_and_count(matches, config)?; @@ -855,7 +868,7 @@ mod test { #[test] fn matches_human_times() { let config = Config::default(); - let app = crate::args::build_app(); + let app = crate::args::build_cmd(); { let app = app.clone(); @@ -882,7 +895,7 @@ mod test { #[test] fn matches_number_times() { let config = Config::default(); - let app = crate::args::build_app(); + let app = crate::args::build_cmd(); { let app = app.clone(); @@ -908,7 +921,7 @@ mod test { #[test] fn config_human_times() { - let app = crate::args::build_app(); + let app = crate::args::build_cmd(); let matches = app.get_matches_from(["btm"]); let mut config = Config::default(); @@ -939,7 +952,7 @@ mod test { #[test] fn config_number_times_as_string() { - let app = crate::args::build_app(); + let app = crate::args::build_cmd(); let matches = app.get_matches_from(["btm"]); let mut config = Config::default(); @@ -970,7 +983,7 @@ mod test { #[test] fn config_number_times_as_num() { - let app = crate::args::build_app(); + let app = crate::args::build_cmd(); let matches = app.get_matches_from(["btm"]); let mut config = Config::default(); @@ -1011,7 +1024,7 @@ mod test { // typos/mixing up. Use proc macros to unify on one struct? #[test] fn verify_cli_options_build() { - let app = crate::args::build_app(); + let app = crate::args::build_cmd(); let default_app = { let app = app.clone(); diff --git a/src/options/args.rs b/src/options/args.rs index 458a1178..e7981e0a 100644 --- a/src/options/args.rs +++ b/src/options/args.rs @@ -5,7 +5,7 @@ // TODO: New sections are misaligned! See if we can get that fixed. -use std::{cmp::Ordering, path::PathBuf}; +use std::path::PathBuf; use clap::*; use indoc::indoc; @@ -40,37 +40,6 @@ const CHART_WIDGET_POSITIONS: [&str; 9] = [ "bottom-right", ]; -pub fn get_matches() -> ArgMatches { - build_app().get_matches() -} - -/// Returns an [`Ordering`] for two [`Arg`] values. -/// -/// Note this assumes that they both have a _long_ name, and will -/// panic if either are missing! -fn sort_args(a: &Arg, b: &Arg) -> Ordering { - let a = a.get_long().unwrap(); - let b = b.get_long().unwrap(); - - a.cmp(b) -} - -/// Create an array of [`Arg`] values. If there is more than one value, then -/// they will be sorted by their long name. Note this sort will panic if -/// any [`Arg`] does not have a long name! -macro_rules! args { - ( $arg:expr $(,)?) => { - [$arg] - }; - ( $( $arg:expr ),+ $(,)? ) => { - { - let mut args = [ $( $arg, )* ]; - args.sort_unstable_by(sort_args); - args - } - }; -} - /// Represents the arguments that can be passed in to bottom. #[derive(Parser, Debug)] #[command( @@ -86,49 +55,49 @@ macro_rules! args { )] pub struct BottomArgs { #[command(flatten)] - pub(crate) general: GeneralArgs, + pub general: GeneralArgs, #[command(flatten)] - pub(crate) process: ProcessArgs, + pub process: ProcessArgs, #[command(flatten)] - pub(crate) temperature: TemperatureArgs, + pub temperature: TemperatureArgs, #[command(flatten)] - pub(crate) cpu: CpuArgs, + pub cpu: CpuArgs, #[command(flatten)] - pub(crate) memory: MemoryArgs, + pub memory: MemoryArgs, #[command(flatten)] - pub(crate) network: NetworkArgs, + pub network: NetworkArgs, #[cfg(feature = "battery")] #[command(flatten)] - pub(crate) battery: BatteryArgs, + pub battery: BatteryArgs, #[cfg(feature = "gpu")] #[command(flatten)] - pub(crate) gpu: GpuArgs, + pub gpu: GpuArgs, #[command(flatten)] - pub(crate) style: StyleArgs, + pub style: StyleArgs, #[command(flatten)] - pub(crate) other: OtherArgs, + pub other: OtherArgs, } /// General arguments/config options. #[derive(Args, Clone, Debug)] #[command(next_help_heading = "General Options", rename_all = "snake_case")] -pub(crate) struct GeneralArgs { +pub struct GeneralArgs { #[arg( long, help = "Temporarily shows the time scale in graphs.", long = "Automatically hides the time scale in graphs after being shown for a brief moment when zoomed \ - in/out. If time is disabled via --hide_time then this will have no effect." + in/out. If time is disabled using --hide_time then this will have no effect." )] - pub(crate) autohide_time: Option<bool>, + pub autohide_time: Option<bool>, #[arg( short = 'b', @@ -136,7 +105,7 @@ pub(crate) struct GeneralArgs { help = "Hides graphs and uses a more basic look.", long_help = "Hides graphs and uses a more basic look, largely inspired by htop's design." )] - pub(crate) basic: Option<bool>, + pub basic: Option<bool>, #[arg( short = 'C', @@ -148,7 +117,7 @@ pub(crate) struct GeneralArgs { If it doesn't exist, a default config file is created at the path. If no path is provided, \ the default config location will be used." )] - pub(crate) config_location: Option<PathBuf>, + pub config_location: Option<PathBuf>, #[arg( short = 't', @@ -158,38 +127,36 @@ pub(crate) struct GeneralArgs { long_help = "Default time value for graphs. Either a number in milliseconds or a 'human duration' \ (e.g. 60s, 10m). Defaults to 60s, must be at least 30s." )] - pub(crate) default_time_value: Option<String>, + pub default_time_value: Option<String>, // TODO: Charts are broken in the manpage #[arg( long, requires_all = ["default_widget_type"], value_name = "N", - help = "Sets the n'th selected widget type as the default. Use --help for more info.", + help = "Sets the N'th selected widget type as the default.", long_help = indoc! { - "Sets the n'th selected widget type to use as the default widget. - Requires 'default_widget_type' to also be set, and defaults to 1. + "Sets the N'th selected widget type to use as the default widget. Requires 'default_widget_type' to also be \ + set, and defaults to 1. - This reads from left to right, top to bottom. For example, suppose - we have a layout that looks like: + This reads from left to right, top to bottom. For example, suppose we have a layout that looks like: +-------------------+-----------------------+ | CPU (1) | CPU (2) | +---------+---------+-------------+---------+ | Process | CPU (3) | Temperature | CPU (4) | +---------+---------+-------------+---------+ - And we set our default widget type to 'CPU'. If we set - '--default_widget_count 1', then it would use the CPU (1) as - the default widget. If we set '--default_widget_count 3', it would - use CPU (3) as the default instead." + And we set our default widget type to 'CPU'. If we set '--default_widget_count 1', then it would use the \ + CPU (1) as the default widget. If we set '--default_widget_count 3', it would use CPU (3) as the default \ + instead." } )] - pub(crate) default_widget_count: Option<u32>, + pub default_widget_count: Option<u32>, #[arg( long, value_name = "WIDGET", - help = "Sets the default widget type. Use --help for more info.\n", // Newline to force the possible values to be on the next line. + help = "Sets the default widget type. Use --help for more info.", long_help = indoc!{ "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 \ @@ -202,7 +169,7 @@ pub(crate) struct GeneralArgs { | Process | CPU (3) | Temperature | CPU (4) | +---------+---------+-------------+---------+ - Setting '--default_widget_type Temp' will make the temperature widget selected by default." + Then, setting '--default_widget_type temperature' will make the temperature widget selected by default." }, value_parser = [ "cpu", @@ -221,22 +188,23 @@ pub(crate) struct GeneralArgs { "battery", ], )] - pub(crate) default_widget_type: Option<String>, + pub default_widget_type: Option<String>, #[arg( long, help = "Disables mouse clicks.", long_help = "Disables mouse clicks from interacting with bottom." )] - pub(crate) disable_click: Option<bool>, + pub disable_click: Option<bool>, + // TODO: Change this to accept a string with the type of marker. #[arg( short = 'm', long, help = "Uses a dot marker for graphs.", long_help = "Uses a dot marker for graphs as opposed to the default braille marker." )] - pub(crate) dot_marker: Option<bool>, + pub dot_marker: Option<bool>, #[arg( short = 'e', @@ -244,13 +212,13 @@ pub(crate) struct GeneralArgs { help = "Expand the default widget upon starting the app.", long_help = "Expand the default widget upon starting the app. This flag has no effect in basic mode (--basic)." )] - pub(crate) expanded: Option<bool>, + pub expanded: Option<bool>, #[arg(long, help = "Hides spacing between table headers and entries.")] - pub(crate) hide_table_gap: Option<bool>, + pub hide_table_gap: Option<bool>, #[arg(long, help = "Hides the time scale from being shown.")] - pub(crate) hide_time: Option<bool>, + pub hide_time: Option<bool>, #[arg( short = 'r', @@ -261,7 +229,7 @@ pub(crate) struct GeneralArgs { (e.g. 1s, 1m). Defaults to 1s, must be at least 250ms. Smaller values may result in \ higher system resource usage." )] - pub(crate) rate: Option<String>, + pub rate: Option<String>, #[arg( long, @@ -271,227 +239,37 @@ pub(crate) struct GeneralArgs { (e.g. 10m, 1h). Defaults to 10 minutes, and must be at least 1 minute. Larger values \ may result in higher memory usage." )] - pub(crate) retention: Option<String>, + pub retention: Option<String>, - #[arg(long, help = "Show the current item entry position for table widgets.")] - pub(crate) show_table_scroll_position: Option<bool>, + #[arg( + long, + help = "Shows the list scroll position tracker in the widget title for table widgets." + )] + pub show_table_scroll_position: Option<bool>, #[arg( short = 'd', long, value_name = "TIME", help = "The amount of time changed upon zooming.", - long_help = "How much time the x-axis shifts by each time you zoom in or out. Either a number in milliseconds \ - or a 'human duration' (e.g. 15s, 1m). Defaults to 15 seconds." + long_help = "The amount of time changed when zooming in/out. Takes a number in \ + milliseconds or a human duration (e.g. 30s). The minimum is 1s, and \ + defaults to 15s." )] - pub(crate) time_delta: Option<String>, -} - -fn general_args(cmd: Command) -> Command { - let cmd = cmd.next_help_heading("General Options"); - - let autohide_time = Arg::new("autohide_time") - .long("autohide_time") - .action(ArgAction::SetTrue) - .help("Temporarily shows the time scale in graphs.") - .long_help( - "Automatically hides the time scale in graphs after being shown for a brief moment when zoomed \ - in/out. If time is disabled via --hide_time then this will have no effect." - ); - - let basic = Arg::new("basic") - .short('b') - .long("basic") - .action(ArgAction::SetTrue) - .help("Hides graphs and uses a more basic look.") - .long_help("Hides graphs and uses a more basic look, largely inspired by htop's design."); - - let config_location = Arg::new("config_location") - .short('C') - .long("config") - .action(ArgAction::Set) - .value_name("CONFIG PATH") - .help("Sets the location of the config file.") - .long_help( - "Sets the location of the config file. Expects a config file in the TOML format. \ - If it doesn't exist, a default config file is created at the path. If no path is provided, \ - the default config location will be used." - ) - .value_hint(ValueHint::AnyPath); - - let default_time_value = Arg::new("default_time_value") - .short('t') - .long("default_time_value") - .action(ArgAction::Set) - .value_name("TIME") - .help("Default time value for graphs.") - .long_help( - "Default time value for graphs. Either a number in milliseconds or a 'human duration' \ - (e.g. 60s, 10m). Defaults to 60s, must be at least 30s.", - ); - - // TODO: Charts are broken in the manpage - let default_widget_count = Arg::new("default_widget_count") - .long("default_widget_count") - .action(ArgAction::Set) - .requires_all(["default_widget_type"]) - .value_name("N") - .help("Sets the N'th selected widget type as the default.") - .long_help(indoc! { - "Sets the N'th selected widget type to use as the default widget. Requires 'default_widget_type' to also be \ - set, and defaults to 1. - - This reads from left to right, top to bottom. For example, suppose we have a layout that looks like: - +-------------------+-----------------------+ - | CPU (1) | CPU (2) | - +---------+---------+-------------+---------+ - | Process | CPU (3) | Temperature | CPU (4) | - +---------+---------+-------------+---------+ - - And we set our default widget type to 'CPU'. If we set '--default_widget_count 1', then it would use the \ - CPU (1) as the default widget. If we set '--default_widget_count 3', it would use CPU (3) as the default \ - instead." - }); - - let default_widget_type = Arg::new("default_widget_type") - .long("default_widget_type") - .action(ArgAction::Set) - .value_name("WIDGET") - .help("Sets the default widget type, use `--help` for info.") - .long_help(indoc!{ - "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 temperature' will make the temperature widget selected by default." - }) - .value_parser([ - "cpu", - "mem", - "net", - "network", - "proc", - "process", - "processes", - "temp", - "temperature", - "disk", - #[cfg(feature = "battery")] - "batt", - #[cfg(feature = "battery")] - "battery", - ]); - - let disable_click = Arg::new("disable_click") - .long("disable_click") - .action(ArgAction::SetTrue) - .help("Disables mouse clicks.") - .long_help("Disables mouse clicks from interacting with bottom."); - - // TODO: Change this to accept a string with the type of marker. - let dot_marker = Arg::new("dot_marker") - .short('m') - .long("dot_marker") - .action(ArgAction::SetTrue) - .help("Uses a dot marker for graphs.") - .long_help("Uses a dot marker for graphs as opposed to the default braille marker."); - - let expanded = Arg::new("expanded") - .short('e') - .long("expanded") - .action(ArgAction::SetTrue) - .help("Expand the default widget upon starting the app.") - .long_help("Expand the default widget upon starting the app. This flag has no effect in basic mode (--basic)."); - - let hide_table_gap = Arg::new("hide_table_gap") - .long("hide_table_gap") - .action(ArgAction::SetTrue) - .help("Hides spacing between table headers and entries."); - - let hide_time = Arg::new("hide_time") - .long("hide_time") - .action(ArgAction::SetTrue) - .help("Hides the time scale from being shown."); - - let rate = Arg::new("rate") - .short('r') - .long("rate") - .action(ArgAction::Set) - .value_name("TIME") - .help("Sets how often data is refreshed.") - .long_help( - "Sets how often data is refreshed. Either a number in milliseconds or a 'human duration' \ - (e.g. 1s, 1m). Defaults to 1s, must be at least 250ms. Smaller values may result in \ - higher system resource usage." - ); - - // TODO: Unify how we do defaults. - let retention = Arg::new("retention") - .long("retention") - .action(ArgAction::Set) - .value_name("TIME") - .help("How far back data will be stored up to.") - .long_help( - "How far back data will be stored up to. Either a number in milliseconds or a 'human duration' \ - (e.g. 10m, 1h). Defaults to 10 minutes, and must be at least 1 minute. Larger values \ - may result in higher memory usage." - ); - - let show_table_scroll_position = Arg::new("show_table_scroll_position") - .long("show_table_scroll_position") - .action(ArgAction::SetTrue) - .help("Shows the scroll position tracker in table widgets.") - .long_help("Shows the list scroll position tracker in the widget title for table widgets."); - - let time_delta = Arg::new("time_delta") - .short('d') - .long("time_delta") - .action(ArgAction::Set) - .value_name("TIME") - .help("The amount of time changed upon zooming.") - .long_help( - "The amount of time changed when zooming in/out. Takes a number in \ - milliseconds or a human duration (e.g. 30s). The minimum is 1s, and \ - defaults to 15s.", - ); - - cmd.args(args![ - autohide_time, - basic, - config_location, - default_widget_count, - default_time_value, - default_widget_type, - disable_click, - dot_marker, - expanded, - hide_table_gap, - hide_time, - rate, - retention, - show_table_scroll_position, - time_delta, - ]) + pub time_delta: Option<String>, } /// Process arguments/config options. #[derive(Args, Clone, Debug, Default)] #[command(next_help_heading = "Process Options", rename_all = "snake_case")] -pub(crate) struct ProcessArgs { +pub struct ProcessArgs { #[arg( short = 'S', long, help = "Enables case sensitivity by default.", long_help = "Enables case sensitivity by default when searching for a process." )] - pub(crate) case_sensitive: Option<bool>, + pub case_sensitive: Option<bool>, // TODO: Rename this. #[arg( @@ -499,7 +277,7 @@ pub(crate) struct ProcessArgs { long, help = "Calculates process CPU usage as a percentage of current usage rather than total usage." )] - pub(crate) current_usage: Option<bool>, + pub current_usage: Option<bool>, // TODO: Disable this on Windows? #[arg( @@ -508,142 +286,58 @@ pub(crate) struct ProcessArgs { long_help = "Hides additional stopping options Unix-like systems. Signal 15 (TERM) will be sent when \ stopping a process." )] - pub(crate) disable_advanced_kill: Option<bool>, + pub disable_advanced_kill: Option<bool>, #[arg( short = 'g', long, help = "Groups processes with the same name by default." )] - pub(crate) group_processes: Option<bool>, + pub group_processes: Option<bool>, #[arg( long, help = "Defaults to showing process memory usage by value.", long_help = "Defaults to showing process memory usage by value. Otherwise, it defaults to showing it by percentage." )] - pub(crate) mem_as_value: Option<bool>, + pub mem_as_value: Option<bool>, #[arg( long, - help = "Shows the full command name instead of just the process name by default." + help = "Shows the full command name instead of the process name by default." )] - pub(crate) process_command: Option<bool>, + pub process_command: Option<bool>, #[arg(short = 'R', long, help = "Enables regex by default while searching.")] - pub(crate) regex: Option<bool>, + pub regex: Option<bool>, #[arg( short = 'T', long, help = "Makes the process widget use tree mode by default." )] - pub(crate) tree: Option<bool>, + pub tree: Option<bool>, #[arg( short = 'n', long, help = "Show process CPU% usage without averaging over the number of CPU cores." )] - pub(crate) unnormalized_cpu: Option<bool>, + pub unnormalized_cpu: Option<bool>, #[arg( short = 'W', long, help = "Enables whole-word matching by default while searching." )] - pub(crate) whole_word: Option<bool>, -} - -fn process_args(cmd: Command) -> Command { - let cmd = cmd.next_help_heading("Process Options"); - - let case_sensitive = Arg::new("case_sensitive") - .short('S') - .long("case_sensitive") - .action(ArgAction::SetTrue) - .help("Enables case sensitivity by default.") - .long_help("Enables case sensitivity by default when searching for a process."); - - // TODO: Rename this. - let current_usage = Arg::new("current_usage") - .short('u') - .long("current_usage") - .action(ArgAction::SetTrue) - .help("Calculates process CPU usage as a percentage of current usage rather than total usage."); - - // TODO: Disable this on Windows? - let disable_advanced_kill = Arg::new("disable_advanced_kill") - .long("disable_advanced_kill") - .action(ArgAction::SetTrue) - .help("Hides additional stopping options Unix-like systems.") - .long_help( - "Hides additional stopping options Unix-like systems. Signal 15 (TERM) will be sent when \ - stopping a process.", - ); - - let group_processes = Arg::new("group_processes") - .short('g') - .long("group_processes") - .action(ArgAction::SetTrue) - .help("Groups processes with the same name by default."); - - let mem_as_value = Arg::new("mem_as_value") - .long("mem_as_value") - .action(ArgAction::SetTrue) - .help("Defaults to showing process memory usage by value.") - .long_help("Defaults to showing process memory usage by value. Otherwise, it defaults to showing it by percentage."); - - let process_command = Arg::new("process_command") - .long("process_command") - .action(ArgAction::SetTrue) - .help("Shows the full command name instead of the process name by default."); - - let regex = Arg::new("regex") - .short('R') - .long("regex") - .action(ArgAction::SetTrue) - .help("Enables regex by default while searching."); - - let tree = Arg::new("tree") - .short('T') - .long("tree") - .action(ArgAction::SetTrue) - .help("Makes the process widget use tree mode by default."); - - let unnormalized_cpu = Arg::new("unnormalized_cpu") - .short('n') - .long("unnormalized_cpu") - .action(ArgAction::SetTrue) - .help("Show process CPU% usage without averaging over the number of CPU cores."); - - let whole_word = Arg::new("whole_word") - .short('W') - .long("whole_word") - .action(ArgAction::SetTrue) - .help("Enables whole-word matching by default while searching."); - - let args = args![ - case_sensitive, - current_usage, - disable_advanced_kill, - group_processes, - mem_as_value, - process_command, - regex, - tree, - unnormalized_cpu, - whole_word, - ]; - - cmd.args(args) + pub whole_word: Option<bool>, } /// Temperature arguments/config options. #[derive(Args, Clone, Debug, Default)] #[command(next_help_heading = "Temperature Options", rename_all = "snake_case")] #[group(id = "temperature_unit", multiple = false)] -pub(crate) struct TemperatureArgs { +pub struct TemperatureArgs { #[arg( short = 'c', long, @@ -651,7 +345,7 @@ pub(crate) struct TemperatureArgs { help = "Use Celsius as the temperature unit. Default.", long_help = "Use Celsius as the temperature unit. This is the default option." )] - pub(crate) celsius: bool, + pub celsius: bool, #[arg( short = 'f', @@ -659,7 +353,7 @@ pub(crate) struct TemperatureArgs { group = "temperature_unit", help = "Use Fahrenheit as the temperature unit." )] - pub(crate) fahrenheit: bool, + pub fahrenheit: bool, #[arg( short = 'k', @@ -667,39 +361,7 @@ pub(crate) struct TemperatureArgs { group = "temperature_unit", help = "Use Kelvin as the temperature unit." )] - pub(crate) kelvin: bool, -} - -fn temperature_args(cmd: Command) -> Command { - let cmd = cmd.next_help_heading("Temperature Options"); - - let celsius = Arg::new("celsius") - .short('c') - .long("celsius") - .action(ArgAction::SetTrue) - .help("Use Celsius as the temperature unit. Default.") - .long_help("Use Celsius as the temperature unit. This is the default option."); - - let fahrenheit = Arg::new("fahrenheit") - .short('f') - .long("fahrenheit") - .action(ArgAction::SetTrue) - .help("Use Fahrenheit as the temperature unit."); - - let kelvin = Arg::new("kelvin") - .short('k') - .long("kelvin") - .action(ArgAction::SetTrue) - .help("Use Kelvin as the temperature unit."); - - let temperature_group = ArgGroup::new("TEMPERATURE_TYPE").args([ - celsius.get_id(), - fahrenheit.get_id(), - kelvin.get_id(), - ]); - - cmd.args(args![celsius, fahrenheit, kelvin]) - .group(temperature_group) + pub kelvin: bool, } /// The default selection of the CPU widget. If the given selection is invalid, @@ -724,18 +386,18 @@ impl From<&str> for CpuDefault { /// CPU arguments/config options. #[derive(Args, Clone, Debug, Default)] #[command(next_help_heading = "CPU Options", rename_all = "snake_case")] -pub(crate) struct CpuArgs { +pub struct CpuArgs { #[arg( long, - help = "Sets which CPU entry is selected by default.", + help = "Sets which CPU entry type is selected by default.", value_name = "ENTRY", value_parser = ["all", "avg"], default_value = "all" )] - pub(crate) default_cpu_entry: CpuDefault, + pub default_cpu_entry: CpuDefault, #[arg(short = 'a', long, help = "Hides the average CPU usage entry.")] - pub(crate) hide_avg_cpu: Option<bool>, + pub hide_avg_cpu: Option<bool>, // TODO: Maybe rename this or fix this? Should this apply to all "left legends"? #[arg( @@ -743,77 +405,50 @@ pub(crate) struct CpuArgs { long, help = "Puts the CPU chart legend on the left side." )] - pub(crate) left_legend: Option<bool>, -} - -fn cpu_args(cmd: Command) -> Command { - let cmd = cmd.next_help_heading("CPU Options"); - - // let default_cpu_entry = Arg::new(""); - - let hide_avg_cpu = Arg::new("hide_avg_cpu") - .short('a') - .long("hide_avg_cpu") - .action(ArgAction::SetTrue) - .help("Hides the average CPU usage entry."); - - let cpu_left_legend = Arg::new("cpu_left_legend") - .long("cpu_left_legend") - .action(ArgAction::SetTrue) - .help("Puts the CPU chart legend on the left side."); - - cmd.args(args![hide_avg_cpu, cpu_left_legend]) + pub left_legend: Option<bool>, } /// Memory argument/config options. #[derive(Args, Clone, Debug, Default)] #[command(next_help_heading = "Memory Options", rename_all = "snake_case")] -pub(crate) struct MemoryArgs { - #[cfg(not(target_os = "windows"))] +pub struct MemoryArgs { #[arg( long, - help = "Enables collecting and displaying cache and buffer memory." + value_parser = CHART_WIDGET_POSITIONS, + value_name = "POSITION", + ignore_case = true, + help = "Where to place the legend for the memory chart widget.", )] - pub(crate) enable_cache_memory: Option<bool>, -} - -fn mem_args(cmd: Command) -> Command { - let cmd = cmd.next_help_heading("Memory Options"); - - let memory_legend = Arg::new("memory_legend") - .long("memory_legend") - .action(ArgAction::Set) - .value_name("POSITION") - .ignore_case(true) - .help("Where to place the legend for the memory chart widget.") - .value_parser(CHART_WIDGET_POSITIONS); + pub memory_legend: Option<String>, #[cfg(not(target_os = "windows"))] - { - let enable_cache_memory = Arg::new("enable_cache_memory") - .long("enable_cache_memory") - .action(ArgAction::SetTrue) - .help("Enable collecting and displaying cache and buffer memory."); - - cmd.args(args![enable_cache_memory, memory_legend]) - } - #[cfg(target_os = "windows")] - { - cmd.arg(memory_legend) - } + #[arg( + long, + help = "Enables collecting and displaying cache and buffer memory." + )] + pub enable_cache_memory: Option<bool>, } /// Network arguments/config options. #[derive(Args, Clo |