Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revise exit status section #30

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ fn main() {
Section::new("usage note")
.paragraph("This program will overwrite any file currently stored at the output path")
)
.exit_status(ExitStatus::default())
.render();

println!("{}", page);
Expand Down
6 changes: 1 addition & 5 deletions examples/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fn main() {
.long("--port")
.help("The network port to listen to."),
)
.exit_status(ExitStatus::default())
.example(
Example::new()
.text("listen on port 3000")
Expand All @@ -43,11 +44,6 @@ fn main() {
.prompt("#")
.command("auth-service"),
)
.custom(
Section::new("custom section")
.paragraph("text for the custom section")
.paragraph("Additional text for the custom section"),
)
.author(Author::new("Alice Person").email("[email protected]"))
.author(Author::new("Bob Human").email("[email protected]"))
.render();
Expand Down
61 changes: 61 additions & 0 deletions examples/without-defaults.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
extern crate man;

use man::prelude::*;

fn main() {
let msg = Manual::new("auth-service")
.arg(Arg::new("path"))
.env(Env::new("PORT").help("The network port to listen to"))
.flag(
Flag::new()
.short("-h")
.long("--help")
.help("Prints help information."),
)
.flag(
Flag::new()
.short("-V")
.long("--version")
.help("Prints version information."),
)
.flag(
Flag::new()
.short("-v")
.long("--verbosity")
.help("Pass multiple times to print more information."),
)
.option(
Opt::new("port")
.short("-p")
.long("--port")
.help("The network port to listen to."),
)
.custom(
Section::new("custom section")
.paragraph("text for the custom section")
.paragraph("Additional text for the custom section"),
)
.custom(
Section::new("second custom section")
.paragraph("text for the custom section")
.paragraph("Additional text for the custom section"),
)
.exit_status(ExitStatus::new(0))
.example(
Example::new()
.text("listen on port 3000")
.command("auth-service -p 3000")
.output("now listening on port 3000"),
)
.example(
Example::new()
.text("auth-service may need to be run by root")
.prompt("#")
.command("auth-service"),
)
.author(Author::new("Alice Person").email("[email protected]"))
.author(Author::new("Bob Human").email("[email protected]"))
.render();

println!("{}", msg);
}
20 changes: 20 additions & 0 deletions src/exit_status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// Add a exit status section
#[derive(Debug, Clone, Default)]
pub struct ExitStatus {
pub(crate) code: Option<i32>,
pub(crate) description: Option<&'static str>,
}

impl ExitStatus {
pub fn new(code: i32) -> Self {
Self {
code: Some(code),
description: None,
}
}

pub fn description(mut self, description: &'static str) -> Self {
self.description = Some(description);
self
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod arg;
mod author;
mod environment;
mod example;
mod exit_status;
mod flag;
mod man;
mod option;
Expand All @@ -20,6 +21,7 @@ pub use arg::Arg;
pub use author::Author;
pub use environment::Env;
pub use example::Example;
pub use exit_status::ExitStatus;
pub use flag::Flag;
pub use man::Manual;
pub use option::Opt;
Expand Down
83 changes: 70 additions & 13 deletions src/man.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,50 @@ pub struct Manual {
environment: Vec<Env>,
arguments: Vec<Arg>,
custom_sections: Vec<Section>,
exit_statuses: ExitStatuses,
examples: Vec<Example>,
}

#[derive(Debug, Clone)]
enum ExitStatuses {
DefaultStatuses,
CustomStatuses(Vec<ExitStatus>),
}

static DEFAULT_STATUSES: [ExitStatus; 3] = [
ExitStatus {
code: Some(0),
description: Some("Successful program execution."),
},
ExitStatus {
code: Some(1),
description: Some("Unsuccessful program execution."),
},
ExitStatus {
code: Some(101),
description: Some("The program panicked."),
},
];

impl ExitStatuses {
fn push(&mut self, new_status: ExitStatus) {
if let ExitStatuses::CustomStatuses(vec) = self {
vec.push(new_status);
}
}

fn set_to_default(&mut self) {
*self = ExitStatuses::DefaultStatuses;
}

fn iter(&self) -> impl Iterator<Item = &ExitStatus> {
match self {
ExitStatuses::CustomStatuses(vec) => vec.iter(),
ExitStatuses::DefaultStatuses => DEFAULT_STATUSES.iter(),
}
}
}

impl Manual {
/// Create a new instance.
pub fn new(name: &str) -> Self {
Expand All @@ -29,6 +70,7 @@ impl Manual {
arguments: vec![],
environment: vec![],
custom_sections: vec![],
exit_statuses: ExitStatuses::CustomStatuses(vec![]),
examples: vec![],
}
}
Expand Down Expand Up @@ -89,6 +131,18 @@ impl Manual {
self
}

pub fn exit_status(mut self, exit_status: ExitStatus) -> Self {
match exit_status {
ExitStatus { code: None, .. } => {
self.exit_statuses.set_to_default();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so this line is what I was missing! I didn't get when you would ever set the exit status list to the default list – I assumed it was the set you were starting with and then when you add a custom one it gets overwritten.

This behavior here is surprising to me: When you call this public function, that has no docs, with a "special" value (code = None), it does an unusual thing. What's also weird: To get this special input you'd have to call default(), but from what I can tell this "special" mode should not be the "default".

}
_ => {
self.exit_statuses.push(exit_status);
}
}
self
}

/// Render to a string.
pub fn render(self) -> String {
let man_num = 1;
Expand All @@ -108,7 +162,7 @@ impl Manual {
for section in self.custom_sections.into_iter() {
page = custom(page, section);
}
page = exit_status(page);
page = exit_status(page, &self.exit_statuses);
page = examples(page, &self.examples);
page = authors(page, &self.authors);
page.render()
Expand Down Expand Up @@ -336,9 +390,9 @@ fn env(page: Roff, environment: &[Env]) -> Roff {

/// Create a `EXIT STATUS` section.
///
/// ## Implementation Note
/// This currently only returns the status code `0`, and takes no arguments. We
/// should let it take arguments.
/// If initialized with the default method, this will have status codes of 0
/// (success), 1 (failure), and 101 (panic). Alternatively, it can be initialized
/// with custom codes and descriptions.
///
/// ## Formatting
/// ```txt
Expand All @@ -349,15 +403,18 @@ fn env(page: Roff, environment: &[Env]) -> Roff {
///
/// 2 Optional error
/// ```
fn exit_status(page: Roff) -> Roff {
page.section(
"EXIT STATUS",
&[
list(&[bold("0")], &["Successful program execution.\n\n"]),
list(&[bold("1")], &["Unsuccessful program execution.\n\n"]),
list(&[bold("101")], &["The program panicked."]),
],
)
fn exit_status(page: Roff, exit_statuses: &ExitStatuses) -> Roff {
if exit_statuses.iter().next().is_none() {
return page;
}
let mut arr = vec![];
for status in exit_statuses.iter() {
let code = format!("{}", status.code.expect("set by `.new()` method"));
let mut description = String::from(status.description.unwrap_or(""));
description.push_str("\n\n");
arr.push(list(&[bold(&code)], &[description]));
}
page.section("exit status", &arr)
}

/// Create a custom section.
Expand Down
1 change: 1 addition & 0 deletions src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub use arg::Arg;
pub use author::Author;
pub use environment::Env;
pub use example::Example;
pub use exit_status::ExitStatus;
pub use flag::Flag;
pub use man::Manual;
pub use option::Opt;
Expand Down