From 2bc4a5e92aef51bd34a5b1a506c5edcee893d6ac Mon Sep 17 00:00:00 2001 From: wickerwaka Date: Sat, 30 Aug 2014 11:27:02 -0700 Subject: [PATCH] Center alignment for fmt Use '^' to specify center alignment in format strings. fmt!( "[{:^5s}]", "Hi" ) -> "[ Hi ]" fmt!( "[{:^5s}]", "H" ) -> "[ H ]" fmt!( "[{:^5d}]", 1i ) -> "[ 1 ]" fmt!( "[{:^5d}]", -1i ) -> "[ -1 ]" fmt!( "[{:^6d}]", 1i ) -> "[ 1 ]" fmt!( "[{:^6d}]", -1i ) -> "[ -1 ]" If the padding is odd then the padding on the right will be one character longer than the padding on the left. Tuples squashed --- src/libcore/fmt/mod.rs | 23 ++++++++++++++++------- src/libcore/fmt/rt.rs | 2 ++ src/libfmt_macros/lib.rs | 6 +++++- src/libstd/fmt.rs | 3 ++- src/libsyntax/ext/format.rs | 3 +++ src/test/run-pass/ifmt.rs | 5 +++++ 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 32663e5eb0f..7c4494358b1 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -461,19 +461,28 @@ impl<'a> Formatter<'a> { use char::Char; let align = match self.align { rt::AlignUnknown => default, - rt::AlignLeft | rt::AlignRight => self.align + _ => self.align }; - if align == rt::AlignLeft { - try!(f(self)); - } + + let (pre_pad, post_pad) = match align { + rt::AlignLeft => (0u, padding), + rt::AlignRight | rt::AlignUnknown => (padding, 0u), + rt::AlignCenter => (padding / 2, (padding + 1) / 2), + }; + let mut fill = [0u8, ..4]; let len = self.fill.encode_utf8(fill).unwrap_or(0); - for _ in range(0, padding) { + + for _ in range(0, pre_pad) { try!(self.buf.write(fill.slice_to(len))); } - if align == rt::AlignRight { - try!(f(self)); + + try!(f(self)); + + for _ in range(0, post_pad) { + try!(self.buf.write(fill.slice_to(len))); } + Ok(()) } diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs index 388084b9ed8..1f5449130ec 100644 --- a/src/libcore/fmt/rt.rs +++ b/src/libcore/fmt/rt.rs @@ -43,6 +43,8 @@ pub enum Alignment { AlignLeft, /// Indication that contents should be right-aligned. AlignRight, + /// Indication that contents should be center-aligned. + AlignCenter, /// No alignment was requested. AlignUnknown, } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 560681765cd..9272369f73c 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -81,6 +81,8 @@ pub enum Alignment { AlignLeft, /// The value will be aligned to the right. AlignRight, + /// The value will be aligned in the center. + AlignCenter, /// The value will take on a default alignment. AlignUnknown, } @@ -279,7 +281,7 @@ impl<'a> Parser<'a> { match self.cur.clone().next() { Some((_, c)) => { match self.cur.clone().skip(1).next() { - Some((_, '>')) | Some((_, '<')) => { + Some((_, '>')) | Some((_, '<')) | Some((_, '^')) => { spec.fill = Some(c); self.cur.next(); } @@ -293,6 +295,8 @@ impl<'a> Parser<'a> { spec.align = AlignLeft; } else if self.consume('>') { spec.align = AlignRight; + } else if self.consume('^') { + spec.align = AlignCenter; } // Sign flags if self.consume('+') { diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index 841567a9120..f69f94c4db6 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -333,7 +333,7 @@ argument := integer | identifier format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] fill := character -align := '<' | '>' +align := '<' | '^' | '>' sign := '+' | '-' width := count precision := count | '*' @@ -357,6 +357,7 @@ parameter. This indicates that if the value being formatted is smaller than are specified by `fill`, and the alignment can be one of two options: * `<` - the argument is left-aligned in `width` columns +* `^` - the argument is center-aligned in `width` columns * `>` - the argument is right-aligned in `width` columns ### Sign/#/0 diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 0994abaadc7..aa2c51c0225 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -430,6 +430,9 @@ impl<'a, 'b> Context<'a, 'b> { parse::AlignRight => { self.ecx.path_global(sp, self.rtpath("AlignRight")) } + parse::AlignCenter => { + self.ecx.path_global(sp, self.rtpath("AlignCenter")) + } parse::AlignUnknown => { self.ecx.path_global(sp, self.rtpath("AlignUnknown")) } diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 2a3bce18eba..d582209a79e 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -90,11 +90,16 @@ pub fn main() { t!(format!("{:4s}", "a"), "a "); t!(format!("{:>4s}", "a"), " a"); t!(format!("{:<4s}", "a"), "a "); + t!(format!("{:^5s}", "a"), " a "); + t!(format!("{:^5s}", "aa"), " aa "); + t!(format!("{:^4s}", "a"), " a "); + t!(format!("{:^4s}", "aa"), " aa "); t!(format!("{:.4s}", "a"), "a"); t!(format!("{:4.4s}", "a"), "a "); t!(format!("{:4.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); t!(format!("{:<4.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); t!(format!("{:>4.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:^4.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); t!(format!("{:>10.4s}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); t!(format!("{:2.4s}", "aaaaa"), "aaaa"); t!(format!("{:2.4s}", "aaaa"), "aaaa");