-
Notifications
You must be signed in to change notification settings - Fork 20
[ACP] Provide an interface for creating and modifying instances of fmt::Formatter #280
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
Comments
Relevant previous libs team discussion: rust-lang/rfcs#3394 (comment) |
Thanks, I had a look through all open and accepted RFCs but didn't look through closed ones. Added the link to the ACP. |
The main takeaway from that previous discussion is that we should have an interface for creating a fmt::Formatter with custom options, not for modifying a fmt::Formatter to change formatting options. Allowing a change for formatting options through So, a possible solution could be having a |
Thanks! After thinking a bit about this, I agree that allowing to modify I'm gonna close this ACP now and open another one with with a new proposal in a few days (probably at the weekend). Thanks again! |
Proposal
Problem statement
Creating a custom
Formatter
at runtime as well as modifying an existingFormatter
is currently not supported, one can only use theFormatter
s passed in by the formatting macros. Being able to create and modify them could be useful for multiple use cases:Motivating examples or use cases
fmt_internals
feature to build a customstd::fmt::Arguments
which has theFormatter
baked in (or rather the mostly equivalentfmt::rt::Placeholder
struct), see here. In consequence, this crate requires nightly Rust. (Note that the interface isn't the current one as runtime-fmt hasn't been updated since 2019)generate_code!
, it generates a function containing aformat_args!
call for every combination of alignment, signedness, default/alternative representation, zero/space padding, width (via variable), precision (via variable) and formatting trait for a total of 1024format_args!
invocations at the time of writing. Fill characters are not supported, as those cannot be passed via a variable to theformat_args!
call but must be part of the format specifier. (If you are interested to see the result of this approach, runcargo expand
in the crate root and search for a huge function namedformat_value
)Solution sketch
fn new(write: &'a mut (dyn Write + 'a)) -> Formatter<'a>
toFormatter
that constructs a new instance ofFormatter
that is equivalent to the{}
formatting specifier (no flags, filled with spaces, no alignment, no width, no precision).set_sign_plus
/set_sign_minus
/set_alternate
/set_sign_aware_zero_pad
/set_fill
/set_align
/set_width
/set_precision
toFormatter
that set the field to the indicated value.fn clone(&'a mut self) -> Self
toFormatter
that clones the instance. Note that this is not aimpl
of theClone
trait as this method takes a mutable borrow ofself
(instead of an immutable one). The mutable borrow is held for the lifetime of the clone. This is necessary because the cloned instance holds the same mutable reference to the outputWrite
instance as the instance it was cloned from.Alternatives
Another idea I had was to use the builder pattern to build new
Formatter
s. The drawback I see with the builder pattern is that changing a single parameter, as needed in use case 1 above, wouldn't be possible. The user would instead need to create a new builder from the existingFormatter
:This is quite verbose compared to the proposed solution:
On the other hand, the prposed solution adds 10 functions to
Formatter
that most users do not care about and that make the documentation harder to navigate. I am still a bit on the fence about which way to go here – feedback is appeciated.Also, this proposal passes the output stream as a dyn Trait to the
new
function. If in the future,Formatter
gets refactored to be generic struct with the output struct used as a generic type parameter,fn new
will not match this new interface. However,Formatter
in this fashion is possible anyway – this would change the interface and therefore would be a breaking change.Links and related work
Relevant previous libs team discussion: rust-lang/rfcs#3394 (comment)
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
Second, if there's a concrete solution:
The text was updated successfully, but these errors were encountered: