Skip to content

Commit dc0468c

Browse files
authored
Generate completion & manpage (#357)
* Generate completion & manpage * Write changelog
1 parent 592f733 commit dc0468c

File tree

7 files changed

+111
-24
lines changed

7 files changed

+111
-24
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
66

77
## [Unreleased]
88

9+
## [0.22.2] - 2024-01-28
10+
11+
## Added
12+
13+
* Generate completion & manpage #357 - @cyqsimon
14+
915
## [0.22.1] - 2024-01-28
1016

1117
## Fixed

Cargo.lock

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+9-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,15 @@ pnet_base = "0.34.0"
6060
regex = "1.10.3"
6161
rstest = "0.18.2"
6262

63-
[target.'cfg(target_os = "windows")'.build-dependencies]
63+
[build-dependencies]
6464
anyhow = "1.0.79"
65+
clap = { version = "4.4.18", features = ["derive"] }
66+
clap-verbosity-flag = "2.1.2"
67+
clap_complete = "4.4.9"
68+
clap_mangen = "0.2.17"
69+
derivative = "2.2.0"
70+
strum = { version = "0.25.0", features = ["derive"] }
71+
72+
[target.'cfg(target_os = "windows")'.build-dependencies]
6573
http_req = "0.10.2"
6674
zip = "0.6.6"

build.rs

+33
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
1+
use std::{env, fs::File};
2+
3+
use anyhow::anyhow;
4+
use clap::CommandFactory;
5+
use clap_complete::Shell;
6+
use clap_mangen::Man;
7+
18
fn main() {
9+
build_completion_manpage().unwrap();
10+
211
#[cfg(target_os = "windows")]
312
download_windows_npcap_sdk().unwrap();
413
}
514

15+
include!("src/cli.rs");
16+
17+
fn build_completion_manpage() -> anyhow::Result<()> {
18+
let mut cmd = Opt::command();
19+
20+
// build into `BANDWHICH_GEN_DIR` with a fallback to `OUT_DIR`
21+
let gen_dir: PathBuf = env::var_os("BANDWHICH_GEN_DIR")
22+
.or_else(|| env::var_os("OUT_DIR"))
23+
.ok_or(anyhow!("OUT_DIR is unset"))?
24+
.into();
25+
26+
// completion
27+
for &shell in Shell::value_variants() {
28+
clap_complete::generate_to(shell, &mut cmd, "bandwhich", &gen_dir)?;
29+
}
30+
31+
// manpage
32+
let mut manpage_out = File::create(gen_dir.join("bandwhich.1"))?;
33+
let manpage = Man::new(cmd);
34+
manpage.render(&mut manpage_out)?;
35+
36+
Ok(())
37+
}
38+
639
#[cfg(target_os = "windows")]
740
fn download_windows_npcap_sdk() -> anyhow::Result<()> {
841
use std::{

src/cli.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use std::{net::Ipv4Addr, path::PathBuf};
22

3-
use clap::{Args, Parser};
3+
use clap::{Args, Parser, ValueEnum, ValueHint};
44
use clap_verbosity_flag::{InfoLevel, Verbosity};
55
use derivative::Derivative;
6-
7-
use crate::display::BandwidthUnitFamily;
6+
use strum::EnumIter;
87

98
#[derive(Clone, Debug, Derivative, Parser)]
109
#[derivative(Default)]
@@ -30,7 +29,7 @@ pub struct Opt {
3029
/// A dns server ip to use instead of the system default
3130
pub dns_server: Option<Ipv4Addr>,
3231

33-
#[arg(long)]
32+
#[arg(long, value_hint = ValueHint::FilePath)]
3433
/// Enable debug logging to a file
3534
pub log_to: Option<PathBuf>,
3635

@@ -58,9 +57,24 @@ pub struct RenderOpts {
5857

5958
#[arg(short, long, value_enum, default_value_t)]
6059
/// Choose a specific family of units
61-
pub unit_family: BandwidthUnitFamily,
60+
pub unit_family: UnitFamily,
6261

6362
#[arg(short, long)]
6463
/// Show total (cumulative) usages
6564
pub total_utilization: bool,
6665
}
66+
67+
// IMPRV: it would be nice if we can `#[cfg_attr(not(build), derive(strum::EnumIter))]` this
68+
// unfortunately there is no configuration option for build script detection
69+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, ValueEnum, EnumIter)]
70+
pub enum UnitFamily {
71+
#[default]
72+
/// bytes, in powers of 2^10
73+
BinBytes,
74+
/// bits, in powers of 2^10
75+
BinBits,
76+
/// bytes, in powers of 10^3
77+
SiBytes,
78+
/// bits, in powers of 10^3
79+
SiBits,
80+
}

src/display/components/display_bandwidth.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::fmt;
22

3-
use clap::ValueEnum;
4-
use strum::EnumIter;
3+
use derivative::Derivative;
4+
5+
use crate::cli::UnitFamily;
56

67
#[derive(Copy, Clone, Debug)]
78
pub struct DisplayBandwidth {
@@ -16,17 +17,14 @@ impl fmt::Display for DisplayBandwidth {
1617
}
1718
}
1819

19-
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, ValueEnum, EnumIter)]
20-
pub enum BandwidthUnitFamily {
21-
#[default]
22-
/// bytes, in powers of 2^10
23-
BinBytes,
24-
/// bits, in powers of 2^10
25-
BinBits,
26-
/// bytes, in powers of 10^3
27-
SiBytes,
28-
/// bits, in powers of 10^3
29-
SiBits,
20+
/// Type wrapper around [`UnitFamily`] to provide extra functionality.
21+
#[derive(Copy, Clone, Derivative, Default, Eq, PartialEq)]
22+
#[derivative(Debug = "transparent")]
23+
pub struct BandwidthUnitFamily(UnitFamily);
24+
impl From<UnitFamily> for BandwidthUnitFamily {
25+
fn from(value: UnitFamily) -> Self {
26+
Self(value)
27+
}
3028
}
3129
impl BandwidthUnitFamily {
3230
#[inline]
@@ -39,9 +37,9 @@ impl BandwidthUnitFamily {
3937
/// Binary base: 2^10.
4038
const BB: f64 = 1024.0;
4139

42-
use BandwidthUnitFamily as F;
40+
use UnitFamily as F;
4341
// probably could macro this stuff, but I'm too lazy
44-
match self {
42+
match self.0 {
4543
F::BinBytes => [
4644
(1.0, BB * STEP_UP_FRAC, "B"),
4745
(BB, BB.powi(2) * STEP_UP_FRAC, "KiB"),
@@ -99,11 +97,12 @@ mod tests {
9997
use itertools::Itertools;
10098
use strum::IntoEnumIterator;
10199

102-
use crate::display::{BandwidthUnitFamily, DisplayBandwidth};
100+
use crate::{cli::UnitFamily, display::DisplayBandwidth};
103101

104102
#[test]
105103
fn bandwidth_formatting() {
106-
let test_bandwidths_formatted = BandwidthUnitFamily::iter()
104+
let test_bandwidths_formatted = UnitFamily::iter()
105+
.map_into()
107106
.cartesian_product(
108107
// I feel like this is a decent selection of values
109108
(-6..60)

src/display/ui.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ where
3333
let state = {
3434
let mut state = UIState::default();
3535
state.interface_name = opts.interface.clone();
36-
state.unit_family = opts.render_opts.unit_family;
36+
state.unit_family = opts.render_opts.unit_family.into();
3737
state.cumulative_mode = opts.render_opts.total_utilization;
3838
state
3939
};

0 commit comments

Comments
 (0)