Skip to content

Allow modifying Formatter members #19207

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

Closed
bluss opened this issue Nov 22, 2014 · 11 comments
Closed

Allow modifying Formatter members #19207

bluss opened this issue Nov 22, 2014 · 11 comments
Labels
C-feature-accepted Category: A feature request that has been accepted pending implementation. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@bluss
Copy link
Member

bluss commented Nov 22, 2014

std::fmt::Formatter's members are now private.

In my usecase, I was formatting an array of elements by passing down the formatter and using it for each element, so for example {:.2} would print each element to two decimals.

In this usage, it was useful to modify the width field of the Formatter so that the array elements were more padded out by default.

@alexcrichton
Copy link
Member

This was specifically left out of std::fmt because by overwriting any members you're silently indicating that you're ignoring the requested preference for formatting options. If you'd like to hard code formatting options, the way you can do so is with a call to write!() and using {:.2} specifically.

@bluss
Copy link
Member Author

bluss commented Nov 23, 2014

No -- my code looks like this, so it is not overwriting.

    if sz > 0 && f.width.is_none() {
        f.width = Some(4)
    }

If I want to override width, but I don't want to override all the other parameters.. precision and formatter type (Default or e or E).

Maybe there could be a way to copy a formatter with different attributes?

Example implementation

Of course the impl could be made smarter, for example adjusting the width so that the elements always line up.

@steveklabnik
Copy link
Member

Triage: no change that I'm aware of, formatter is still private.

@rust-lang/libs, is this a use-case that you intend to support, or is this not a bug?

@sfackler
Copy link
Member

There are now stable accessors for all of the relevant fields except for alignment.

EDIT: Oh, misread, didn't realize this was for modifiers.

@bluss
Copy link
Member Author

bluss commented Jan 1, 2016

The general question is how to allow passing down formatting options for a container to the elements in a convenient way. Preferably while allowing to set defaults, like my use case indicated.

Imagine a simple numerical container, like a mathematical vector. Since the numerics are the main feature, it makes sense we want rich formatting options for how the components of the vector are formatted.

format!("{:4.2}", Vector::new(&[1., 2., 3.])) affects the elements and not the vector itself — I think this is an ok "overloading" of the formatting options, or is there a different way we should design the API? A callback-based solution might be too unergonomic.

The numerical container will want to support {}, {:e}, {:E}, all the same way, preferably by allowing the user to set width and precision while supplying defaults when they are not present. That was what I was going for in ndarray until the width went immutable.

@alexcrichton
Copy link
Member

@steveklabnik I believe this is still a legitimate bug in terms of "this could be implemented but isn't".

My personal opinion is that I'd like to push as hard as we can on read-only members without providing writable variants.

@alexreg
Copy link
Contributor

alexreg commented Feb 14, 2016

Could we have writable variants actually, please? Currently, since FlagV1 is private, I can't even mimic the functionality of impl<T> Pointer for *const T for my own types, which is a shame.

@steveklabnik steveklabnik added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed A-libs labels Mar 24, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-feature-request Category: A feature request, i.e: not implemented / a PR. label Jul 22, 2017
@alexcrichton alexcrichton added C-feature-accepted Category: A feature request that has been accepted pending implementation. and removed C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Aug 1, 2017
@alexcrichton
Copy link
Member

This seems like a fine feature to me to add! PRs would be most welcome to review an implementation here.

@jimblandy
Copy link
Contributor

Here's another example of where this would be useful. In our book, @jorendorff and I show how to implement the std::fmt formatting traits using a complex number type as an example:

#[derive(Copy, Clone, Debug)]
struct Complex { r: f64, i: f64 }

use std::fmt;

impl fmt::Display for Complex {
    fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
        let i_sign = if self.i < 0.0 { '-' } else { '+' };
        write!(dest, "{} {} {}i", self.r, i_sign, f64::abs(self.i))
    }
}

This is okay, but ideally, alignment and padding would apply to the complex number's representation as a whole, while numeric precision would apply to each component individually, such that:

assert_eq!(format!("{:16.2}", Complex { r: 1.5, i: 3.125 }), "    1.50 + 3.13i");

The example could certainly use Formatter::pad with the library as it stands, but it seemed like that raised questions about the individual components that we didn't have good answers for, so we blew it off. Leading zeros are a hairy question, but if I could at least get the precision right, I'd feel okay expanding the example.

@alexreg
Copy link
Contributor

alexreg commented Dec 1, 2017

This seems like a fine feature to me to add! PRs would be most welcome to review an implementation here.

What way do you want to address this though?

  1. Provide setter methods for various members.
  2. Keep Formatter immutable and allow overriding of (all/just unset?) members on copying, using a copy_from method or such.
  3. Some alternative approach?

I'd be happy to have a go at a PR, if you let me know.

@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-accepted Category: A feature request that has been accepted pending implementation. 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

9 participants