use std::io;
use crate::resolution::{Entry, HIR};
pub fn write(hir: &HIR, writer: &mut dyn io::Write) -> io::Result<()> {
let mut first = true;
for price in &hir.prices {
if !first {
writeln!(writer)?;
}
first = false;
let price_str = format!("{}", price.price);
writeln!(writer, "P {} {} {}", price.date, price.commodity, price_str)?;
}
for entry in &hir.entries {
match &entry.data {
Entry::Transaction(txn) => {
if !first {
writeln!(writer)?;
}
first = false;
write_transaction(txn, writer)?;
}
Entry::Assertion(a) => {
if !first {
writeln!(writer)?;
}
first = false;
let strict = if a.strict { "==" } else { "=" };
writeln!(writer, "{} {} {} {}", a.date, strict, a.account, a.amount)?;
}
Entry::Pad(p) => {
if !first {
writeln!(writer)?;
}
first = false;
writeln!(
writer,
"; [beancount] pad {} {} {}",
p.date, p.target_account, p.source_account
)?;
}
}
}
Ok(())
}
fn write_transaction(
txn: &crate::resolution::Transaction,
writer: &mut dyn io::Write,
) -> io::Result<()> {
write!(writer, "{}", txn.date)?;
if let Some(sec) = txn.secondary_date {
write!(writer, "={sec}")?;
}
match txn.state {
crate::ast::TransactionState::Uncleared => {}
crate::ast::TransactionState::Pending => write!(writer, " !")?,
crate::ast::TransactionState::Cleared => write!(writer, " *")?,
}
if let Some(ref code) = txn.code {
write!(writer, " ({code})")?;
}
writeln!(writer, " {}", txn.description)?;
for comment in &txn.comments {
writeln!(writer, " ; {comment}")?;
}
for tag in &txn.tags {
writeln!(writer, " ; :{tag}:")?;
}
for (key, value) in &txn.metadata {
writeln!(writer, " ; {key}: {value}")?;
}
for posting in &txn.postings {
write_posting(posting, writer)?;
}
Ok(())
}
fn write_posting(
posting: &crate::resolution::Posting,
writer: &mut dyn io::Write,
) -> io::Result<()> {
write!(writer, " ")?;
match posting.state {
crate::ast::TransactionState::Uncleared => {}
crate::ast::TransactionState::Pending => write!(writer, "! ")?,
crate::ast::TransactionState::Cleared => write!(writer, "* ")?,
}
match posting.kind {
crate::ast::PostingKind::Real => write!(writer, "{}", posting.account)?,
crate::ast::PostingKind::VirtualUnbalanced => write!(writer, "({})", posting.account)?,
crate::ast::PostingKind::VirtualBalanced => write!(writer, "[{}]", posting.account)?,
}
if let Some(ref amount) = posting.amount {
write!(writer, " {amount}")?;
}
writeln!(writer)?;
for comment in &posting.comments {
writeln!(writer, " ; {comment}")?;
}
for tag in &posting.tags {
writeln!(writer, " ; :{tag}:")?;
}
for (key, value) in &posting.metadata {
writeln!(writer, " ; {key}: {value}")?;
}
Ok(())
}