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

Unable to create Formatter #46591

Closed
71 opened this issue Dec 8, 2017 · 6 comments
Closed

Unable to create Formatter #46591

71 opened this issue Dec 8, 2017 · 6 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@71
Copy link
Contributor

71 commented Dec 8, 2017

Issue

There is currently no (obvious) way to create a Formatter.

Example scenario

In my case, this is a problem because I'd like to display an element that requires informations from external data; I'd thus like to do something like this:

pub trait ContextDependantDisplay {
    fn display(&self, f: &mut Formatter, data: &Data) -> fmt::Result;

    fn to_string(&self, data: &Data) -> String {
        let mut formatter = Formatter::new();
        self.display(&mut f, data).expect("...");
        format!("{}", formatter)
    }
}

However, there is currently no way to create a Formatter, so I had to use a little hack instead:

fn to_string(&self, data: &Data) -> String {
    let fmt = {
        struct ManualDisplay<'a>(&'a ContextDependantDisplay, &'a Data);

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

        ManualDisplay(self, data)
    };

    format!("{}", fmt)
}

I also noticed there is an existing issue about it, which requests the following thing:

Formatter should show where it's created, and talk about the details more.

Meta

rustc 1.24.0-nightly (5a2465e2b 2017-12-06)
binary: rustc
commit-hash: 5a2465e2b44ecdd3b5d835c0abe29e9a4c9dcfe4
commit-date: 2017-12-06
host: x86_64-unknown-linux-gnu
release: 1.24.0-nightly
LLVM version: 4.0
@bluss
Copy link
Member

bluss commented Dec 9, 2017

I don't think the solution is necessarily to create a formatter, but other ways of making the formatter available. In this case you are using format!() so its formatter can be made available, and then the formatted output is also placed directly into the resulting String, which saves copying. Like your workaround shows this can be achieved with a helper type, and we can make that a bit more general.

For example a more general helper like this can be used, it's a helper function and type called Fmt.

format!("{}", Fmt(|f| self.display(f, data)));

@pietroalbini pietroalbini added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Jan 23, 2018
@tailhook
Copy link

I also would like to be able to create a formatter. Because I want to receive format string from user. I.e. at runtime receive a format string from +05, then construct formatter for that and format the value. Currently, to achieve that I must reimplement all the things: microformat parser (which is okay), Formatter itself and Display trait for all needed types. Which is too much.

Are there any obstacles for adding a constructor?

@MightyPork
Copy link

I just hit the same obstacle. I have a struct that can be rendered to string in different ways, and fmt.alternate() and friends just aren't sufficient to express this configuration. Having access to Formatter (or some more generic way to pass options in the {} formatting pattern) would let me avoid constructing throwaway strings

@kgv
Copy link

kgv commented Apr 1, 2020

format is utility crate to make it easier to work with the Formatter.
It defines format wrappers (Debug, Display, Binary, ...) which implements respectively traits. For example LowerHex impl fmt::LowerHex, fmt::Display and fmt::Debug traits. Also it defines lazy_format helper macro.

lazy_format!(|f| self.display(f, data)).to_string();

@NeoGalaxy
Copy link

NeoGalaxy commented Mar 5, 2023

What is the philosophy behind hiding ways to build a formatter? Why do we need to use a utility crate or hacky ways when the standard library can for instance build a formatter from a buffer?

If we have a good reason, then yeah, let's maintain a utility crate. If we don't, then maybe we should consider exposing ways to build a formatter?

@dtolnay
Copy link
Member

dtolnay commented Oct 16, 2023

Closing now that there is a libs-team ACP for this: rust-lang/libs-team#280.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants