Skip to content

Commit db4bcc6

Browse files
committed
release: 0.3.0
2 parents cffa1c5 + f2d9caf commit db4bcc6

File tree

14 files changed

+303
-340
lines changed

14 files changed

+303
-340
lines changed

CREDITS.md

Lines changed: 62 additions & 279 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Build Status](https://github.com/Blobfolio/bashman/workflows/Build/badge.svg)](https://github.com/Blobfolio/bashman/actions)
44
[![Dependency Status](https://deps.rs/repo/github/blobfolio/bashman/status.svg)](https://deps.rs/repo/github/blobfolio/bashman)
55

6-
`BashMan` is a Cargo plugin that helps you generate BASH completions and/or MAN pages for your Rust apps using metadata from your projects' `Cargo.toml` manifests. It pairs well with the (unaffiliated) [cargo-deb](https://github.com/mmstick/cargo-deb).
6+
`BashMan` is a Cargo plugin that helps you generate BASH completions, MAN pages, and/or a `CREDITS.md` page for your Rust apps using metadata from your projects' `Cargo.toml` manifests. It pairs well with the (unaffiliated) [cargo-deb](https://github.com/mmstick/cargo-deb).
77

88
(This can technically be used for non-Rust apps. It just parses the data out of a [TOML](https://en.wikipedia.org/wiki/TOML) file. Any TOML'll do.)
99

@@ -48,12 +48,14 @@ cargo build \
4848

4949
```bash
5050
# Generate the stuff for the thing:
51-
cargo bashman [-m/--manifest-path] /path/to/Cargo.toml
51+
cargo bashman [--manifest-path /path/to/Cargo.toml]
5252

5353
# You can also pull up help via:
5454
cargo bashman [-h/--help]
5555
```
5656

57+
The flags `--no-bash`, `--no-man`, and `--no-credits` can be used to skip the generation of BASH completions, MAN pages, and/or `CREDITS.md` respectively.
58+
5759

5860
## CONFIGURATION
5961

@@ -66,19 +68,24 @@ For everything else, start by adding a section to your `Cargo.toml` manifest lik
6668
name = "Cargo BashMan"
6769
bash-dir = "../release/completions"
6870
man-dir = "../release/man"
71+
credits-dir = "../"
6972
```
7073

7174
| Key | Type | Description | Default |
7275
| --- | ---- | ----------- | ------- |
7376
| name | *string* | The proper name of your application. | If not provided, the binary name is used. |
7477
| bash-dir | *directory* | The output directory for BASH completions. This can be an absolute path, or a path relative to the manifest. | If not provided, the manifest's parent directory is used. |
78+
| credits-dir | *directory* | The output directory for the `CREDITS.md` dependency list. This can be an absolute path, or a path relative to the manifest. | If not provided, the manifest's parent directory is used. |
7579
| man-dir | *directory* | The output directory for MAN page(s). This can be an absolute path, or a path relative to the manifest. | If not provided, the manifest's parent directory is used. |
7680
| subcommands | *array* | An array of your app's subcommands, if any. | |
7781
| switches | *array* | An array of your app's true/false flags, if any. | |
7882
| options | *array* | An array of your app's key=value options, if any. | |
7983
| arguments | *array* | An array of any trailing arguments expected by your app. | |
8084
| sections | *array* | Arbitrary sections to append to the MAN page. | |
8185

86+
While `bash-dir`, `man-dir`, and `credits-dir` are required, the actual content generation can be skipped by using the CLI flags `--no-bash`, `--no-man`, and/or `--no-credits` respectively.
87+
88+
8289
### SUBCOMMANDS
8390

8491
When adding subcommands, each entry requires the following fields:
@@ -99,6 +106,7 @@ cmd="whale"
99106
description="Print an underwater message."
100107
```
101108

109+
102110
### SWITCHES
103111

104112
A "switch" is a CLI flag that either is or isn't. It can be a short key, like `-h`, or a long key like `--help`, or both. The value is implicitly `true` if the flag is present, or `false` if not.
@@ -126,6 +134,7 @@ description = "Print help information."
126134
subcommands = [ "call", "text", "" ]
127135
```
128136

137+
129138
### OPTIONS
130139

131140
An "option" is exactly like a "switch", except it takes a value. As such, they have a couple more fields:
@@ -156,6 +165,7 @@ label = "<NUM>"
156165
subcommands = [ "print", "echo" ]
157166
```
158167

168+
159169
### ARGUMENTS
160170

161171
A trailing argument is what comes after everything else.
@@ -174,6 +184,7 @@ description = "Files and directories to search."
174184
subcommands = [ "search" ]
175185
```
176186

187+
177188
### SECTIONS
178189

179190
`BashMan` will automatically generate manual sections for:
@@ -215,6 +226,7 @@ items = [
215226
]
216227
```
217228

229+
218230
### ALL TOGETHER NOW
219231

220232
Taking `BashMan` as an example, the `Cargo.toml` will end up containing something like:
@@ -230,6 +242,7 @@ description = "BashMan is a Cargo plugin that helps you generate BASH completion
230242
name = "Cargo BashMan"
231243
bash-dir = "../release/completions"
232244
man-dir = "../release/man"
245+
credits-dir = "../"
233246

234247
[[package.metadata.bashman.switches]]
235248
short = "-h"

about.toml

Lines changed: 0 additions & 12 deletions
This file was deleted.

bashman/Cargo.toml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cargo-bashman"
3-
version = "0.2.9"
3+
version = "0.3.0"
44
license = "WTFPL"
55
authors = ["Josh Stoik <[email protected]>"]
66
edition = "2021"
@@ -26,12 +26,24 @@ assets = [
2626
name = "Cargo BashMan"
2727
bash-dir = "../release/completions"
2828
man-dir = "../release/man"
29+
credits-dir = "../"
2930

3031
[[package.metadata.bashman.switches]]
3132
short = "-h"
3233
long = "--help"
3334
description = "Print help information."
34-
subcommands = [ "", "sub" ]
35+
36+
[[package.metadata.bashman.switches]]
37+
long = "--no-bash"
38+
description = "Do not generate BASH completions."
39+
40+
[[package.metadata.bashman.switches]]
41+
long = "--no-credits"
42+
description = "Do not generate CREDITS.md."
43+
44+
[[package.metadata.bashman.switches]]
45+
long = "--no-man"
46+
description = "Do not generate MAN page(s)."
3547

3648
[[package.metadata.bashman.switches]]
3749
short = "-V"

bashman/src/main.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,14 @@ For everything else, start by adding a section to your `Cargo.toml` manifest lik
5151
name = "Cargo BashMan"
5252
bash-dir = "../release/bash_completion.d"
5353
man-dir = "../release/man1"
54+
credits-dir = "../"
5455
```
5556
5657
| Key | Type | Description | Default |
5758
| --- | ---- | ----------- | ------- |
5859
| name | *string* | The proper name of your application. | If not provided, the binary name is used. |
5960
| bash-dir | *directory* | The output directory for BASH completions. This can be an absolute path, or a path relative to the manifest. | If not provided, the manifest's parent directory is used. |
61+
| credits-dir | *directory* | The output directory for the `CREDITS.md` dependency list. This can be an absolute path, or a path relative to the manifest. | If not provided, the manifest's parent directory is used. |
6062
| man-dir | *directory* | The output directory for MAN page(s). This can be an absolute path, or a path relative to the manifest. | If not provided, the manifest's parent directory is used. |
6163
| subcommands | *array* | An array of your app's subcommands, if any. | |
6264
| switches | *array* | An array of your app's true/false flags, if any. | |
@@ -256,7 +258,13 @@ path = true
256258
#![allow(clippy::module_name_repetitions)]
257259

258260

259-
use bashman_core::BashManError;
261+
use bashman_core::{
262+
BashManError,
263+
FLAG_ALL,
264+
FLAG_BASH,
265+
FLAG_CREDITS,
266+
FLAG_MAN,
267+
};
260268
use argyle::{
261269
Argue,
262270
ArgyleError,
@@ -294,6 +302,17 @@ fn _main() -> Result<(), BashManError> {
294302
// Parse CLI arguments.
295303
let args = Argue::new(FLAG_HELP | FLAG_VERSION).map_err(BashManError::Argue)?;
296304

305+
let mut flags: u8 = FLAG_ALL;
306+
if args.switch(b"--no-bash") {
307+
flags &= ! FLAG_BASH;
308+
}
309+
if args.switch(b"--no-credits") {
310+
flags &= ! FLAG_CREDITS;
311+
}
312+
if args.switch(b"--no-man") {
313+
flags &= ! FLAG_MAN;
314+
}
315+
297316
bashman_core::parse(
298317
args.option2(b"-m", b"--manifest-path")
299318
.map_or_else(
@@ -303,7 +322,8 @@ fn _main() -> Result<(), BashManError> {
303322
}),
304323
|b| Some(PathBuf::from(OsStr::from_bytes(b)))
305324
)
306-
.ok_or(BashManError::InvalidManifest)?
325+
.ok_or(BashManError::InvalidManifest)?,
326+
flags,
307327
)?;
308328

309329
Ok(())
@@ -334,6 +354,9 @@ USAGE:
334354
335355
FLAGS:
336356
-h, --help Prints help information.
357+
--no-bash Do not generate BASH completions.
358+
--no-credits Do not generate CREDITS.md.
359+
--no-man Do not generate MAN page(s).
337360
-V, --version Prints version information.
338361
339362
OPTIONS:

bashman_core/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bashman_core"
3-
version = "0.2.9"
3+
version = "0.3.0"
44
license = "WTFPL"
55
authors = ["Josh Stoik <[email protected]>"]
66
edition = "2021"
@@ -11,9 +11,12 @@ publish = false
1111

1212
[dependencies]
1313
argyle = "0.5.*"
14+
cargo-license = "0.4.*"
15+
cargo_metadata = "0.14.*"
1416
fyi_msg = "0.9.*"
1517
indexmap = "1.7.*"
1618
libdeflater = "0.7.*"
19+
regex = "1.5.*"
1720
utc2k = "0.3.*"
1821

1922
[dependencies.serde]

bashman_core/src/data.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@ This module contains the [`Command`] and related data structures produced from
55
[`Raw`]. See that module for more information on why all the windiness.
66
*/
77

8+
use cargo_metadata::MetadataCommand;
89
use crate::BashManError;
910
use fyi_msg::Msg;
1011
use libdeflater::{
1112
CompressionLvl,
1213
Compressor,
1314
};
15+
use regex::Regex;
1416
use std::{
1517
ffi::OsStr,
1618
fs::File,
1719
io::Write,
1820
os::unix::ffi::OsStrExt,
1921
path::Path,
2022
};
23+
use utc2k::Utc2k;
2124

2225

2326

@@ -505,6 +508,101 @@ impl<'a> Command<'a> {
505508
}
506509
}
507510

511+
/// # Credits.
512+
impl<'a> Command<'a> {
513+
/// # Write Bash.
514+
pub(crate) fn write_credits(&self, manifest: &Path, path: &Path, buf: &mut Vec<u8>) -> Result<(), BashManError> {
515+
let re: Regex = Regex::new(r"([^\|]+?) <([^>]+)>").unwrap();
516+
517+
let meta = {
518+
let mut tmp = MetadataCommand::new();
519+
tmp.manifest_path(&manifest);
520+
tmp
521+
};
522+
523+
let mut raw: Vec<(String, String)> = cargo_license::get_dependencies_from_cargo_lock(
524+
meta,
525+
true,
526+
true,
527+
)
528+
.map_err(|_| BashManError::InvalidManifest)?
529+
.into_iter()
530+
.filter_map(|x| {
531+
let name = x.name.replace("|", "");
532+
if name == self.bin {
533+
return None;
534+
}
535+
536+
let version = x.version.to_string().replace("|", "");
537+
let author = x.authors.map_or_else(
538+
String::new,
539+
|y| {
540+
let y = y.replace(" <>", "");
541+
let z = re.replace_all(&y, "[$1](mailto:$2)");
542+
z.replace("|", "; ")
543+
},
544+
);
545+
let license = x.license.map_or_else(
546+
|| String::from("Unknown"),
547+
|y| y.replace("|", ""),
548+
);
549+
550+
let line = x.repository.map_or_else(
551+
|| format!(
552+
"\n| {} | {} | {} | {} |",
553+
name,
554+
version,
555+
author,
556+
license,
557+
),
558+
|y| format!(
559+
"\n| [{}]({}) | {} | {} | {} |",
560+
name,
561+
y.replace("|", ""),
562+
version,
563+
author,
564+
license,
565+
)
566+
);
567+
568+
Some((name.to_ascii_lowercase(), line))
569+
})
570+
.collect();
571+
572+
// Write the header.
573+
buf.extend_from_slice(format!(
574+
"# Project Dependencies\n Package: {}\n Version: {}\n Generated: {} UTC\n",
575+
self.bin,
576+
self.version,
577+
Utc2k::now().to_string(),
578+
).as_bytes());
579+
580+
if raw.is_empty() {
581+
buf.extend_from_slice(b"This package has no dependencies.\n");
582+
}
583+
else {
584+
buf.extend_from_slice(b"\n| Package | Version | Author(s) | License |\n| ---- | ---- | ---- | ---- |");
585+
raw.sort_by(|a, b| a.0.cmp(&b.0));
586+
for (_, line) in raw {
587+
buf.extend_from_slice(line.as_bytes());
588+
}
589+
590+
buf.push(b'\n');
591+
}
592+
593+
let mut out = path.to_path_buf();
594+
out.push("CREDITS.md");
595+
596+
// Write plain.
597+
File::create(&out)
598+
.and_then(|mut f| f.write_all(buf).and_then(|_| f.flush()))
599+
.map_err(|_| BashManError::WriteCredits)?;
600+
601+
Msg::success(format!("Credits written to: {:?}", out)).print();
602+
Ok(())
603+
}
604+
}
605+
508606

509607

510608
#[derive(Debug, Clone)]

0 commit comments

Comments
 (0)