print.rs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. use std::collections::BTreeMap;
  2. use itertools::Itertools;
  3. use crate::data::{Root, SourceFile, Span, Spanned};
  4. use super::{LedgerEntry, Transaction};
  5. fn print_transaction(root: &Root, tx: &Transaction, padding: usize) {
  6. println!(
  7. "{}: {}",
  8. tx.datestamp,
  9. tx.title.as_deref().unwrap_or("")
  10. );
  11. if !tx.annotations.is_empty() {
  12. println!(
  13. " {}",
  14. tx.annotations.iter().map(|a| format!("[{a}]")).join(" ")
  15. );
  16. }
  17. let force_show = tx.changes.iter().unique_by(|b| *b.account).count() > 1;
  18. for change in &tx.changes {
  19. let spacer = if change.amount.is_sign_positive() {
  20. " "
  21. } else {
  22. ""
  23. };
  24. let balance = if let Some(bal) = change.balance {
  25. format!(" = {bal}")
  26. } else {
  27. String::new()
  28. };
  29. if Some(change.unit.as_ref()) == root.account_spec(*change.account).unwrap().unit.as_ref()
  30. && !force_show
  31. {
  32. println!(" - {:padding$}: {spacer}{}{balance}", change.account, change.amount,);
  33. } else {
  34. println!(
  35. " - {:padding$}: {spacer}{}{balance} {}",
  36. change.account, change.amount, change.unit,
  37. );
  38. }
  39. }
  40. // empty line afterwards
  41. println!();
  42. }
  43. fn print_comment(c: &Spanned<String>) {
  44. println!("{c}");
  45. }
  46. pub fn print_ledger<'l>(root: &Root, entries: impl Iterator<Item = &'l LedgerEntry>) {
  47. let mut ordering = BTreeMap::<SourceFile, BTreeMap<Span, &LedgerEntry>>::new();
  48. entries.for_each(|e| {
  49. ordering
  50. .entry(e.span().context)
  51. .or_default()
  52. .insert(e.span(), &e);
  53. });
  54. let Some(padding) = root.spec_root.accounts.keys().map(|k| k.len()).max() else {
  55. // no accounts
  56. return;
  57. };
  58. for (filename, entries) in ordering {
  59. println!(
  60. "==== file {} ====",
  61. std::path::Path::new(filename.as_ref()).display()
  62. );
  63. for (_span, le) in entries {
  64. match le {
  65. LedgerEntry::Transaction(tx) => print_transaction(root, tx, padding),
  66. LedgerEntry::Comment(c) => print_comment(c),
  67. }
  68. }
  69. }
  70. }