mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-26 07:04:51 +02:00
refactor: rearrange/resort args (#1376)
* clean up Cargo.toml * some small cleanup * refactor: group together similar args in the help generation and code This groups together related arguments in both the help text and the code itself. * update changelog * clippy * builder pattern instead
This commit is contained in:
parent
0f969fcfd4
commit
6b62176554
@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
- [#1344](https://github.com/ClementTsang/bottom/pull/1344): Change the `group` command line argument to `group_processes` for consistency with the config file option.
|
- [#1344](https://github.com/ClementTsang/bottom/pull/1344): Change the `group` command line-argument to `group_processes` for consistency with the config file option.
|
||||||
|
- [#1376](https://github.com/ClementTsang/bottom/pull/1376): Group together related command-line arguments in `-h` and `--help`.
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -239,18 +239,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.4.11"
|
version = "4.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
|
checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.4.11"
|
version = "4.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
|
checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@ -261,9 +261,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_complete"
|
name = "clap_complete"
|
||||||
version = "4.4.5"
|
version = "4.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a51919c5608a32e34ea1d6be321ad070065e17613e168c5b6977024290f2630b"
|
checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
]
|
]
|
||||||
@ -296,9 +296,9 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_mangen"
|
name = "clap_mangen"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3be86020147691e1d2ef58f75346a3d4d94807bfc473e377d52f09f0f7d77f7"
|
checksum = "10b5db60b3310cdb376fbeb8826e875a38080d0c61bdec0a91a3da8338948736"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"roff",
|
"roff",
|
||||||
|
25
Cargo.toml
25
Cargo.toml
@ -64,23 +64,20 @@ strip = false
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
battery = ["starship-battery"]
|
battery = ["starship-battery"]
|
||||||
gpu = ["nvidia"]
|
|
||||||
nvidia = ["nvml-wrapper"]
|
nvidia = ["nvml-wrapper"]
|
||||||
|
gpu = ["nvidia"]
|
||||||
zfs = []
|
zfs = []
|
||||||
|
|
||||||
# Including logging for debugging purposes.
|
# Logging for debugging performance.
|
||||||
logging = ["fern", "log", "time/local-offset"]
|
logging = ["fern", "log", "time/local-offset"]
|
||||||
|
|
||||||
# The features we use on deploy. Logging is not included as that is primarily (for now) just for debugging locally.
|
default = ["battery", "gpu", "zfs"]
|
||||||
deploy = ["battery", "gpu", "zfs"]
|
|
||||||
|
|
||||||
default = ["deploy"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
backtrace = "0.3.69"
|
backtrace = "0.3.69"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
clap = { version = "4.4.11", features = ["default", "cargo", "wrap_help"] }
|
clap = { version = "4.4.14", features = ["default", "cargo", "wrap_help"] }
|
||||||
concat-string = "1.0.1"
|
concat-string = "1.0.1"
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
ctrlc = { version = "3.4.1", features = ["termination"] }
|
ctrlc = { version = "3.4.1", features = ["termination"] }
|
||||||
@ -93,7 +90,9 @@ indexmap = "2.1.0"
|
|||||||
itertools = "0.12.0"
|
itertools = "0.12.0"
|
||||||
kstring = { version = "2.0.0", features = ["arc"] }
|
kstring = { version = "2.0.0", features = ["arc"] }
|
||||||
log = { version = "0.4.20", optional = true }
|
log = { version = "0.4.20", optional = true }
|
||||||
nvml-wrapper = { version = "0.9.0", optional = true, features = ["legacy-functions"] }
|
nvml-wrapper = { version = "0.9.0", optional = true, features = [
|
||||||
|
"legacy-functions",
|
||||||
|
] }
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
serde = { version = "=1.0.193", features = ["derive"] }
|
serde = { version = "=1.0.193", features = ["derive"] }
|
||||||
starship-battery = { version = "0.8.2", optional = true }
|
starship-battery = { version = "0.8.2", optional = true }
|
||||||
@ -133,15 +132,17 @@ filedescriptor = "0.8.2"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_cmd = "2.0.12"
|
assert_cmd = "2.0.12"
|
||||||
cargo-husky = { version = "1.5.0", default-features = false, features = ["user-hooks"] }
|
cargo-husky = { version = "1.5.0", default-features = false, features = [
|
||||||
|
"user-hooks",
|
||||||
|
] }
|
||||||
predicates = "3.0.3"
|
predicates = "3.0.3"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = { version = "4.4.11", features = ["default", "cargo", "wrap_help"] }
|
clap = { version = "4.4.14", features = ["default", "cargo", "wrap_help"] }
|
||||||
clap_complete = "4.4.5"
|
clap_complete = "4.4.6"
|
||||||
clap_complete_fig = "4.4.2"
|
clap_complete_fig = "4.4.2"
|
||||||
clap_complete_nushell = "4.4.2"
|
clap_complete_nushell = "4.4.2"
|
||||||
clap_mangen = "0.2.15"
|
clap_mangen = "0.2.16"
|
||||||
|
|
||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
section = "utility"
|
section = "utility"
|
||||||
|
7
build.rs
7
build.rs
@ -1,13 +1,18 @@
|
|||||||
|
#[allow(dead_code)]
|
||||||
|
#[path = "src/options/args.rs"]
|
||||||
|
mod args;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env, fs, io,
|
env, fs, io,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use clap::Command;
|
||||||
use clap_complete::{generate_to, shells::Shell, Generator};
|
use clap_complete::{generate_to, shells::Shell, Generator};
|
||||||
use clap_complete_fig::Fig;
|
use clap_complete_fig::Fig;
|
||||||
use clap_complete_nushell::Nushell;
|
use clap_complete_nushell::Nushell;
|
||||||
|
|
||||||
include!("src/options/args.rs");
|
use crate::args::build_app;
|
||||||
|
|
||||||
fn create_dir(dir: &Path) -> io::Result<()> {
|
fn create_dir(dir: &Path) -> io::Result<()> {
|
||||||
let res = fs::create_dir_all(dir);
|
let res = fs::create_dir_all(dir);
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
|
//! Argument parsing via clap.
|
||||||
|
//!
|
||||||
|
//! Note that you probably want to keep this as a single file so the build script doesn't
|
||||||
|
//! trip all over itself.
|
||||||
|
|
||||||
use clap::{builder::PossibleValuesParser, *};
|
use clap::{builder::PossibleValuesParser, *};
|
||||||
|
|
||||||
const TEMPLATE: &str = "\
|
|
||||||
{name} {version}
|
|
||||||
{author}
|
|
||||||
|
|
||||||
{about}
|
|
||||||
|
|
||||||
{usage-heading} {usage}
|
|
||||||
|
|
||||||
{all-args}";
|
|
||||||
|
|
||||||
const USAGE: &str = "btm [OPTIONS]";
|
|
||||||
|
|
||||||
const DEFAULT_WIDGET_TYPE_STR: &str = {
|
const DEFAULT_WIDGET_TYPE_STR: &str = {
|
||||||
#[cfg(feature = "battery")]
|
#[cfg(feature = "battery")]
|
||||||
{
|
{
|
||||||
@ -87,30 +80,32 @@ pub fn get_matches() -> ArgMatches {
|
|||||||
build_app().get_matches()
|
build_app().get_matches()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_app() -> Command {
|
trait CommandBuilder {
|
||||||
// Temps
|
fn general_args(self) -> Self;
|
||||||
let kelvin = Arg::new("kelvin")
|
|
||||||
.short('k')
|
|
||||||
.long("kelvin")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Sets the temperature type to Kelvin.")
|
|
||||||
.long_help("Sets the temperature type to Kelvin.");
|
|
||||||
|
|
||||||
let fahrenheit = Arg::new("fahrenheit")
|
fn style_args(self) -> Self;
|
||||||
.short('f')
|
|
||||||
.long("fahrenheit")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Sets the temperature type to Fahrenheit.")
|
|
||||||
.long_help("Sets the temperature type to Fahrenheit.");
|
|
||||||
|
|
||||||
let celsius = Arg::new("celsius")
|
fn temperature_args(self) -> Self;
|
||||||
.short('c')
|
|
||||||
.long("celsius")
|
fn process_args(self) -> Self;
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Sets the temperature type to Celsius.")
|
fn cpu_args(self) -> Self;
|
||||||
.long_help("Sets the temperature type to Celsius. This is the default option.");
|
|
||||||
|
fn mem_args(self) -> Self;
|
||||||
|
|
||||||
|
fn network_args(self) -> Self;
|
||||||
|
|
||||||
|
fn battery_args(self) -> Self;
|
||||||
|
|
||||||
|
fn gpu_args(self) -> Self;
|
||||||
|
|
||||||
|
fn other(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandBuilder for Command {
|
||||||
|
fn general_args(self) -> Command {
|
||||||
|
const HEADING: &str = "General Options";
|
||||||
|
|
||||||
// All flags. These are in alphabetical order
|
|
||||||
let autohide_time = Arg::new("autohide_time")
|
let autohide_time = Arg::new("autohide_time")
|
||||||
.long("autohide_time")
|
.long("autohide_time")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
@ -119,7 +114,8 @@ pub fn build_app() -> Command {
|
|||||||
"Automatically hides the time scale in graphs after being shown for \
|
"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 \
|
a brief moment when zoomed in/out. If time is disabled via --hide_time \
|
||||||
then this will have no effect.",
|
then this will have no effect.",
|
||||||
);
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let basic = Arg::new("basic")
|
let basic = Arg::new("basic")
|
||||||
.short('b')
|
.short('b')
|
||||||
@ -128,121 +124,55 @@ pub fn build_app() -> Command {
|
|||||||
.help("Hides graphs and uses a more basic look.")
|
.help("Hides graphs and uses a more basic look.")
|
||||||
.long_help(
|
.long_help(
|
||||||
"Hides graphs and uses a more basic look. Design is largely inspired by htop's.",
|
"Hides graphs and uses a more basic look. Design is largely inspired by htop's.",
|
||||||
);
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
let case_sensitive = Arg::new("case_sensitive")
|
|
||||||
.short('S')
|
|
||||||
.long("case_sensitive")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Enables case sensitivity by default.")
|
|
||||||
.long_help("When searching for a process, enables case sensitivity by default.");
|
|
||||||
|
|
||||||
let current_usage = Arg::new("current_usage")
|
|
||||||
.short('u')
|
|
||||||
.long("current_usage")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Sets process CPU% to be based on current CPU%.")
|
|
||||||
.long_help("Sets process CPU% usage to be based on the current system CPU% usage rather than total CPU usage.");
|
|
||||||
|
|
||||||
let unnormalized_cpu = Arg::new("unnormalized_cpu")
|
|
||||||
.short('n')
|
|
||||||
.long("unnormalized_cpu")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Show process CPU% usage without normalizing over the number of cores.")
|
|
||||||
.long_help(
|
|
||||||
"Shows all process CPU% usage without averaging over the number of CPU cores in the system.",
|
|
||||||
);
|
|
||||||
|
|
||||||
let disable_click = Arg::new("disable_click")
|
let disable_click = Arg::new("disable_click")
|
||||||
.long("disable_click")
|
.long("disable_click")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Disables mouse clicks.")
|
.help("Disables mouse clicks.")
|
||||||
.long_help("Disables mouse clicks from interacting with the program.");
|
.long_help("Disables mouse clicks from interacting with the program.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let dot_marker = Arg::new("dot_marker")
|
let dot_marker = Arg::new("dot_marker")
|
||||||
.short('m')
|
.short('m')
|
||||||
.long("dot_marker")
|
.long("dot_marker")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Uses a dot marker for graphs.")
|
.help("Uses a dot marker for graphs.")
|
||||||
.long_help("Uses a dot marker for graphs as opposed to the default braille marker.");
|
.long_help("Uses a dot marker for graphs as opposed to the default braille marker.")
|
||||||
|
.help_heading(HEADING);
|
||||||
let group_processes = Arg::new("group_processes")
|
|
||||||
.short('g')
|
|
||||||
.long("group_processes")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Groups processes with the same name by default.")
|
|
||||||
.long_help("Groups processes with the same name by default.");
|
|
||||||
|
|
||||||
let hide_avg_cpu = Arg::new("hide_avg_cpu")
|
|
||||||
.short('a')
|
|
||||||
.long("hide_avg_cpu")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Hides the average CPU usage.")
|
|
||||||
.long_help("Hides the average CPU usage from being shown.");
|
|
||||||
|
|
||||||
let hide_table_gap = Arg::new("hide_table_gap")
|
let hide_table_gap = Arg::new("hide_table_gap")
|
||||||
.long("hide_table_gap")
|
.long("hide_table_gap")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Hides spacing between table headers and entries.")
|
.help("Hides spacing between table headers and entries.")
|
||||||
.long_help("Hides the spacing between table headers and entries.");
|
.long_help("Hides the spacing between table headers and entries.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let hide_time = Arg::new("hide_time")
|
let hide_time = Arg::new("hide_time")
|
||||||
.long("hide_time")
|
.long("hide_time")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Hides the time scale.")
|
.help("Hides the time scale.")
|
||||||
.long_help("Completely hides the time scale from being shown.");
|
.long_help("Completely hides the time scale from being shown.")
|
||||||
|
.help_heading(HEADING);
|
||||||
let process_command = Arg::new("process_command")
|
|
||||||
.long("process_command")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Show processes as their commands by default.")
|
|
||||||
.long_help("Show processes as their commands by default in the process widget.");
|
|
||||||
|
|
||||||
let left_legend = Arg::new("left_legend")
|
let left_legend = Arg::new("left_legend")
|
||||||
.short('l')
|
.short('l')
|
||||||
.long("left_legend")
|
.long("left_legend")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Puts the CPU chart legend to the left side.")
|
.help("Puts the CPU chart legend to the left side.")
|
||||||
.long_help("Puts the CPU chart legend to the left side rather than the right side.");
|
.long_help("Puts the CPU chart legend to the left side rather than the right side.")
|
||||||
|
.help_heading(HEADING);
|
||||||
let regex = Arg::new("regex")
|
|
||||||
.short('R')
|
|
||||||
.long("regex")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Enables regex by default.")
|
|
||||||
.long_help("When searching for a process, enables regex by default.");
|
|
||||||
|
|
||||||
let disable_advanced_kill = Arg::new("disable_advanced_kill")
|
|
||||||
.long("disable_advanced_kill")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Hides advanced process killing.")
|
|
||||||
.long_help("Hides advanced options to stop a process on Unix-like systems. The only option shown is 15 (TERM).");
|
|
||||||
|
|
||||||
let show_table_scroll_position = Arg::new("show_table_scroll_position")
|
let show_table_scroll_position = Arg::new("show_table_scroll_position")
|
||||||
.long("show_table_scroll_position")
|
.long("show_table_scroll_position")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Shows the scroll position tracker in table widgets.")
|
.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 use_old_network_legend = Arg::new("use_old_network_legend")
|
|
||||||
.long("use_old_network_legend")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("DEPRECATED - uses a separate network legend.")
|
|
||||||
.long_help(
|
.long_help(
|
||||||
"DEPRECATED - uses an older (pre-0.4), separate network widget legend. This display is not \
|
"Shows the list scroll position tracker in the widget title for table widgets.",
|
||||||
tested anymore and could be broken.",
|
)
|
||||||
);
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let whole_word = Arg::new("whole_word")
|
|
||||||
.short('W')
|
|
||||||
.long("whole_word")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Enables whole-word matching by default.")
|
|
||||||
.long_help(
|
|
||||||
"When searching for a process, return results that match the entire query by default.",
|
|
||||||
);
|
|
||||||
|
|
||||||
// All options. Again, alphabetical order.
|
|
||||||
let config_location = Arg::new("config_location")
|
let config_location = Arg::new("config_location")
|
||||||
.short('C')
|
.short('C')
|
||||||
.long("config")
|
.long("config")
|
||||||
@ -253,7 +183,115 @@ pub fn build_app() -> Command {
|
|||||||
"Sets the location of the config file. Expects a config file in the TOML format. \
|
"Sets the location of the config file. Expects a config file in the TOML format. \
|
||||||
If it doesn't exist, one is created.",
|
If it doesn't exist, one is created.",
|
||||||
)
|
)
|
||||||
.value_hint(ValueHint::AnyPath);
|
.value_hint(ValueHint::AnyPath)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
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. Takes a number in milliseconds or a human duration (e.g. 60s). The minimum time is 30s, and the default is 60s.",
|
||||||
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
// 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("INT")
|
||||||
|
.help("Sets the n'th selected widget type as the default.")
|
||||||
|
.long_help(
|
||||||
|
"\
|
||||||
|
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.
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let default_widget_type = Arg::new("default_widget_type")
|
||||||
|
.long("default_widget_type")
|
||||||
|
.action(ArgAction::Set)
|
||||||
|
.value_name("WIDGET TYPE")
|
||||||
|
.help("Sets the default widget type, use --help for info.")
|
||||||
|
.long_help(DEFAULT_WIDGET_TYPE_STR)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let expanded_on_startup = Arg::new("expanded_on_startup")
|
||||||
|
.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. Same as pressing \"e\" inside the app. Use with \"default_widget_type\" and \"default_widget_count\" to select desired expanded widget. This flag has no effect in basic mode (--basic)")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let rate = Arg::new("rate")
|
||||||
|
.short('r')
|
||||||
|
.long("rate")
|
||||||
|
.action(ArgAction::Set)
|
||||||
|
.value_name("TIME")
|
||||||
|
.help("Sets the data refresh rate.")
|
||||||
|
.long_help("Sets the data refresh rate. Takes a number in milliseconds or a human duration (e.g. 5s). The minimum is 250ms, and defaults to 1000ms. Smaller values may take more computer resources.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
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.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let retention = Arg::new("retention")
|
||||||
|
.long("retention")
|
||||||
|
.action(ArgAction::Set)
|
||||||
|
.value_name("TIME")
|
||||||
|
.help("The timespan of data stored.")
|
||||||
|
.long_help("How much data is stored at once in terms of time. Takes a number in milliseconds or a human duration (e.g. 20m), with a minimum of 1 minute. Note higher values will take up more memory. Defaults to 10 minutes.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let mut args = [
|
||||||
|
autohide_time,
|
||||||
|
basic,
|
||||||
|
disable_click,
|
||||||
|
dot_marker,
|
||||||
|
hide_table_gap,
|
||||||
|
hide_time,
|
||||||
|
left_legend,
|
||||||
|
show_table_scroll_position,
|
||||||
|
config_location,
|
||||||
|
default_time_value,
|
||||||
|
default_widget_count,
|
||||||
|
default_widget_type,
|
||||||
|
expanded_on_startup,
|
||||||
|
rate,
|
||||||
|
time_delta,
|
||||||
|
retention,
|
||||||
|
];
|
||||||
|
args.sort_unstable();
|
||||||
|
|
||||||
|
self.args(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style_args(self) -> Command {
|
||||||
|
const HEADING: &str = "Style Options";
|
||||||
|
|
||||||
// TODO: File an issue with manpage, it cannot render charts correctly.
|
// TODO: File an issue with manpage, it cannot render charts correctly.
|
||||||
let color = Arg::new("color")
|
let color = Arg::new("color")
|
||||||
@ -288,99 +326,207 @@ Use a pre-defined color scheme. Currently supported values are:
|
|||||||
+------------------------------------------------------------+
|
+------------------------------------------------------------+
|
||||||
Defaults to \"default\".
|
Defaults to \"default\".
|
||||||
",
|
",
|
||||||
);
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let mem_as_value = Arg::new("mem_as_value")
|
self.arg(color)
|
||||||
.long("mem_as_value")
|
}
|
||||||
|
|
||||||
|
fn temperature_args(self) -> Command {
|
||||||
|
const HEADING: &str = "Temperature Options";
|
||||||
|
|
||||||
|
let celsius = Arg::new("celsius")
|
||||||
|
.short('c')
|
||||||
|
.long("celsius")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Defaults to showing process memory usage by value.")
|
.help("Use Celsius as the temperature unit.")
|
||||||
.long_help("Defaults to showing process memory usage by value. Otherwise, it defaults to showing it by percentage.");
|
.long_help("Use Celsius as the temperature unit. This is the default option.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let default_time_value = Arg::new("default_time_value")
|
let fahrenheit = Arg::new("fahrenheit")
|
||||||
.short('t')
|
.short('f')
|
||||||
.long("default_time_value")
|
.long("fahrenheit")
|
||||||
.action(ArgAction::Set)
|
|
||||||
.value_name("TIME")
|
|
||||||
.help("Default time value for graphs.")
|
|
||||||
.long_help(
|
|
||||||
"Default time value for graphs. Takes a number in milliseconds or a human duration (e.g. 60s). The minimum time is 30s, and the default is 60s.",
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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("INT")
|
|
||||||
.help("Sets the n'th selected widget type as the default.")
|
|
||||||
.long_help(
|
|
||||||
"\
|
|
||||||
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 TYPE")
|
|
||||||
.help("Sets the default widget type, use --help for info.")
|
|
||||||
.long_help(DEFAULT_WIDGET_TYPE_STR);
|
|
||||||
|
|
||||||
let expanded_on_startup = Arg::new("expanded_on_startup")
|
|
||||||
.short('e')
|
|
||||||
.long("expanded")
|
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Expand the default widget upon starting the app.")
|
.help("Use Fahrenheit as the temperature unit.")
|
||||||
.long_help("Expand the default widget upon starting the app. Same as pressing \"e\" inside the app. Use with \"default_widget_type\" and \"default_widget_count\" to select desired expanded widget. This flag has no effect in basic mode (--basic)");
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let rate = Arg::new("rate")
|
let kelvin = Arg::new("kelvin")
|
||||||
.short('r')
|
.short('k')
|
||||||
.long("rate")
|
.long("kelvin")
|
||||||
.action(ArgAction::Set)
|
.action(ArgAction::SetTrue)
|
||||||
.value_name("TIME")
|
.help("Use Kelvin as the temperature unit.")
|
||||||
.help("Sets the data refresh rate.")
|
.help_heading(HEADING);
|
||||||
.long_help("Sets the data refresh rate. Takes a number in milliseconds or a human duration (e.g. 5s). The minimum is 250ms, and defaults to 1000ms. Smaller values may take more computer resources.");
|
|
||||||
|
|
||||||
let time_delta = Arg::new("time_delta")
|
let temperature_group = ArgGroup::new("TEMPERATURE_TYPE").args([
|
||||||
.short('d')
|
celsius.get_id(),
|
||||||
.long("time_delta")
|
fahrenheit.get_id(),
|
||||||
.action(ArgAction::Set)
|
kelvin.get_id(),
|
||||||
.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.");
|
let args = [celsius, fahrenheit, kelvin];
|
||||||
|
|
||||||
|
self.args(args).group(temperature_group)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_args(self) -> Command {
|
||||||
|
const HEADING: &str = "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("When searching for a process, enables case sensitivity by default.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let current_usage = Arg::new("current_usage")
|
||||||
|
.short('u')
|
||||||
|
.long("current_usage")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Sets process CPU% to be based on current CPU%.")
|
||||||
|
.long_help("Sets process CPU% usage to be based on the current system CPU% usage rather than total CPU usage.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let unnormalized_cpu = Arg::new("unnormalized_cpu")
|
||||||
|
.short('n')
|
||||||
|
.long("unnormalized_cpu")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Show process CPU% usage without normalizing over the number of cores.")
|
||||||
|
.long_help(
|
||||||
|
"Shows all process CPU% usage without averaging over the number of CPU cores in the system.",
|
||||||
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let group_processes = Arg::new("group_processes")
|
||||||
|
.short('g')
|
||||||
|
.long("group_processes")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Groups processes with the same name by default.")
|
||||||
|
.long_help("Groups processes with the same name by default.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let process_command = Arg::new("process_command")
|
||||||
|
.long("process_command")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Show processes as their commands by default.")
|
||||||
|
.long_help("Show processes as their commands by default in the process widget.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let regex = Arg::new("regex")
|
||||||
|
.short('R')
|
||||||
|
.long("regex")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Enables regex by default.")
|
||||||
|
.long_help("When searching for a process, enables regex by default.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let disable_advanced_kill = Arg::new("disable_advanced_kill")
|
||||||
|
.long("disable_advanced_kill")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Hides advanced process killing.")
|
||||||
|
.long_help("Hides advanced options to stop a process on Unix-like systems. The only option shown is 15 (TERM).")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let whole_word = Arg::new("whole_word")
|
||||||
|
.short('W')
|
||||||
|
.long("whole_word")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Enables whole-word matching by default.")
|
||||||
|
.long_help(
|
||||||
|
"When searching for a process, return results that match the entire query by default.",
|
||||||
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let tree = Arg::new("tree")
|
let tree = Arg::new("tree")
|
||||||
.short('T')
|
.short('T')
|
||||||
.long("tree")
|
.long("tree")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Defaults the process widget be in tree mode.")
|
.help("Defaults the process widget be in tree mode.")
|
||||||
.long_help("Defaults to showing the process widget in tree mode.");
|
.long_help("Defaults to showing the process widget in tree mode.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let mut args = [
|
||||||
|
case_sensitive,
|
||||||
|
current_usage,
|
||||||
|
unnormalized_cpu,
|
||||||
|
group_processes,
|
||||||
|
process_command,
|
||||||
|
regex,
|
||||||
|
whole_word,
|
||||||
|
disable_advanced_kill,
|
||||||
|
tree,
|
||||||
|
];
|
||||||
|
args.sort_unstable();
|
||||||
|
|
||||||
|
self.args(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cpu_args(self) -> Command {
|
||||||
|
const HEADING: &str = "CPU Options";
|
||||||
|
|
||||||
|
let hide_avg_cpu = Arg::new("hide_avg_cpu")
|
||||||
|
.short('a')
|
||||||
|
.long("hide_avg_cpu")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Hides the average CPU usage.")
|
||||||
|
.long_help("Hides the average CPU usage from being shown.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
self.arg(hide_avg_cpu)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_args(self) -> Command {
|
||||||
|
const HEADING: &str = "Memory Options";
|
||||||
|
|
||||||
|
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.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
#[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.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
self.args([mem_as_value, enable_cache_memory])
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
self.arg(mem_as_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn network_args(self) -> Command {
|
||||||
|
const HEADING: &str = "Network Options";
|
||||||
|
|
||||||
|
let use_old_network_legend = Arg::new("use_old_network_legend")
|
||||||
|
.long("use_old_network_legend")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("DEPRECATED - uses a separate network legend.")
|
||||||
|
.long_help(
|
||||||
|
"DEPRECATED - uses an older (pre-0.4), separate network widget legend. This display is not \
|
||||||
|
tested anymore and could be broken.",
|
||||||
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let network_use_bytes = Arg::new("network_use_bytes")
|
let network_use_bytes = Arg::new("network_use_bytes")
|
||||||
.long("network_use_bytes")
|
.long("network_use_bytes")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Displays the network widget using bytes.")
|
.help("Displays the network widget using bytes.")
|
||||||
.long_help("Displays the network widget using bytes. Defaults to bits.");
|
.long_help("Displays the network widget using bytes. Defaults to bits.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let network_use_log = Arg::new("network_use_log")
|
let network_use_log = Arg::new("network_use_log")
|
||||||
.long("network_use_log")
|
.long("network_use_log")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Displays the network widget with a log scale.")
|
.help("Displays the network widget with a log scale.")
|
||||||
.long_help("Displays the network widget with a log scale. Defaults to a non-log scale.");
|
.long_help("Displays the network widget with a log scale. Defaults to a non-log scale.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
let network_use_binary_prefix = Arg::new("network_use_binary_prefix")
|
let network_use_binary_prefix = Arg::new("network_use_binary_prefix")
|
||||||
.long("network_use_binary_prefix")
|
.long("network_use_binary_prefix")
|
||||||
@ -388,113 +534,106 @@ use CPU (3) as the default instead.
|
|||||||
.help("Displays the network widget with binary prefixes.")
|
.help("Displays the network widget with binary prefixes.")
|
||||||
.long_help(
|
.long_help(
|
||||||
"Displays the network widget with binary prefixes (i.e. kibibits, mebibits) rather than a decimal prefix (i.e. kilobits, megabits). Defaults to decimal prefixes.",
|
"Displays the network widget with binary prefixes (i.e. kibibits, mebibits) rather than a decimal prefix (i.e. kilobits, megabits). Defaults to decimal prefixes.",
|
||||||
);
|
)
|
||||||
|
.help_heading(HEADING);
|
||||||
let retention = Arg::new("retention")
|
|
||||||
.long("retention")
|
|
||||||
.action(ArgAction::Set)
|
|
||||||
.value_name("TIME")
|
|
||||||
.help("The timespan of data stored.")
|
|
||||||
.long_help("How much data is stored at once in terms of time. Takes a number in milliseconds or a human duration (e.g. 20m), with a minimum of 1 minute. Note higher values will take up more memory. Defaults to 10 minutes.");
|
|
||||||
|
|
||||||
let version = Arg::new("version")
|
|
||||||
.short('V')
|
|
||||||
.long("version")
|
|
||||||
.action(ArgAction::Version)
|
|
||||||
.help("Prints version information.");
|
|
||||||
|
|
||||||
const VERSION: &str = match option_env!("NIGHTLY_VERSION") {
|
|
||||||
Some(nightly_version) => nightly_version,
|
|
||||||
None => crate_version!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let temperature_group = ArgGroup::new("TEMPERATURE_TYPE").args([
|
|
||||||
kelvin.get_id(),
|
|
||||||
fahrenheit.get_id(),
|
|
||||||
celsius.get_id(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
let mut args = [
|
let mut args = [
|
||||||
version,
|
use_old_network_legend,
|
||||||
kelvin,
|
|
||||||
fahrenheit,
|
|
||||||
celsius,
|
|
||||||
autohide_time,
|
|
||||||
basic,
|
|
||||||
case_sensitive,
|
|
||||||
process_command,
|
|
||||||
config_location,
|
|
||||||
color,
|
|
||||||
mem_as_value,
|
|
||||||
default_time_value,
|
|
||||||
default_widget_count,
|
|
||||||
default_widget_type,
|
|
||||||
disable_click,
|
|
||||||
dot_marker,
|
|
||||||
group_processes,
|
|
||||||
hide_avg_cpu,
|
|
||||||
hide_table_gap,
|
|
||||||
hide_time,
|
|
||||||
show_table_scroll_position,
|
|
||||||
left_legend,
|
|
||||||
disable_advanced_kill,
|
|
||||||
rate,
|
|
||||||
regex,
|
|
||||||
time_delta,
|
|
||||||
tree,
|
|
||||||
network_use_bytes,
|
network_use_bytes,
|
||||||
network_use_log,
|
network_use_log,
|
||||||
network_use_binary_prefix,
|
network_use_binary_prefix,
|
||||||
current_usage,
|
];
|
||||||
unnormalized_cpu,
|
|
||||||
use_old_network_legend,
|
args.sort_unstable();
|
||||||
whole_word,
|
|
||||||
retention,
|
self.args(args)
|
||||||
expanded_on_startup,
|
}
|
||||||
|
|
||||||
|
fn battery_args(self) -> Command {
|
||||||
#[cfg(feature = "battery")]
|
#[cfg(feature = "battery")]
|
||||||
{
|
{
|
||||||
Arg::new("battery")
|
let battery = Arg::new("battery")
|
||||||
.long("battery")
|
.long("battery")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Shows the battery widget.")
|
.help("Shows the battery widget.")
|
||||||
.long_help(
|
.long_help(
|
||||||
"Shows the battery widget in default or basic mode. No effect on custom layouts.",
|
"Shows the battery widget in default or basic mode. No effect on custom layouts.",
|
||||||
)
|
)
|
||||||
},
|
.help_heading("Battery Options");
|
||||||
|
|
||||||
|
self.arg(battery)
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "battery"))]
|
||||||
|
{
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gpu_args(self) -> Command {
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
{
|
{
|
||||||
Arg::new("enable_gpu")
|
let enable_gpu = Arg::new("enable_gpu")
|
||||||
.long("enable_gpu")
|
.long("enable_gpu")
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Enable collecting and displaying GPU usage.")
|
.help("Enable collecting and displaying GPU usage.")
|
||||||
},
|
.help_heading("GPU Options");
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
|
self.arg(enable_gpu)
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "gpu"))]
|
||||||
{
|
{
|
||||||
Arg::new("enable_cache_memory")
|
self
|
||||||
.long("enable_cache_memory")
|
}
|
||||||
.action(ArgAction::SetTrue)
|
}
|
||||||
.help("Enable collecting and displaying cache and buffer memory.")
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// Manually sort the arguments.
|
fn other(self) -> Command {
|
||||||
args.sort_by(|a, b| {
|
const HEADING: &str = "Other Options";
|
||||||
let a = a.get_long().unwrap_or(a.get_id().as_str());
|
|
||||||
let b = b.get_long().unwrap_or(b.get_id().as_str());
|
|
||||||
|
|
||||||
a.cmp(b)
|
let version = Arg::new("version")
|
||||||
});
|
.short('V')
|
||||||
|
.long("version")
|
||||||
|
.action(ArgAction::Version)
|
||||||
|
.help("Prints version information.")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
let help = Arg::new("help")
|
||||||
|
.short('h')
|
||||||
|
.long("help")
|
||||||
|
.action(ArgAction::Help)
|
||||||
|
.help("Prints help (see more with '--help').")
|
||||||
|
.help_heading(HEADING);
|
||||||
|
|
||||||
|
self.args([version, help])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_app() -> Command {
|
||||||
|
const TEMPLATE: &str = include_str!("./args.template");
|
||||||
|
const USAGE: &str = "btm [OPTIONS]";
|
||||||
|
const VERSION: &str = match option_env!("NIGHTLY_VERSION") {
|
||||||
|
Some(nightly_version) => nightly_version,
|
||||||
|
None => crate_version!(),
|
||||||
|
};
|
||||||
|
|
||||||
Command::new(crate_name!())
|
Command::new(crate_name!())
|
||||||
.version(VERSION)
|
|
||||||
.author(crate_authors!())
|
.author(crate_authors!())
|
||||||
.about(crate_description!())
|
.about(crate_description!())
|
||||||
.color(ColorChoice::Auto)
|
.disable_help_flag(true)
|
||||||
.override_usage(USAGE)
|
|
||||||
.help_template(TEMPLATE)
|
|
||||||
.disable_version_flag(true)
|
.disable_version_flag(true)
|
||||||
.args(args)
|
.color(ColorChoice::Auto)
|
||||||
.group(temperature_group)
|
.help_template(TEMPLATE)
|
||||||
|
.override_usage(USAGE)
|
||||||
|
.version(VERSION)
|
||||||
|
.general_args()
|
||||||
|
.style_args()
|
||||||
|
.temperature_args()
|
||||||
|
.process_args()
|
||||||
|
.cpu_args()
|
||||||
|
.mem_args()
|
||||||
|
.network_args()
|
||||||
|
.battery_args()
|
||||||
|
.gpu_args()
|
||||||
|
.other()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -505,4 +644,15 @@ mod test {
|
|||||||
fn verify_cli() {
|
fn verify_cli() {
|
||||||
build_app().debug_assert();
|
build_app().debug_assert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn help_heading_no_default() {
|
||||||
|
let mut app = build_app();
|
||||||
|
let help_str = app.render_help();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
!help_str.to_string().contains("\nOptions:\n"),
|
||||||
|
"the default 'Options' heading should not exist; if it does then an argument is missing a help heading."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
src/options/args.template
Normal file
8
src/options/args.template
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{name} {version}
|
||||||
|
{author}
|
||||||
|
|
||||||
|
{about}
|
||||||
|
|
||||||
|
{usage-heading} {usage}
|
||||||
|
|
||||||
|
{all-args}
|
Loading…
x
Reference in New Issue
Block a user