pub struct CodeBuffer {
buffer: Vec<String>,
indent: i32,
level: i32,
}
impl Default for CodeBuffer {
fn default() -> Self {
let buffer: Vec<String> = Vec::new();
let indent = 4;
let level = 0;
CodeBuffer {
buffer,
indent,
level,
}
}
}
impl ToString for CodeBuffer {
fn to_string(&self) -> String {
self.buffer.join("\n")
}
}
impl CodeBuffer {
pub fn new(indent: i32) -> Self {
let buffer: Vec<String> = Vec::new();
let level = 0;
CodeBuffer {
buffer,
indent,
level,
}
}
pub fn println(&mut self, str: &str) {
let indent_size = self.indent * self.level;
let indent_str = " ".repeat(indent_size as usize);
self.buffer.push(format!("{}{}", indent_str, str));
}
pub fn indent_right(&mut self) {
self.level += 1;
}
pub fn indent_left(&mut self) {
if self.level > 0 {
self.level -= 1;
}
}
pub fn println_right(&mut self, str: &str) {
self.indent_right();
self.println(str);
}
pub fn println_left(&mut self, str: &str) {
self.indent_left();
self.println(str);
}
}
#[cfg(test)]
mod tests {
use crate::code_buffer::CodeBuffer;
#[test]
fn should_write_to_buffer() {
let mut printer = CodeBuffer::new(4);
printer.println("testing");
let actual = printer.to_string();
assert_eq!("testing", actual);
}
#[test]
fn default_should_return_valid_printer() {
let mut printer = CodeBuffer::default();
printer.println("default");
let actual = printer.to_string();
assert_eq!("default", actual);
}
#[test]
fn should_indent_on_indent_right() {
let mut printer = CodeBuffer::new(4);
printer.indent_right();
printer.println("testing");
let actual = printer.to_string();
assert_eq!(" testing", actual);
}
#[test]
fn should_indent_on_indent_left() {
let mut printer = CodeBuffer::new(4);
printer.indent_right();
printer.indent_right();
printer.indent_left();
printer.println("testing");
let actual = printer.to_string();
assert_eq!(" testing", actual);
}
#[test]
fn printer_should_not_unindent_beyond_level_zero() {
let mut printer = CodeBuffer::default();
printer.indent_left();
printer.println("testing");
let actual = printer.to_string();
assert_eq!("testing", actual);
}
#[test]
fn printer_should_handle_indent_then_unindent() {
let mut printer = CodeBuffer::new(4);
let expected = "fn do_something() {\n println!(\"Hello, World!\");\n}";
printer.println("fn do_something() {");
printer.indent_right();
printer.println("println!(\"Hello, World!\");");
printer.indent_left();
printer.println("}");
let actual = printer.to_string();
assert_eq!(expected, actual);
}
#[test]
fn printer_should_maintain_indent_across_multiple_println() {
let mut printer = CodeBuffer::new(4);
let expected = " testing1\n testing2";
printer.indent_right();
printer.indent_right();
printer.println("testing1");
printer.println("testing2");
let actual = printer.to_string();
assert_eq!(expected, actual);
}
#[test]
fn println_left_should_indent_left_then_print() {
let mut printer = CodeBuffer::new(4);
printer.indent_right();
printer.indent_right();
printer.println_left("testing");
let actual = printer.to_string();
assert_eq!(" testing", actual);
}
#[test]
fn println_right_should_indent_right_then_print() {
let mut printer = CodeBuffer::new(4);
printer.println_right("testing");
let actual = printer.to_string();
assert_eq!(" testing", actual);
}
}