Skip to content

Commit 4a1775d

Browse files
authoredJul 21, 2016
Auto merge of #34544 - 3Hren:issue/xx/reinterpret-format-precision-for-strings, r=alexcrichton
feat: reinterpret `precision` field for strings 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, I admit.__ Feel free to close it, but otherwise it should be mentioned in the `std::fmt` documentation somewhere near of `fill/align/width` fields description.
2 parents 7588653 + ede39ae commit 4a1775d

File tree

3 files changed

+17
-10
lines changed

3 files changed

+17
-10
lines changed
 

‎src/libcollections/fmt.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,8 @@
409409
//! ## Precision
410410
//!
411411
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
412-
//! longer than this width, then it is truncated down to this many characters and only those are
413-
//! emitted.
412+
//! longer than this width, then it is truncated down to this many characters and that truncated
413+
//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
414414
//!
415415
//! For integral types, this is ignored.
416416
//!
@@ -470,13 +470,15 @@
470470
//! ```
471471
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
472472
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
473+
//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
473474
//! ```
474475
//!
475476
//! print two significantly different things:
476477
//!
477478
//! ```text
478479
//! Hello, `1234.560` has 3 fractional digits
479480
//! Hello, `123` has 3 characters
481+
//! Hello, ` 123` has 3 right-aligned characters
480482
//! ```
481483
//!
482484
//! # Escaping

‎src/libcore/fmt/mod.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -980,15 +980,19 @@ impl<'a> Formatter<'a> {
980980
return self.buf.write_str(s);
981981
}
982982
// The `precision` field can be interpreted as a `max-width` for the
983-
// string being formatted
984-
if let Some(max) = self.precision {
985-
// If there's a maximum width and our string is longer than
986-
// that, then we must always have truncation. This is the only
987-
// case where the maximum length will matter.
983+
// string being formatted.
984+
let s = if let Some(max) = self.precision {
985+
// If our string is longer that the precision, then we must have
986+
// truncation. However other flags like `fill`, `width` and `align`
987+
// must act as always.
988988
if let Some((i, _)) = s.char_indices().skip(max).next() {
989-
return self.buf.write_str(&s[..i])
989+
&s[..i]
990+
} else {
991+
&s
990992
}
991-
}
993+
} else {
994+
&s
995+
};
992996
// The `width` field is more of a `min-width` parameter at this point.
993997
match self.width {
994998
// If we're under the maximum length, and there's no minimum length

‎src/test/run-pass/ifmt.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub fn main() {
125125
t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
126126
t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
127127
t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
128-
t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
128+
t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), " aaaa");
129129
t!(format!("{:2.4}", "aaaaa"), "aaaa");
130130
t!(format!("{:2.4}", "aaaa"), "aaaa");
131131
t!(format!("{:2.4}", "aaa"), "aaa");
@@ -140,6 +140,7 @@ pub fn main() {
140140
t!(format!("{:a$}", "a", a=4), "a ");
141141
t!(format!("{:-#}", "a"), "a");
142142
t!(format!("{:+#}", "a"), "a");
143+
t!(format!("{:/^10.8}", "1234567890"), "/12345678/");
143144

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

0 commit comments

Comments
 (0)