1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
use std::fmt::{self, Write};
use crate::body::Body;
use crate::formatter::Formatter;
/// Defines a code block. This is used to define a function body.
#[derive(Debug, Clone)]
pub struct Block {
/// Content before the block.
before: Option<String>,
/// Content after the block.
after: Option<String>,
/// The contents inside the block.
body: Vec<Body>,
}
impl Block {
/// Returns an empty code block.
///
/// # Arguments
///
/// * `before` - The contents to add before the block. This can be an empty "" if you don't want anything before the block.
///
/// # Examples
///
/// ```
/// use rust_codegen::Block;
///
/// let mut block = Block::new("");
/// ```
pub fn new(before: &str) -> Self {
Block {
before: Some(before.to_string()),
after: None,
body: vec![],
}
}
/// Push a line to the code block.
///
/// # Arguments
///
/// * `line` - The line to add to the code block.
///
/// # Examples
///
/// ```
/// use rust_codegen::Block;
///
/// let mut block = Block::new("");
/// block.line("println!(\"Hello, world!\");");
/// ```
pub fn line<T>(&mut self, line: T) -> &mut Self
where
T: ToString,
{
self.body.push(Body::String(line.to_string()));
self
}
/// Push a nested block to this block.
///
/// # Arguments
///
/// * `block` - The block to push to this block.
///
/// # Examples
///
/// ```
/// use rust_codegen::Block;
///
/// let mut block_1 = Block::new("");
/// block_1.line("println!(\"Hello, world!\");");
///
/// let mut block_2 = Block::new("");
/// block_2.line("println!(\"from Rust!!\");");
///
/// block_1.push_block(block_2);
/// ```
pub fn push_block(&mut self, block: Block) -> &mut Self {
self.body.push(Body::Block(block));
self
}
/// Add a snippet after the block.
///
/// # Arguments
///
/// * `after` - The snippet to add after the code block.
///
/// # Examples
///
/// ```
/// use rust_codegen::Block;
///
/// let mut block = Block::new("This is before");
/// block.after("This is after");
/// ```
pub fn after(&mut self, after: &str) -> &mut Self {
self.after = Some(after.to_string());
self
}
/// Formats the block using the given formatter.
///
/// # Arguments
///
/// * `fmt` - The formatter to use.
///
/// # Examples
///
/// ```
/// use rust_codegen::{Block, Formatter};
///
/// let mut dest = String::new();
/// let mut fmt = Formatter::new(&mut dest);
///
/// let mut block = Block::new("This is before");
/// block.fmt(&mut fmt);
/// ```
pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
if let Some(ref before) = self.before {
write!(fmt, "{}", before)?;
}
// Inlined `Formatter::fmt`
if !fmt.is_start_of_line() {
write!(fmt, " ")?;
}
write!(fmt, "{{\n")?;
fmt.indent(|fmt| {
for b in &self.body {
b.fmt(fmt)?;
}
Ok(())
})?;
write!(fmt, "}}")?;
if let Some(ref after) = self.after {
write!(fmt, "{}", after)?;
}
write!(fmt, "\n")?;
Ok(())
}
}