Can you give an example? Do you mean you don’t like the “Error:” prefix before the error’s message is displayed? That part is hardcoded in std. Once the Termination trait is stable, you can return a custom type with whatever output you like.
I am using nightly so I can use unstable stuff. Do you have details on how Termination trait can be used for this? I thought it’s only to be used to control the exit code.
I am ok with the Error: prefix. I want to be able to control how the error context and other additional info (specific to failure crate) is printed. Also, I would like to add the backtrace if the user is using a cli flag.
For example, by default the error looks like this:
Error: KubeclientError("Kubernetes API error: pods \"serve-hostname-86bc9d96dc-tztt\" not found")
The foo bar thing is the additional context() passed to the error
It has to return the exit code, but you can do whatever you want inside Termination::report. You can see how Result<(), E> does it. But you said you’re ok with the “Error:” prefix, so I don’t think you really need Termination anyway.
You could conceivably add a newtype over failure::Context, although there may be a better way. But something like:
Yes, I’m questioning the question here OP knows the solution, but IMHO incorrectly rejects it.
The desire to format that output was the first thing that came up in the RFC. It feels like something that should be done, so “don’t bother” is a very counter-intuitive answer.
But it goes like this:
You want to pretty-print output from main
It’s almost, but not quite what you want. Maybe it prints with “error:” prefix, but you wanted “Error!”, or you use failure and want to list causes. Or you wanted to return exit status 7 when errors happen on Tuesday.
so you want to replace the default pretty print logic
And when you reach the point 3 you end up defining newtypes, implementing traits and piling all that “elegant” complexity to inject the same code you’d put in if let Err. The wrapper function doesn’t give the feeling of using the right language feature, but it is the right way to do it.
In general, I’m in agreement with you. It’s hard to suggest things in a vacuum, when one doesn’t have enough context. For instance, you might have a type that’s already used for printing stuff somehow - you may want to reuse it as the return value in main() (once Termination is stable), rather than refactoring rendering into a standalone function and/or wrapping into a Result.
I think it’s worthwhile to demonstrate various techniques, and then let others judge which is best for their case. Particularly when there’s little context and a person is asking precisely for alternatives. The alternative may be worse in a particular case but better in another, but one can only judge that if they know the alternative to begin with .
I’ve written a small crate that takes exactly this approach and provides a newtype wrapper around failure::Error - exitfailure. Lets me just use a main() -> Result<(), ExitFailure> and have the pretty printing taken care of.
It’s nothing fancy but it saves me writing all that boilerplate for each project.