Comments (5)
Should CLIs always document exit codes?
(including some that I trust to be good, including git, bash, zsh, and rg. Thus, I think that we should make the exit status section optional.
Hmm, I wonder about that. In the case of rg
(a rust tool) it will definitely have possible exit codes of 0, 1 and 101 even if they're not documented. I'm leaning more towards it being something that ripgrep's docs are missing, than something people might not want to include. But maybe that's me?
API
With the rest of the APIs every item is added individually. That would more or less translate to this:
let page = Manual::new("basic")
.exit_status(3, "Invalid config.")
.exit_status(5, "Could not read file.")
.render();
Optional Defaults?
Circling back to the question of defaults. I think we're on the same page that we want to have a convenient way to include the defaults, but there's a question if they should be enabled by default. I'm thinking there's two options:
- we enable the default status codes, and allow people to opt-out.
- we disable the default status codes, and allow people to opt-in.
This would roughly translate to two possible APIs:
opt-out of defaults
defaults enabled
let page = Manual::new("basic")
.exit_status(3, "Invalid config.")
.exit_status(5, "Could not read file.")
.render();
defaults disabled
let page = Manual::new("basic")
.no_default_exit_status()
.exit_status(0, "Successful program execution.")
.exit_status(1, "Unsuccessful program execution.")
.exit_status(3, "Invalid config.")
.exit_status(5, "Could not read file.")
.exit_status(101, "Program panicked.")
.render();
opt-in to defaults
defaults enabled
let page = Manual::new("basic")
.default_exit_status()
.exit_status(3, "Invalid config.")
.exit_status(5, "Could not read file.")
.render();
defaults disabled
let page = Manual::new("basic")
.exit_status(0, "Successful program execution.")
.exit_status(1, "Unsuccessful program execution.")
.exit_status(3, "Invalid config.")
.exit_status(5, "Could not read file.")
.exit_status(101, "Program panicked.")
.render();
I'm not sure what the best option here is. I feel there's arguments for both; I'd be curious to hear which people prefer.
from man.
Hmm, interesting thoughts.
One point comes to mind: with most of our methods (.arg
, .author
, .custom
, .env
, .flag
, and .option
), we don't take arguments directly—instead, we take a corresponding struct. If we wanted to follow that here, we could have:
opt-out of defaults
let page = Manual::new("basic")
.exit_status(ExitStatus::no_defaults())
.exit_status(
ExitStatus::new(0)
.description("Successful program execution.")
)
.exit_status(
ExitStatus::new(1)
.description("Unsuccessful program execution.")
)
.exit_status(
ExitStatus::new(3)
.description("Invalid config.")
)
.exit_status(
ExitStatus::new(5)
.description("Could not read file")
)
.exit_status(
ExitStatus::new(101).
description("Program panicked.")
)
.render();
or
opt-into defaults
let page = Manual::new("basic")
.exit_status(ExitStatus::default())
.exit_status(
ExitStatus::new(1)
.description("Unsuccessful program execution.")
)
.exit_status(
ExitStatus::new(3)
.description("Invalid config.")
)
.exit_status(
ExitStatus::new(5)
.description("Could not read file")
)
.render();
Admittedly, this version of the API is slightly more verbose—but I think I'd prefer it a bit based on the consistency with the rest of the API. Plus, it seems like it makes the default
option a little clearer than having an explicit default
or no_default
option.
One related point: In the first API I proposed, I was suggesting that the/a default could preserve the current behavior (giving 0, 1, and 101 exit codes). The API you proposed, on the other hand, had only 0 and 101.
If we could have all three as the default, that seems to argue a bit in favor of the opt-in: the most common use-case would just be
let page = Manual::new("basic")
.exit_status(ExitStatus::default())
.render();
Of course, the downside of providing more in the default is that more people would need to opt out.
from man.
with most of our methods (...), we don't take arguments directly—instead, we take a corresponding struct.
@codesections originally those APIs didn't take structs either. But because every argument ended up being on Option<>
it felt better to use builders. I think it's worth considering if the status code's description should be optional. It probably should tho?
If we could have all three as the default, that seems to argue a bit in favor of the opt-in: the most common use-case would just be.
I think that example looks pretty reasonable actually -- I like it a lot!
from man.
We discussed the API proposed here in #30 and I noticed that I don't fully agree with it. The main issue for me is that .exit_status
does two things. See #30 (comment) for more context.
Here's the API I'd try to offer, with my expectations. This is very similar to what @yoshuawuyts proposed as "opt-in to defaults" above.
Empty
let page = Manual::new("basic").render();
This does not output a list of error codes.
Just default errors
let page = Manual::new("basic")
.use_default_exit_statuses()
.render();
This renders the three default error codes (with their default description).
The basic case
let page = Manual::new("basic")
.exit_status(
ExitStatus::new(5)
.description("Could not read file")
)
.render();
This renders an exit code section with just one error code listed, 5.
Defaults and more
let page = Manual::new("basic")
.use_default_exit_statuses()
.exit_status(
ExitStatus::new(5)
.description("Could not read file")
)
.render();
This renders the three default error codes, plus the exit code 5.
Overwrite an exit code
(optional to implement but would make sense to me to support)
let page = Manual::new("basic")
.use_default_exit_statuses()
.exit_status(
ExitStatus::new(5)
.description("Could not read file")
)
.exit_status(
ExitStatus::new(5)
.description("Foobar")
)
.render();
This renders the three default error codes, plus the exit code 5 which has "Foobar" s description.
from man.
I like this API, and agree that it's similar to one of @yoshuawuyts's suggestions above.
My only concern with this is that it adds two methods to Manual
to deal with exit codes. This doesn't clutter the API much but could do so if we want to have other default behaviors that users can opt in to (or out of).
I was reviewing the clap-rs API to see how they handle it, and it looks like they have a settings
method.
I wonder if we could do the same? If we did that, here's what the API examples from above would look like:
(Another advantage of pulling this out into a setting is that we could make this (or any other default) opt-out if we later want to)
Empty
let page = Manual::new("basic").render();This does not output a list of error codes.
Just default errors
let page = Manual::new("basic") .setting(ManSetting::DefaultExitStatuses) .render();This renders the three default error codes (with their default description).
The basic case
let page = Manual::new("basic") .exit_status( ExitStatus::new(5) .description("Could not read file") ) .render();This renders an exit code section with just one error code listed, 5.
Defaults and more
let page = Manual::new("basic") .setting(ManSetting::DefaultExitStatuses) .exit_status( ExitStatus::new(5) .description("Could not read file") ) .render();This renders the three default error codes, plus the exit code 5.
Overwrite an exit code
(optional to implement but would make sense to me to support)
let page = Manual::new("basic") .setting(ManSetting::DefaultExitStatuses) .exit_status( ExitStatus::new(5) .description("Could not read file") ) .exit_status( ExitStatus::new(5) .description("Foobar") ) .render();This renders the three default error codes, plus the exit code 5 which has "Foobar" s description.
from man.
Related Issues (17)
- Which sections should a man page have? HOT 3
- Have method for file path HOT 3
- Have "source" section
- Add DESCRIPTION section
- API design HOT 2
- The README example does not compile HOT 1
- Support for custom sections? HOT 3
- Add version/date API HOT 1
- Add examples API HOT 1
- Format example in README to show bold HOT 1
- Document full use-case (e.g., `build.rs` script) HOT 5
- Options with no "="
- update to roff 0.2? HOT 1
- Accept more types of positional arguments
- Design: how should we display subcommands? HOT 1
- Move clap v3 -> man glue code to clap_generate HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from man.