//! calculation, SCAN will write "infinity" to the size and let PRINT consume
//! it.
//!
-//! In this implementation (following the paper, again) the SCAN process is
-//! the method called `Printer::pretty_print`, and the 'PRINT' process is the method
-//! called `Printer::print`.
+//! In this implementation (following the paper, again) the SCAN process is the
+//! methods called `Printer::pretty_print_*`, and the 'PRINT' process is the
+//! method called `Printer::print`.
use std::collections::VecDeque;
use std::fmt;
self.buf[self.right].token = t;
}
- pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
- debug!("pp Vec<{},{}>", self.left, self.right);
- match token {
- Token::Eof => {
- if !self.scan_stack.is_empty() {
- self.check_stack(0);
- self.advance_left()?;
- }
- self.indent(0);
- Ok(())
- }
- Token::Begin(b) => {
- if self.scan_stack.is_empty() {
- self.left_total = 1;
- self.right_total = 1;
- self.left = 0;
- self.right = 0;
- } else {
- self.advance_right();
- }
- debug!("pp Begin({})/buffer Vec<{},{}>",
- b.offset, self.left, self.right);
- self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
- let right = self.right;
- self.scan_push(right);
- Ok(())
- }
- Token::End => {
- if self.scan_stack.is_empty() {
- debug!("pp End/print Vec<{},{}>", self.left, self.right);
- self.print(token, 0)
- } else {
- debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
- self.advance_right();
- self.buf[self.right] = BufEntry { token: token, size: -1 };
- let right = self.right;
- self.scan_push(right);
- Ok(())
- }
- }
- Token::Break(b) => {
- if self.scan_stack.is_empty() {
- self.left_total = 1;
- self.right_total = 1;
- self.left = 0;
- self.right = 0;
- } else {
- self.advance_right();
- }
- debug!("pp Break({})/buffer Vec<{},{}>",
- b.offset, self.left, self.right);
- self.check_stack(0);
- let right = self.right;
- self.scan_push(right);
- self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
- self.right_total += b.blank_space;
- Ok(())
- }
- Token::String(s, len) => {
- if self.scan_stack.is_empty() {
- debug!("pp String('{}')/print Vec<{},{}>",
- s, self.left, self.right);
- self.print(Token::String(s, len), len)
- } else {
- debug!("pp String('{}')/buffer Vec<{},{}>",
- s, self.left, self.right);
- self.advance_right();
- self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
- self.right_total += len;
- self.check_stream()
- }
- }
+ fn pretty_print_eof(&mut self) -> io::Result<()> {
+ if !self.scan_stack.is_empty() {
+ self.check_stack(0);
+ self.advance_left()?;
+ }
+ self.indent(0);
+ Ok(())
+ }
+
+ fn pretty_print_begin(&mut self, b: BeginToken) -> io::Result<()> {
+ if self.scan_stack.is_empty() {
+ self.left_total = 1;
+ self.right_total = 1;
+ self.left = 0;
+ self.right = 0;
+ } else {
+ self.advance_right();
+ }
+ debug!("pp Begin({})/buffer Vec<{},{}>",
+ b.offset, self.left, self.right);
+ self.buf[self.right] = BufEntry { token: Token::Begin(b), size: -self.right_total };
+ let right = self.right;
+ self.scan_push(right);
+ Ok(())
+ }
+
+ fn pretty_print_end(&mut self) -> io::Result<()> {
+ if self.scan_stack.is_empty() {
+ debug!("pp End/print Vec<{},{}>", self.left, self.right);
+ self.print_end()
+ } else {
+ debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
+ self.advance_right();
+ self.buf[self.right] = BufEntry { token: Token::End, size: -1 };
+ let right = self.right;
+ self.scan_push(right);
+ Ok(())
+ }
+ }
+
+ fn pretty_print_break(&mut self, b: BreakToken) -> io::Result<()> {
+ if self.scan_stack.is_empty() {
+ self.left_total = 1;
+ self.right_total = 1;
+ self.left = 0;
+ self.right = 0;
+ } else {
+ self.advance_right();
+ }
+ debug!("pp Break({})/buffer Vec<{},{}>",
+ b.offset, self.left, self.right);
+ self.check_stack(0);
+ let right = self.right;
+ self.scan_push(right);
+ self.buf[self.right] = BufEntry { token: Token::Break(b), size: -self.right_total };
+ self.right_total += b.blank_space;
+ Ok(())
+ }
+
+ fn pretty_print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> {
+ if self.scan_stack.is_empty() {
+ debug!("pp String('{}')/print Vec<{},{}>",
+ s, self.left, self.right);
+ self.print_string(s, len)
+ } else {
+ debug!("pp String('{}')/buffer Vec<{},{}>",
+ s, self.left, self.right);
+ self.advance_right();
+ self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
+ self.right_total += len;
+ self.check_stream()
}
}
}
}
- pub fn print_str(&mut self, s: &str) -> io::Result<()> {
+ pub fn print_begin(&mut self, b: BeginToken, l: isize) -> io::Result<()> {
+ if l > self.space {
+ let col = self.margin - self.space + b.offset;
+ debug!("print Begin -> push broken block at col {}", col);
+ self.print_stack.push(PrintStackElem {
+ offset: col,
+ pbreak: PrintStackBreak::Broken(b.breaks)
+ });
+ } else {
+ debug!("print Begin -> push fitting block");
+ self.print_stack.push(PrintStackElem {
+ offset: 0,
+ pbreak: PrintStackBreak::Fits
+ });
+ }
+ Ok(())
+ }
+
+ pub fn print_end(&mut self) -> io::Result<()> {
+ debug!("print End -> pop End");
+ let print_stack = &mut self.print_stack;
+ assert!(!print_stack.is_empty());
+ print_stack.pop().unwrap();
+ Ok(())
+ }
+
+ pub fn print_break(&mut self, b: BreakToken, l: isize) -> io::Result<()> {
+ let top = self.get_top();
+ match top.pbreak {
+ PrintStackBreak::Fits => {
+ debug!("print Break({}) in fitting block", b.blank_space);
+ self.space -= b.blank_space;
+ self.indent(b.blank_space);
+ Ok(())
+ }
+ PrintStackBreak::Broken(Breaks::Consistent) => {
+ debug!("print Break({}+{}) in consistent block",
+ top.offset, b.offset);
+ let ret = self.print_newline(top.offset + b.offset);
+ self.space = self.margin - (top.offset + b.offset);
+ ret
+ }
+ PrintStackBreak::Broken(Breaks::Inconsistent) => {
+ if l > self.space {
+ debug!("print Break({}+{}) w/ newline in inconsistent",
+ top.offset, b.offset);
+ let ret = self.print_newline(top.offset + b.offset);
+ self.space = self.margin - (top.offset + b.offset);
+ ret
+ } else {
+ debug!("print Break({}) w/o newline in inconsistent",
+ b.blank_space);
+ self.indent(b.blank_space);
+ self.space -= b.blank_space;
+ Ok(())
+ }
+ }
+ }
+ }
+
+ pub fn print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> {
+ debug!("print String({})", s);
+ // assert!(len <= space);
+ self.space -= len;
while self.pending_indentation > 0 {
write!(self.out, " ")?;
self.pending_indentation -= 1;
self.right,
6));
match token {
- Token::Begin(b) => {
- if l > self.space {
- let col = self.margin - self.space + b.offset;
- debug!("print Begin -> push broken block at col {}", col);
- self.print_stack.push(PrintStackElem {
- offset: col,
- pbreak: PrintStackBreak::Broken(b.breaks)
- });
- } else {
- debug!("print Begin -> push fitting block");
- self.print_stack.push(PrintStackElem {
- offset: 0,
- pbreak: PrintStackBreak::Fits
- });
- }
- Ok(())
- }
- Token::End => {
- debug!("print End -> pop End");
- let print_stack = &mut self.print_stack;
- assert!(!print_stack.is_empty());
- print_stack.pop().unwrap();
- Ok(())
- }
- Token::Break(b) => {
- let top = self.get_top();
- match top.pbreak {
- PrintStackBreak::Fits => {
- debug!("print Break({}) in fitting block", b.blank_space);
- self.space -= b.blank_space;
- self.indent(b.blank_space);
- Ok(())
- }
- PrintStackBreak::Broken(Breaks::Consistent) => {
- debug!("print Break({}+{}) in consistent block",
- top.offset, b.offset);
- let ret = self.print_newline(top.offset + b.offset);
- self.space = self.margin - (top.offset + b.offset);
- ret
- }
- PrintStackBreak::Broken(Breaks::Inconsistent) => {
- if l > self.space {
- debug!("print Break({}+{}) w/ newline in inconsistent",
- top.offset, b.offset);
- let ret = self.print_newline(top.offset + b.offset);
- self.space = self.margin - (top.offset + b.offset);
- ret
- } else {
- debug!("print Break({}) w/o newline in inconsistent",
- b.blank_space);
- self.indent(b.blank_space);
- self.space -= b.blank_space;
- Ok(())
- }
- }
- }
- }
- Token::String(ref s, len) => {
- debug!("print String({})", s);
- assert_eq!(l, len);
- // assert!(l <= space);
- self.space -= len;
- self.print_str(s)
- }
- Token::Eof => {
- // Eof should never get here.
- panic!();
+ Token::Begin(b) => self.print_begin(b, l),
+ Token::End => self.print_end(),
+ Token::Break(b) => self.print_break(b, l),
+ Token::String(s, len) => {
+ assert_eq!(len, l);
+ self.print_string(s, len)
}
+ Token::Eof => panic!(), // Eof should never get here.
}
}
/// "raw box"
pub fn rbox(&mut self, indent: usize, b: Breaks) -> io::Result<()> {
- self.pretty_print(Token::Begin(BeginToken {
+ self.pretty_print_begin(BeginToken {
offset: indent as isize,
breaks: b
- }))
+ })
}
/// Inconsistent breaking box
}
pub fn break_offset(&mut self, n: usize, off: isize) -> io::Result<()> {
- self.pretty_print(Token::Break(BreakToken {
+ self.pretty_print_break(BreakToken {
offset: off,
blank_space: n as isize
- }))
+ })
}
pub fn end(&mut self) -> io::Result<()> {
- self.pretty_print(Token::End)
+ self.pretty_print_end()
}
pub fn eof(&mut self) -> io::Result<()> {
- self.pretty_print(Token::Eof)
+ self.pretty_print_eof()
}
pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) -> io::Result<()> {
let s = wrd.into();
let len = s.len() as isize;
- self.pretty_print(Token::String(s, len))
+ self.pretty_print_string(s, len)
}
fn spaces(&mut self, n: usize) -> io::Result<()> {