mod account;
mod balance;
mod balance_tree;
mod book_keeping;
mod commodity;
mod context;
mod error;
mod eval;
mod price_db;
mod process;
pub mod query;
mod tags;
mod transaction;
use std::borrow::Borrow;
pub use account::{Account, AccountAggregate, AccountTree, AccountTreeKey};
pub use balance::Balance;
pub use balance_tree::{BalanceTree, BalanceTreeNode};
pub use commodity::{Commodity, CommodityStore, CommodityTag, OwnedCommodity};
pub use context::ReportContext;
pub use error::ReportError;
pub use eval::{Amount, SingleAmount};
pub use price_db::LoadError;
pub use process::{ProcessOptions, process};
pub use tags::{Tag, TagQuery, TagValue, tags};
pub use transaction::{Posting, Transaction};
use crate::{load, syntax::plain::LedgerStatement};
pub fn accounts<'ctx, L, F>(
ctx: &'_ mut context::ReportContext<'ctx>,
loader: L,
) -> Result<Vec<Account<'ctx>>, ReportError>
where
L: Borrow<load::Loader<F>>,
F: load::FileSystem,
{
loader.borrow().load(|path, pctx, entry| {
match &entry.statement {
LedgerStatement::Account(account) => {
process::process_account(ctx, account).map_err(|berr| {
ReportError::BookKeep(
berr,
error::ErrorContext::new(
loader.borrow().error_style().clone(),
path.to_owned(),
pctx,
),
)
})?
}
LedgerStatement::Txn(txn) => {
for posting in &txn.posts {
ctx.accounts.ensure(&posting.account);
}
}
_ => (),
}
Ok::<(), ReportError>(())
})?;
Ok(ctx.all_accounts())
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use bumpalo::Bump;
use indoc::indoc;
use maplit::hashmap;
use pretty_assertions::assert_eq;
use crate::{load, report};
#[test]
fn accounts_gives_all_accounts() {
let fake = hashmap! {
PathBuf::from("path/to/root.ledger") => indoc! {"
account Expenses:Food
alias Expenses:Bar
account Expenses:Bar
alias Expenses:Baz
2026/01/01 drink
Expenses:Baz 1,000 JPY
Assets:Bank:X
"}.as_bytes().to_vec(),
};
let loader = load::Loader::new(
PathBuf::from("path/to/root.ledger"),
load::FakeFileSystem::from(fake),
);
let arena = Bump::new();
let mut ctx = report::ReportContext::new(&arena);
let got = report::accounts(&mut ctx, &loader).unwrap();
assert_eq!(
vec![
ctx.account("Assets:Bank:X").unwrap(),
ctx.account("Expenses:Food").unwrap()
],
got,
);
}
}