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
This commit is contained in:
wickerwaka 2014-08-30 11:27:02 -07:00
parent 6d8b5c9f7d
commit 2bc4a5e92a
6 changed files with 33 additions and 9 deletions

View File

@ -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(())
}

View File

@ -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,
}

View File

@ -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('+') {

View File

@ -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

View File

@ -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"))
}

View File

@ -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");