Skip to content

Commit

Permalink
feat: reinterpret precision field for strings
Browse files Browse the repository at this point in the history
This commit changes the behavior of formatting string arguments
with both width and precision fields set.

Documentation says that the `width` field is the "minimum width"
that the format should take up. If the value's string does not
fill up this many characters, then the padding specified by
fill/alignment will be used to take up the required space.

This is true for all formatted types except string, which is truncated
down to `precision` number of chars and then all of `fill`, `align` and
`width` fields are completely ignored.

For example: `format!("{:/^10.8}", "1234567890);` emits "12345678".
In the contrast Python version works as the expected:
```python
>>> '{:/^10.8}'.format('1234567890')
'/12345678/'
```

This commit gives back the `Python` behavior by changing the `precision`
field meaning to the truncation and nothing more. The result string *will*
be prepended/appended up to the `width` field with the proper `fill` char.

However, this is the breaking change.

Also updated `std::fmt` docs about string precision.

Signed-off-by: Evgeny Safronov <division494@gmail.com>
  • Loading branch information
3Hren committed Jul 5, 2016
1 parent ea0dc92 commit ede39ae
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 10 deletions.
6 changes: 4 additions & 2 deletions src/libcollections/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,8 @@
//! ## Precision
//!
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
//! longer than this width, then it is truncated down to this many characters and only those are
//! emitted.
//! longer than this width, then it is truncated down to this many characters and that truncated
//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
//!
//! For integral types, this is ignored.
//!
Expand Down Expand Up @@ -469,13 +469,15 @@
//! ```
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
//! ```
//!
//! print two significantly different things:
//!
//! ```text
//! Hello, `1234.560` has 3 fractional digits
//! Hello, `123` has 3 characters
//! Hello, ` 123` has 3 right-aligned characters
//! ```
//!
//! # Escaping
Expand Down
18 changes: 11 additions & 7 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,15 +983,19 @@ impl<'a> Formatter<'a> {
return self.buf.write_str(s);
}
// The `precision` field can be interpreted as a `max-width` for the
// string being formatted
if let Some(max) = self.precision {
// If there's a maximum width and our string is longer than
// that, then we must always have truncation. This is the only
// case where the maximum length will matter.
// string being formatted.
let s = if let Some(max) = self.precision {
// If our string is longer that the precision, then we must have
// truncation. However other flags like `fill`, `width` and `align`
// must act as always.
if let Some((i, _)) = s.char_indices().skip(max).next() {
return self.buf.write_str(&s[..i])
&s[..i]
} else {
&s
}
}
} else {
&s
};
// The `width` field is more of a `min-width` parameter at this point.
match self.width {
// If we're under the maximum length, and there's no minimum length
Expand Down
3 changes: 2 additions & 1 deletion src/test/run-pass/ifmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ pub fn main() {
t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), " aaaa");
t!(format!("{:2.4}", "aaaaa"), "aaaa");
t!(format!("{:2.4}", "aaaa"), "aaaa");
t!(format!("{:2.4}", "aaa"), "aaa");
Expand All @@ -140,6 +140,7 @@ pub fn main() {
t!(format!("{:a$}", "a", a=4), "a ");
t!(format!("{:-#}", "a"), "a");
t!(format!("{:+#}", "a"), "a");
t!(format!("{:/^10.8}", "1234567890"), "/12345678/");

// Some float stuff
t!(format!("{:}", 1.0f32), "1");
Expand Down

0 comments on commit ede39ae

Please sign in to comment.