mirror of
https://github.com/imsnif/bandwhich.git
synced 2026-02-09 01:59:18 +08:00
Generate completion & manpage (#357)
* Generate completion & manpage * Write changelog
This commit is contained in:
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.22.2] - 2024-01-28
|
||||
|
||||
## Added
|
||||
|
||||
* Generate completion & manpage #357 - @cyqsimon
|
||||
|
||||
## [0.22.1] - 2024-01-28
|
||||
|
||||
## Fixed
|
||||
|
||||
27
Cargo.lock
generated
27
Cargo.lock
generated
@@ -168,6 +168,8 @@ dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap-verbosity-flag",
|
||||
"clap_complete",
|
||||
"clap_mangen",
|
||||
"crossterm",
|
||||
"derivative",
|
||||
"http_req",
|
||||
@@ -340,6 +342,15 @@ dependencies = [
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df631ae429f6613fcd3a7c1adbdb65f637271e561b03680adaa6573015dfb106"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.7"
|
||||
@@ -358,6 +369,16 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "clap_mangen"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a7c2b01e5e779c19f46a94bbd398f33ae63b0f78c07108351fb4536845bb7fd"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"roff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
@@ -1514,6 +1535,12 @@ dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roff"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
|
||||
|
||||
[[package]]
|
||||
name = "rstest"
|
||||
version = "0.18.2"
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -60,7 +60,15 @@ pnet_base = "0.34.0"
|
||||
regex = "1.10.3"
|
||||
rstest = "0.18.2"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.build-dependencies]
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.79"
|
||||
clap = { version = "4.4.18", features = ["derive"] }
|
||||
clap-verbosity-flag = "2.1.2"
|
||||
clap_complete = "4.4.9"
|
||||
clap_mangen = "0.2.17"
|
||||
derivative = "2.2.0"
|
||||
strum = { version = "0.25.0", features = ["derive"] }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.build-dependencies]
|
||||
http_req = "0.10.2"
|
||||
zip = "0.6.6"
|
||||
|
||||
33
build.rs
33
build.rs
@@ -1,8 +1,41 @@
|
||||
use std::{env, fs::File};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use clap::CommandFactory;
|
||||
use clap_complete::Shell;
|
||||
use clap_mangen::Man;
|
||||
|
||||
fn main() {
|
||||
build_completion_manpage().unwrap();
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
download_windows_npcap_sdk().unwrap();
|
||||
}
|
||||
|
||||
include!("src/cli.rs");
|
||||
|
||||
fn build_completion_manpage() -> anyhow::Result<()> {
|
||||
let mut cmd = Opt::command();
|
||||
|
||||
// build into `BANDWHICH_GEN_DIR` with a fallback to `OUT_DIR`
|
||||
let gen_dir: PathBuf = env::var_os("BANDWHICH_GEN_DIR")
|
||||
.or_else(|| env::var_os("OUT_DIR"))
|
||||
.ok_or(anyhow!("OUT_DIR is unset"))?
|
||||
.into();
|
||||
|
||||
// completion
|
||||
for &shell in Shell::value_variants() {
|
||||
clap_complete::generate_to(shell, &mut cmd, "bandwhich", &gen_dir)?;
|
||||
}
|
||||
|
||||
// manpage
|
||||
let mut manpage_out = File::create(gen_dir.join("bandwhich.1"))?;
|
||||
let manpage = Man::new(cmd);
|
||||
manpage.render(&mut manpage_out)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn download_windows_npcap_sdk() -> anyhow::Result<()> {
|
||||
use std::{
|
||||
|
||||
24
src/cli.rs
24
src/cli.rs
@@ -1,10 +1,9 @@
|
||||
use std::{net::Ipv4Addr, path::PathBuf};
|
||||
|
||||
use clap::{Args, Parser};
|
||||
use clap::{Args, Parser, ValueEnum, ValueHint};
|
||||
use clap_verbosity_flag::{InfoLevel, Verbosity};
|
||||
use derivative::Derivative;
|
||||
|
||||
use crate::display::BandwidthUnitFamily;
|
||||
use strum::EnumIter;
|
||||
|
||||
#[derive(Clone, Debug, Derivative, Parser)]
|
||||
#[derivative(Default)]
|
||||
@@ -30,7 +29,7 @@ pub struct Opt {
|
||||
/// A dns server ip to use instead of the system default
|
||||
pub dns_server: Option<Ipv4Addr>,
|
||||
|
||||
#[arg(long)]
|
||||
#[arg(long, value_hint = ValueHint::FilePath)]
|
||||
/// Enable debug logging to a file
|
||||
pub log_to: Option<PathBuf>,
|
||||
|
||||
@@ -58,9 +57,24 @@ pub struct RenderOpts {
|
||||
|
||||
#[arg(short, long, value_enum, default_value_t)]
|
||||
/// Choose a specific family of units
|
||||
pub unit_family: BandwidthUnitFamily,
|
||||
pub unit_family: UnitFamily,
|
||||
|
||||
#[arg(short, long)]
|
||||
/// Show total (cumulative) usages
|
||||
pub total_utilization: bool,
|
||||
}
|
||||
|
||||
// IMPRV: it would be nice if we can `#[cfg_attr(not(build), derive(strum::EnumIter))]` this
|
||||
// unfortunately there is no configuration option for build script detection
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, ValueEnum, EnumIter)]
|
||||
pub enum UnitFamily {
|
||||
#[default]
|
||||
/// bytes, in powers of 2^10
|
||||
BinBytes,
|
||||
/// bits, in powers of 2^10
|
||||
BinBits,
|
||||
/// bytes, in powers of 10^3
|
||||
SiBytes,
|
||||
/// bits, in powers of 10^3
|
||||
SiBits,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use std::fmt;
|
||||
|
||||
use clap::ValueEnum;
|
||||
use strum::EnumIter;
|
||||
use derivative::Derivative;
|
||||
|
||||
use crate::cli::UnitFamily;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct DisplayBandwidth {
|
||||
@@ -16,17 +17,14 @@ impl fmt::Display for DisplayBandwidth {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, ValueEnum, EnumIter)]
|
||||
pub enum BandwidthUnitFamily {
|
||||
#[default]
|
||||
/// bytes, in powers of 2^10
|
||||
BinBytes,
|
||||
/// bits, in powers of 2^10
|
||||
BinBits,
|
||||
/// bytes, in powers of 10^3
|
||||
SiBytes,
|
||||
/// bits, in powers of 10^3
|
||||
SiBits,
|
||||
/// Type wrapper around [`UnitFamily`] to provide extra functionality.
|
||||
#[derive(Copy, Clone, Derivative, Default, Eq, PartialEq)]
|
||||
#[derivative(Debug = "transparent")]
|
||||
pub struct BandwidthUnitFamily(UnitFamily);
|
||||
impl From<UnitFamily> for BandwidthUnitFamily {
|
||||
fn from(value: UnitFamily) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl BandwidthUnitFamily {
|
||||
#[inline]
|
||||
@@ -39,9 +37,9 @@ impl BandwidthUnitFamily {
|
||||
/// Binary base: 2^10.
|
||||
const BB: f64 = 1024.0;
|
||||
|
||||
use BandwidthUnitFamily as F;
|
||||
use UnitFamily as F;
|
||||
// probably could macro this stuff, but I'm too lazy
|
||||
match self {
|
||||
match self.0 {
|
||||
F::BinBytes => [
|
||||
(1.0, BB * STEP_UP_FRAC, "B"),
|
||||
(BB, BB.powi(2) * STEP_UP_FRAC, "KiB"),
|
||||
@@ -99,11 +97,12 @@ mod tests {
|
||||
use itertools::Itertools;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::display::{BandwidthUnitFamily, DisplayBandwidth};
|
||||
use crate::{cli::UnitFamily, display::DisplayBandwidth};
|
||||
|
||||
#[test]
|
||||
fn bandwidth_formatting() {
|
||||
let test_bandwidths_formatted = BandwidthUnitFamily::iter()
|
||||
let test_bandwidths_formatted = UnitFamily::iter()
|
||||
.map_into()
|
||||
.cartesian_product(
|
||||
// I feel like this is a decent selection of values
|
||||
(-6..60)
|
||||
|
||||
@@ -33,7 +33,7 @@ where
|
||||
let state = {
|
||||
let mut state = UIState::default();
|
||||
state.interface_name = opts.interface.clone();
|
||||
state.unit_family = opts.render_opts.unit_family;
|
||||
state.unit_family = opts.render_opts.unit_family.into();
|
||||
state.cumulative_mode = opts.render_opts.total_utilization;
|
||||
state
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user