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

Add a format_fallback method for printing fallback values in the --help output with a custom formatting function #411

Merged
merged 2 commits into from
Feb 24, 2025

Conversation

antalsz
Copy link
Contributor

@antalsz antalsz commented Feb 24, 2025

Hi, hope you don't mind the unsolicited feature PR! I just started using bpaf for a project (I really appreciate your support for parsing enums), and discovered that I wanted the ability to print out fallback values using a custom formatting function:

use bpaf::*;

use std::{fmt::Display as _, path::PathBuf};

#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
    /// Path to log file
    #[bpaf(
        argument("FILE"),
        fallback(PathBuf::from("logfile.txt")),
        format_fallback(|path, f| path.display().fmt(f)),
    )]
    log_file: PathBuf,
}

You can get the same effect in bpaf today by using mapping into and out of a struct with a custom Display impl, but it's much clunkier; you have to create a separate struct, provide it the relevant display instance, and map into and out of it, plus you have to manually wrap the fallback value.

use bpaf::*;

use std::path::PathBuf;

#[derive(Clone)]
struct DisplayPathBuf(PathBuf);

impl std::fmt::Display for DisplayPathBuf {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.0.display().fmt(f)
    }
}

#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
    /// Path to log file
    #[bpaf(
        argument("FILE"),
        map(DisplayPathBuf),
        fallback(DisplayPathBuf(PathBuf::from("logfile.txt"))),
        display_fallback,
        map(|dpb| dpb.0),
    )]
    log_file: PathBuf,
}

Also, because the type of PathBuf::display is (&self) -> Display<'_>, we can't simply map into that type, as it doesn't live long enough, and we can't specify it in some sort of "display PathBufs as Display" because we can't provide a lifetime.

I also added some documentation for the docs2 crate since I had trouble finding out how to regenerate the docs until I found an old comment of yours.

I think this PR should have everything needed for the change:

  • Updates to bpaf to support the new format_fallback methods on both ParseFallback and ParseFallbackWith;
  • Updates to bpaf_derive to support using format_fallback in attributes;
  • A test of the behavior of format_fallback;
  • New documentation for format_fallback; and
  • Updates to old documentation to mention format_fallback alongside display_fallback and debug_fallback.

The only exception is that I didn't include any changelog or version number updates because I wasn't sure how you handled those, but I'm happy to add them too!

This lets you output fallback values (in `[default: …]`, as usual) with a custom
formatting function; the motivating example, which is presented in the docs, is
displaying `PathBuf`s, but it's more generally useful.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the only file with code changes; everything else is documentation or tests

@pacak
Copy link
Owner

pacak commented Feb 24, 2025

This looks great! A very elegant solution ❤️

@pacak pacak merged commit 40cce9c into pacak:master Feb 24, 2025
3 checks passed
@pacak
Copy link
Owner

pacak commented Feb 25, 2025

I'll try to release a new version in a day or two.

@antalsz
Copy link
Contributor Author

antalsz commented Feb 25, 2025

Thank you!

@pacak
Copy link
Owner

pacak commented Mar 1, 2025

0.9.17 should be out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants