Implement metadata & price directives

korrat
Apr 1, 2023, 10:57 AM
R524JUUE57KNHXLPN52X6DWK6PPQPBG5DXYNSVLGSEI5UMYXWDMQC

Dependencies

  • [2] VM4ZH5WD Handle transaction metadata when pretty printing
  • [3] X6YJF46G Respect directive order when writing trees
  • [4] YBARPI2B Make account templates owned
  • [5] 6MYJDQ3I Handle price directives
  • [6] MG46NYAC enable deserialization of configuration for common utilities
  • [7] 2NYDNXH7 Use OS dependent path separator when constructing paths in tree writer
  • [8] QRIJE4AQ add a simple pretty printer for beancount directives
  • [9] SMBQYFPG Enable access to timestamps for directives
  • [10] SEEWF7KX Implement metadata on transactions
  • [11] ND7GASJ4 track current column position when writing
  • [12] YDK6X6PP add a library of important types for beancount
  • [13] T2S6UAVJ Include builder methods on beancount-types
  • [14] R7S2CWF7 Add type for account segments
  • [15] D6UTHZA4 add a simple writer for saving a set of directives to a tree of files
  • [16] SJ6AFVZL remove const configuration in favor of runtime config
  • [17] 2JBFREZG enable additional warnings
  • [18] ENLUNKU5 Make PrettyPrinterConfig public
  • [*] W3MWSSJ7 Add a templating engine for accounts
  • [*] UESS5YZE migrate dependencies into workspace manifest

Change contents

  • edit in common/beancount-types/src/transaction.rs at line 12
    [6.3497]
    [6.86]
    use crate::Acc;
  • edit in common/beancount-types/src/transaction.rs at line 17
    [6.37]
    [6.37]
    use crate::LinkSet;
  • edit in common/beancount-types/src/transaction.rs at line 19
    [6.61]
    [6.61]
    use crate::MetadataMap;
  • edit in common/beancount-types/src/transaction.rs at line 21
    [6.87][6.87:119]()
    use crate::TransactionMetadata;
  • replacement in common/beancount-types/src/transaction.rs at line 53
    [6.501][6.501:543]()
    self.amount = Default::default();
    [6.501]
    [6.543]
    self.amount = None;
  • replacement in common/beancount-types/src/transaction.rs at line 59
    [6.625][6.625:665]()
    self.cost = Default::default();
    [6.625]
    [6.665]
    self.cost = None;
  • replacement in common/beancount-types/src/transaction.rs at line 65
    [6.747][6.747:787]()
    self.flag = Default::default();
    [6.747]
    [6.787]
    self.flag = None;
  • replacement in common/beancount-types/src/transaction.rs at line 71
    [6.870][6.870:911]()
    self.price = Default::default();
    [6.870]
    [6.911]
    self.price = None;
  • replacement in common/beancount-types/src/transaction.rs at line 159
    [6.1][6.1:40]()
    pub metadata: TransactionMetadata,
    [6.1]
    [6.1311]
    pub links: LinkSet,
    pub meta: MetadataMap,
  • replacement in common/beancount-types/src/transaction.rs at line 169
    [6.1973][6.41:120]()
    let (flag, metadata, payee, narration, postings) = Default::default();
    [6.1973]
    [6.2042]
    let (flag, links, meta, payee, narration, postings) = Default::default();
  • replacement in common/beancount-types/src/transaction.rs at line 176
    [6.2136][6.121:143]()
    metadata,
    [6.2136]
    [6.2136]
    links,
    meta,
  • replacement in common/beancount-types/src/transaction.rs at line 191
    [6.178][6.178:204]()
    pub fn add_key_value(
    [6.178]
    [6.204]
    pub fn add_meta(
  • replacement in common/beancount-types/src/transaction.rs at line 196
    [6.322][6.322:371]()
    self.metadata.add_key_value(key, value);
    [6.322]
    [6.371]
    self.meta.insert(key.into(), value.into());
  • replacement in common/beancount-types/src/transaction.rs at line 202
    [6.474][6.474:512]()
    self.metadata.add_link(link);
    [6.474]
    [6.2313]
    self.links.insert(link.into());
  • replacement in common/beancount-types/src/transaction.rs at line 216
    [6.534][6.534:630]()
    pub fn clear_metadata(&mut self) -> &mut Self {
    self.metadata = Default::default();
    [6.534]
    [6.630]
    pub fn clear_meta(&mut self) -> &mut Self {
    self.meta.clear();
  • replacement in common/beancount-types/src/transaction.rs at line 223
    [6.717][6.717:762]()
    self.narration = Default::default();
    [6.717]
    [6.762]
    self.narration = None;
  • replacement in common/beancount-types/src/transaction.rs at line 229
    [6.845][6.845:886]()
    self.payee = Default::default();
    [6.845]
    [6.886]
    self.payee = None;
  • replacement in common/beancount-types/src/transaction.rs at line 262
    [6.1482][6.1482:1615]()
    pub fn set_metadata(&mut self, metadata: impl Into<TransactionMetadata>) -> &mut Self {
    self.metadata = metadata.into();
    [6.1482]
    [6.1615]
    pub fn set_meta(&mut self, meta: impl Into<MetadataMap>) -> &mut Self {
    self.meta = meta.into();
  • edit in common/beancount-types/src/transaction.rs at line 284
    [6.2106]
    [6.2106]
    }
  • replacement in common/beancount-types/src/transaction.rs at line 286
    [6.2107][6.2107:2266]()
    #[inline]
    pub fn with_metadata(&mut self, block: impl FnOnce(&mut TransactionMetadata)) -> &mut Self {
    block(&mut self.metadata);
    self
    [6.2107]
    [6.2266]
    impl Transaction {
    pub fn main_account(&self) -> Option<&Acc> {
    self.postings
    .first()
    .map(|posting| posting.account.as_ref())
  • edit in common/beancount-types/src/transaction.rs at line 294
    [6.2287][6.2287:2434](),[6.2434][6.79:112]()
    pub fn with_postings(&mut self, block: impl FnOnce(&mut Vec<Posting>)) -> &mut Self {
    block(&mut self.postings);
    self
    }
    }
    impl Transaction {
    #[inline]
  • replacement in common/beancount-types/src/transaction.rs at line 295
    [6.168][6.168:213]()
    self.metadata
    .key_value
    [6.168]
    [6.213]
    self.meta
  • replacement in common/beancount-types/src/transaction.rs at line 308
    [6.1525][6.2435:2457]()
    metadata,
    [6.1525]
    [6.1525]
    links,
    meta,
  • replacement in common/beancount-types/src/transaction.rs at line 323
    [6.2459][6.2459:2493]()
    write!(f, "{metadata}")?;
    [6.2459]
    [6.1931]
    for link in links {
    write!(f, "\n {link}")?;
    }
    for (key, value) in meta {
    write!(f, "\n {key}: {value}")?;
    }
  • file addition: price.rs (---r------)
    [6.44]
    use core::fmt::Display;
    use time::Date;
    use crate::Amount;
    use crate::Commodity;
    use crate::MetadataKey;
    use crate::MetadataMap;
    use crate::MetadataValue;
    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
    pub struct Price {
    pub date: Date,
    pub quote: Commodity,
    pub price: Amount,
    pub meta: MetadataMap,
    }
    impl Price {
    pub fn new(date: Date, quote: Commodity, price: Amount) -> Self {
    let meta = MetadataMap::default();
    Self {
    date,
    quote,
    price,
    meta,
    }
    }
    }
    impl Price {
    #[inline]
    pub fn add_meta(
    &mut self,
    key: impl Into<MetadataKey>,
    value: impl Into<MetadataValue>,
    ) -> &mut Self {
    self.meta.insert(key.into(), value.into());
    self
    }
    #[inline]
    pub fn clear_meta(&mut self) -> &mut Self {
    self.meta.clear();
    self
    }
    #[inline]
    pub fn set_quote(&mut self, quote: impl Into<Commodity>) -> &mut Self {
    self.quote = quote.into();
    self
    }
    #[inline]
    pub fn set_price(&mut self, price: Amount) -> &mut Self {
    self.price = price;
    self
    }
    #[inline]
    pub fn set_date(&mut self, date: Date) -> &mut Self {
    self.date = date;
    self
    }
    #[inline]
    pub fn set_meta(&mut self, meta: impl Into<MetadataMap>) -> &mut Self {
    self.meta = meta.into();
    self
    }
    }
    impl Display for Price {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    let Self {
    date,
    quote,
    price,
    meta,
    } = self;
    write!(f, "{date} price {quote} {price}")?;
    for (key, value) in meta {
    write!(f, "\n {key}: {value}")?;
    }
    Ok(())
    }
    }
  • replacement in common/beancount-types/src/metadata.rs at line 1
    [6.2624][6.2625:2982](),[6.2982][6.381:572](),[6.572][6.2982:6532](),[6.2982][6.2982:6532](),[6.6532][6.573:714](),[6.714][6.6557:6691](),[6.6557][6.6557:6691](),[6.6691][6.715:839](),[6.839][6.6691:7247](),[6.6691][6.6691:7247]()
    use core::borrow::Borrow;
    use core::fmt::Display;
    use core::ops::Deref;
    use core::str::FromStr;
    use alloc::collections::BTreeMap;
    use delegate::delegate;
    use miette::Diagnostic;
    use snafu::ensure;
    use snafu::Backtrace;
    use snafu::Snafu;
    #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[repr(transparent)]
    pub struct Key {
    name: String,
    }
    impl Key {
    pub const unsafe fn from_unchecked(name: String) -> Self {
    Self { name }
    }
    }
    impl Borrow<str> for Key {
    fn borrow(&self) -> &str {
    &self.name
    }
    }
    impl Display for Key {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    f.write_str(&self.name)
    }
    }
    impl FromStr for Key {
    type Err = KeyError;
    #[inline]
    fn from_str(name: &str) -> Result<Self, Self::Err> {
    ensure!(is_valid_key(name), KeySnafu { name });
    let name = name.to_owned();
    Ok(Self { name })
    }
    }
    impl TryFrom<String> for Key {
    type Error = KeyError;
    fn try_from(name: String) -> Result<Self, Self::Error> {
    ensure!(is_valid_key(&name), KeySnafu { name });
    Ok(Self { name })
    }
    }
    #[derive(Debug, Diagnostic, Snafu)]
    pub struct KeyError {
    backtrace: Backtrace,
    name: String,
    }
    #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[repr(transparent)]
    pub struct Link {
    name: String,
    }
    impl Borrow<Lnk> for Link {
    fn borrow(&self) -> &Lnk {
    self
    }
    }
    impl Deref for Link {
    type Target = Lnk;
    fn deref(&self) -> &Self::Target {
    #[allow(unsafe_code)]
    unsafe {
    // SAFETY: self.name is a valid link name, by construction
    Self::Target::from_unchecked(&self.name)
    }
    }
    }
    impl Display for Link {
    delegate! {
    to self.name {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
    }
    }
    }
    impl From<&Lnk> for Link {
    #[inline]
    fn from(link: &Lnk) -> Self {
    link.to_owned()
    }
    }
    impl FromStr for Link {
    type Err = LinkError;
    #[inline]
    fn from_str(name: &str) -> Result<Self, Self::Err> {
    <&Lnk>::try_from(name).map(Self::from)
    }
    }
    impl TryFrom<String> for Link {
    type Error = LinkError;
    #[inline]
    fn try_from(name: String) -> Result<Self, Self::Error> {
    ensure!(is_valid_link_name(&name), LinkSnafu { name });
    Ok(Self { name })
    }
    }
    #[derive(Debug, Diagnostic, Snafu)]
    pub struct LinkError {
    name: String,
    backtrace: Backtrace,
    }
    #[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[repr(transparent)]
    pub struct Lnk {
    name: str,
    }
    impl Lnk {
    #[allow(unsafe_code)]
    #[inline]
    const unsafe fn from_unchecked(name: &str) -> &Self {
    let name: *const _ = name;
    let name = name as *const _;
    unsafe { &*name }
    }
    }
    impl ToOwned for Lnk {
    type Owned = Link;
    #[inline]
    fn to_owned(&self) -> Self::Owned {
    let name = self.name.to_owned();
    Self::Owned { name }
    }
    }
    impl<'l> TryFrom<&'l str> for &'l Lnk {
    type Error = LinkError;
    #[inline]
    fn try_from(name: &'l str) -> Result<Self, Self::Error> {
    ensure!(is_valid_link_name(name), LinkSnafu { name });
    Ok(
    #[allow(unsafe_code)]
    unsafe {
    // SAFETY: we have ensured that `name` is a valid link.
    Lnk::from_unchecked(name)
    },
    )
    }
    }
    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
    pub struct Transaction {
    pub key_value: BTreeMap<Key, Value>,
    pub links: Vec<Link>,
    }
    impl Transaction {
    #[inline]
    pub fn add_link(&mut self, link: impl Into<Link>) -> &mut Self {
    self.links.push(link.into());
    self
    }
    #[inline]
    pub fn add_key_value(&mut self, key: impl Into<Key>, value: impl Into<Value>) -> &mut Self {
    self.key_value.insert(key.into(), value.into());
    self
    }
    }
    impl Display for Transaction {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    for link in &self.links {
    write!(f, "\n {link}")?;
    }
    for (key, value) in &self.key_value {
    write!(f, "\n {key}: {value}")?;
    }
    Ok(())
    }
    }
    #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    pub enum Value {
    String(String),
    }
    impl Value {
    pub fn as_str(&self) -> Option<&str> {
    let Self::String(inner) = self;
    Some(inner)
    }
    }
    impl Display for Value {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    match self {
    Value::String(inner) => write!(f, "{inner:?}"),
    }
    }
    }
    impl<S> From<S> for Value
    where
    S: Into<String>,
    {
    fn from(value: S) -> Self {
    Self::String(value.into())
    }
    }
    fn is_valid_key(name: &str) -> bool {
    lazy_regex::regex_is_match!(r"^(:?[a-z][a-zA-Z0-9\-_]+)$", name)
    }
    fn is_valid_link_name(name: &str) -> bool {
    lazy_regex::regex_is_match!(r"^(:?\^[A-Za-z0-9\-_/.]+)$", name)
    }
    [6.2624]
    pub mod kv;
    pub mod link;
  • file addition: metadata (d--r------)
    [6.44]
  • file addition: link.rs (---r------)
    [0.1851]
    use alloc::collections::BTreeSet;
    use delegate::delegate;
    use miette::Diagnostic;
    use snafu::Backtrace;
    use snafu::ensure;
    use snafu::Snafu;
    use core::str::FromStr;
    use core::fmt::Display;
    use core::ops::Deref;
    use core::borrow::Borrow;
    #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[repr(transparent)]
    pub struct Link {
    pub(crate) name: String,
    }
    impl Borrow<Lnk> for Link {
    fn borrow(&self) -> &Lnk {
    self
    }
    }
    impl Deref for Link {
    type Target = Lnk;
    fn deref(&self) -> &Self::Target {
    #[allow(unsafe_code)]
    unsafe {
    // SAFETY: self.name is a valid link name, by construction
    Self::Target::from_unchecked(&self.name)
    }
    }
    }
    impl Display for Link {
    delegate! {
    to self.name {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
    }
    }
    }
    impl From<&Lnk> for Link {
    #[inline]
    fn from(link: &Lnk) -> Self {
    link.to_owned()
    }
    }
    impl FromStr for Link {
    type Err = LinkError;
    #[inline]
    fn from_str(name: &str) -> Result<Self, Self::Err> {
    <&Lnk>::try_from(name).map(Self::from)
    }
    }
    impl TryFrom<String> for Link {
    type Error = LinkError;
    #[inline]
    fn try_from(name: String) -> Result<Self, Self::Error> {
    ensure!(is_valid_link_name(&name), LinkSnafu { name });
    Ok(Self { name })
    }
    }
    #[derive(Debug, Diagnostic, Snafu)]
    pub struct LinkError {
    pub(crate) name: String,
    pub(crate) backtrace: Backtrace,
    }
    #[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[repr(transparent)]
    pub struct Lnk {
    pub(crate) name: str,
    }
    impl Lnk {
    #[allow(unsafe_code)]
    #[inline]
    pub(crate) const unsafe fn from_unchecked(name: &str) -> &Self {
    let name: *const _ = name;
    let name = name as *const _;
    unsafe { &*name }
    }
    }
    impl ToOwned for Lnk {
    type Owned = Link;
    #[inline]
    fn to_owned(&self) -> Self::Owned {
    let name = self.name.to_owned();
    Self::Owned { name }
    }
    }
    impl<'l> TryFrom<&'l str> for &'l Lnk {
    type Error = LinkError;
    #[inline]
    fn try_from(name: &'l str) -> Result<Self, Self::Error> {
    ensure!(is_valid_link_name(name), LinkSnafu { name });
    Ok(
    #[allow(unsafe_code)]
    unsafe {
    // SAFETY: we have ensured that `name` is a valid link.
    Lnk::from_unchecked(name)
    },
    )
    }
    }
    pub type Set = BTreeSet<Link>;
    fn is_valid_link_name(name: &str) -> bool {
    lazy_regex::regex_is_match!(r"^(:?\^[A-Za-z0-9\-_/.]+)$", name)
    }
  • file addition: kv.rs (---r------)
    [0.1851]
    use alloc::collections::BTreeMap;
    use miette::Diagnostic;
    use rust_decimal::Decimal;
    use snafu::Backtrace;
    use snafu::ensure;
    use snafu::Snafu;
    use core::ops::Deref;
    use core::str::FromStr;
    use core::fmt::Display;
    use core::borrow::Borrow;
    pub mod common_keys;
    #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[repr(transparent)]
    pub struct Key {
    name: String,
    }
    impl Key {
    #[must_use]
    pub const unsafe fn from_unchecked(name: String) -> Self {
    Self { name }
    }
    }
    impl Borrow<Ky> for Key {
    fn borrow(&self) -> &Ky {
    self
    }
    }
    impl Borrow<str> for Key {
    fn borrow(&self) -> &str {
    &self.name
    }
    }
    impl Deref for Key {
    type Target = Ky;
    fn deref(&self) -> &Self::Target {
    unsafe { Ky::from_unchecked(&self.name) }
    }
    }
    impl Display for Key {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    f.write_str(&self.name)
    }
    }
    impl From<&Ky> for Key {
    fn from(value: &Ky) -> Self {
    value.to_owned()
    }
    }
    impl FromStr for Key {
    type Err = KeyError;
    #[inline]
    fn from_str(name: &str) -> Result<Self, Self::Err> {
    Self::try_from(name)
    }
    }
    impl TryFrom<&str> for Key {
    type Error = KeyError;
    #[inline]
    fn try_from(name: &str) -> Result<Self, Self::Error> {
    ensure!(is_valid_key(name), KeySnafu { name });
    let name = name.to_owned();
    Ok(Self { name })
    }
    }
    impl TryFrom<String> for Key {
    type Error = KeyError;
    #[inline]
    fn try_from(name: String) -> Result<Self, Self::Error> {
    ensure!(is_valid_key(&name), KeySnafu { name });
    Ok(Self { name })
    }
    }
    #[derive(Debug, Diagnostic, Snafu)]
    pub struct KeyError {
    pub(crate) backtrace: Backtrace,
    pub(crate) name: String,
    }
    #[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[repr(transparent)]
    pub struct Ky {
    name: str,
    }
    impl Ky {
    #[must_use]
    pub const unsafe fn from_unchecked(name: &str) -> &Self {
    unsafe {
    let name: *const _ = name;
    let name: *const Self = name as _;
    &*name
    }
    }
    }
    impl Borrow<str> for Ky {
    fn borrow(&self) -> &str {
    &self.name
    }
    }
    impl Display for Ky {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    f.write_str(&self.name)
    }
    }
    impl ToOwned for Ky {
    type Owned = Key;
    fn to_owned(&self) -> Self::Owned {
    let name = self.name.to_owned();
    Key { name }
    }
    }
    impl<'s> TryFrom<&'s str> for &'s Ky {
    type Error = KeyError;
    #[inline]
    fn try_from(name: &'s str) -> Result<Self, Self::Error> {
    ensure!(is_valid_key(name), KeySnafu { name });
    Ok(unsafe { Ky::from_unchecked(name) })
    }
    }
    pub type Map = BTreeMap<Key, Value>;
    #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    pub enum Value {
    Number(Decimal),
    String(String),
    }
    impl Value {
    #[must_use]
    pub fn as_number(&self) -> Option<Decimal> {
    if let Self::Number(v) = self {
    Some(*v)
    } else {
    None
    }
    }
    #[must_use]
    pub fn as_str(&self) -> Option<&str> {
    if let Self::String(inner) = self {
    Some(inner)
    } else {
    None
    }
    }
    }
    impl Display for Value {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    match self {
    Value::Number(inner) => inner.fmt(f),
    Value::String(inner) => write!(f, "{inner:?}"),
    }
    }
    }
    impl From<&str> for Value {
    fn from(value: &str) -> Self {
    Self::from(value.to_owned())
    }
    }
    impl From<Decimal> for Value {
    fn from(value: Decimal) -> Self {
    Self::Number(value)
    }
    }
    impl From<String> for Value {
    fn from(value: String) -> Self {
    Self::String(value)
    }
    }
    impl From<u8> for Value {
    fn from(value: u8) -> Self {
    Self::Number(Decimal::from(value))
    }
    }
    impl From<u16> for Value {
    fn from(value: u16) -> Self {
    Self::Number(Decimal::from(value))
    }
    }
    impl From<u32> for Value {
    fn from(value: u32) -> Self {
    Self::Number(Decimal::from(value))
    }
    }
    impl From<u64> for Value {
    fn from(value: u64) -> Self {
    Self::Number(Decimal::from(value))
    }
    }
    fn is_valid_key(name: &str) -> bool {
    lazy_regex::regex_is_match!(r"^(:?[a-z][a-zA-Z0-9\-_]+)$", name)
    }
  • file addition: kv (d--r------)
    [0.1851]
  • file addition: common_keys.rs (---r------)
    [0.9034]
    use crate::MetadataKy;
    pub const FILENAME: &MetadataKy = unsafe { MetadataKy::from_unchecked("filename") };
    pub const LINE_NUMBER: &MetadataKy = unsafe { MetadataKy::from_unchecked("lineno") };
    pub const TIMESTAMP: &MetadataKy = unsafe { MetadataKy::from_unchecked("timestamp") };
    pub const TRANSACTION_ID: &MetadataKy = unsafe { MetadataKy::from_unchecked("transaction-id") };
  • replacement in common/beancount-types/src/lib.rs at line 14
    [6.4225][6.7248:7434]()
    pub use crate::metadata::Key as MetadataKey;
    pub use crate::metadata::Link;
    pub use crate::metadata::Transaction as TransactionMetadata;
    pub use crate::metadata::Value as MetadataValue;
    [6.4225]
    [5.0]
    pub use crate::metadata::kv::common_keys;
    pub use crate::metadata::kv::Key as MetadataKey;
    pub use crate::metadata::kv::Ky as MetadataKy;
    pub use crate::metadata::kv::Map as MetadataMap;
    pub use crate::metadata::kv::Value as MetadataValue;
    pub use crate::metadata::link::Link;
    pub use crate::metadata::link::Set as LinkSet;
  • edit in common/beancount-types/src/lib.rs at line 47
    [6.4457]
    [6.6434]
    }
    impl Directive {
    pub fn add_meta(
    &mut self,
    key: impl Into<MetadataKey>,
    value: impl Into<MetadataValue>,
    ) -> &mut Self {
    match self {
    Directive::Balance(inner) => {
    inner.add_meta(key, value);
    }
    Directive::Price(inner) => {
    inner.add_meta(key, value);
    }
    Directive::Transaction(inner) => {
    inner.add_meta(key, value);
    }
    }
    self
    }
  • edit in common/beancount-types/src/lib.rs at line 72
    [6.6454]
    [6.6454]
    /// Returns `true` if the directive is [`Balance`].
    ///
    /// [`Balance`]: Directive::Balance
    #[must_use]
    pub fn is_balance(&self) -> bool {
    matches!(self, Self::Balance(..))
    }
    }
    impl Directive {
  • replacement in common/beancount-types/src/lib.rs at line 94
    [5.149][6.6778:6949](),[6.6778][6.6778:6949]()
    Directive::Transaction(transaction) => transaction
    .postings
    .get(0)
    .map(|posting| posting.account.as_ref()),
    [5.149]
    [6.909]
    Directive::Transaction(transaction) => transaction.main_account(),
  • edit in common/beancount-types/src/lib.rs at line 123
    [6.7363]
    [6.4593]
    impl From<Price> for Directive {
    fn from(price: Price) -> Self {
    Self::Price(price)
    }
    }
  • edit in common/beancount-types/src/balance.rs at line 10
    [6.9337]
    [6.9397]
    use crate::MetadataKey;
    use crate::MetadataMap;
    use crate::MetadataValue;
  • replacement in common/beancount-types/src/balance.rs at line 14
    [6.9398][6.7502:7559]()
    #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd)]
    [6.9398]
    [6.9443]
    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
  • edit in common/beancount-types/src/balance.rs at line 21
    [6.9536]
    [6.9536]
    pub meta: MetadataMap,
    }
    impl Balance {
    pub fn new(date: Date, account: impl Into<Account>, amount: Amount) -> Self {
    let (account, meta) = (account.into(), MetadataMap::default());
    Self {
    date,
    account,
    amount,
    meta,
    }
    }
  • edit in common/beancount-types/src/balance.rs at line 38
    [6.1221]
    [6.1221]
    #[inline]
    pub fn add_meta(
    &mut self,
    key: impl Into<MetadataKey>,
    value: impl Into<MetadataValue>,
    ) -> &mut Self {
    self.meta.insert(key.into(), value.into());
    self
    }
  • edit in common/beancount-types/src/balance.rs at line 49
    [6.1235]
    [6.1235]
    pub fn clear_meta(&mut self) -> &mut Self {
    self.meta.clear();
    self
    }
    #[inline]
    pub fn set_account(&mut self, account: impl Into<Account>) -> &mut Self {
    self.account = account.into();
    self
    }
    #[inline]
    pub fn set_amount(&mut self, amount: Amount) -> &mut Self {
    self.amount = amount;
    self
    }
    #[inline]
    pub fn set_date(&mut self, date: Date) -> &mut Self {
    self.date = date;
    self
    }
    #[inline]
    pub fn set_meta(&mut self, meta: impl Into<MetadataMap>) -> &mut Self {
    self.meta = meta.into();
    self
    }
    }
    impl Balance {
    #[inline]
    #[must_use]
  • edit in common/beancount-types/src/balance.rs at line 97
    [6.9720]
    [6.9720]
    meta,
  • replacement in common/beancount-types/src/balance.rs at line 99
    [6.9738][6.9738:9793]()
    write!(f, "{date} balance {account} {amount}")
    [6.9738]
    [6.9793]
    write!(f, "{date} balance {account} {amount}")?;
    for (key, value) in meta {
    write!(f, "\n {key}: {value}")?;
    }
    Ok(())
  • edit in common/beancount-types/src/account/template.rs at line 13
    [20.9989]
    [20.10005]
    use crate::Acc;
  • edit in common/beancount-types/src/account/template.rs at line 113
    [4.1133]
    [20.12256]
    pub fn base(&self) -> &Acc {
    &self.base
    }
  • replacement in common/beancount-tree-writer/src/lib.rs at line 11
    [6.129][6.129:159]()
    use beancount_types::Account;
    [6.129]
    [6.159]
    use beancount_types::Acc;
    use beancount_types::Balance;
    use beancount_types::Commodity;
  • edit in common/beancount-tree-writer/src/lib.rs at line 15
    [6.191]
    [6.191]
    use beancount_types::Price;
  • replacement in common/beancount-tree-writer/src/lib.rs at line 26
    [6.633][6.633:650]()
    use time::Month;
    [6.562]
    [6.16505]
    use time::Date;
    use tracing::warn;
  • replacement in common/beancount-tree-writer/src/lib.rs at line 61
    [3.91][3.91:181]()
    .into_group_map_by(|directive| DirectiveIndex::try_from(directive).unwrap());
    [3.91]
    [6.1774]
    .filter_map(|directive| {
    Some((file_for(&self.config.output_path, &directive)?, directive))
    })
    .into_group_map();
  • replacement in common/beancount-tree-writer/src/lib.rs at line 68
    [6.1834][6.539:638]()
    .map(|(index, directives)| self.write_month(pretty_printer_config, index, directives))
    [6.1834]
    [6.1910]
    .map(|(file, directives)| self.write_month(pretty_printer_config, &file, directives))
  • replacement in common/beancount-tree-writer/src/lib.rs at line 84
    [6.770][6.2297:2328](),[6.2297][6.2297:2328]()
    index: DirectiveIndex,
    [6.770]
    [6.2328]
    file: &Utf8Path,
  • replacement in common/beancount-tree-writer/src/lib.rs at line 98
    [6.979][6.979:1039](),[6.1039][6.2514:2544](),[6.2514][6.2514:2544]()
    let file = index.file_in(&self.config.output_path);
    self.open_file(&file)
    [6.979]
    [6.2544]
    self.open_file(file)
  • replacement in common/beancount-tree-writer/src/lib.rs at line 102
    [6.2682][6.2682:2740]()
    .context(PrettyPrintingSnafu { file, index })
    [6.2682]
    [6.2740]
    .context(PrettyPrintingSnafu { file })
  • replacement in common/beancount-tree-writer/src/lib.rs at line 116
    [6.3055][6.3055:3172]()
    #[derive(Debug, Eq, Hash, PartialEq)]
    struct DirectiveIndex {
    account: Account,
    year: i32,
    month: Month,
    [6.3055]
    [6.3172]
    fn file_for(base: &Utf8Path, directive: &Directive) -> Option<Utf8PathBuf> {
    match directive {
    Directive::Balance(Balance { date, account, .. }) => {
    Some(account_file(base, account, *date))
    }
    Directive::Price(Price { quote, .. }) => Some(price_file(base, quote)),
    Directive::Transaction(transaction) => {
    if let Some(account) = transaction.main_account() {
    Some(account_file(base, account, transaction.date))
    } else {
    warn!(
    ?transaction,
    "ignoring transaction since it has no postings"
    );
    None
    }
    }
    }
  • replacement in common/beancount-tree-writer/src/lib.rs at line 139
    [6.3175][6.3175:3382]()
    impl DirectiveIndex {
    fn file_in(&self, path: &Utf8Path) -> Utf8PathBuf {
    let Self {
    account,
    year,
    month,
    } = self;
    let month = *month as u8;
    [6.3175]
    [6.3382]
    fn account_file(base: &Utf8Path, account: &Acc, date: Date) -> Utf8PathBuf {
    let year = date.year();
    let month = date.month();
    let month = month as u8;
  • replacement in common/beancount-tree-writer/src/lib.rs at line 144
    [6.3383][6.324:370]()
    let separator = path::MAIN_SEPARATOR;
    [6.3383]
    [6.370]
    let separator = path::MAIN_SEPARATOR;
  • replacement in common/beancount-tree-writer/src/lib.rs at line 146
    [6.371][6.3383:3424](),[6.3383][6.3383:3424](),[6.3424][6.372:490](),[6.490][6.3565:3599](),[6.3565][6.3565:3599]()
    let mut path = path.to_string();
    let additional = account.len() + 4 + 2 + 5 + 3; // account name + year + month + extension + extra separators
    path.reserve(additional);
    [6.371]
    [6.3599]
    let mut path = base.to_string();
    let additional = account.len() + 4 + 2 + 5 + 3; // account name + year + month + extension + extra separators
    path.reserve(additional);
  • replacement in common/beancount-tree-writer/src/lib.rs at line 150
    [6.3600][6.3600:3640](),[6.3640][6.491:571]()
    account
    .segments()
    .for_each(|segment| write!(path, "{separator}{segment}").unwrap());
    [6.3600]
    [6.3714]
    account
    .segments()
    .for_each(|segment| write!(path, "{separator}{segment}").unwrap());
  • replacement in common/beancount-tree-writer/src/lib.rs at line 154
    [6.3715][6.572:650]()
    write!(path, "{separator}{year}{separator}{month:02}.bean").unwrap();
    [6.3715]
    [6.3773]
    write!(path, "{separator}{year}{separator}{month:02}.bean").unwrap();
  • replacement in common/beancount-tree-writer/src/lib.rs at line 156
    [6.3774][6.3774:3800]()
    path.into()
    }
    [6.3774]
    [6.3800]
    Utf8PathBuf::from(path)
  • edit in common/beancount-tree-writer/src/lib.rs at line 158
    [6.3802][6.3802:3849](),[6.3849][6.651:679]()
    impl TryFrom<&Directive> for DirectiveIndex {
    type Error = ErrorKind;
  • replacement in common/beancount-tree-writer/src/lib.rs at line 159
    [6.3874][6.3874:4287]()
    fn try_from(value: &Directive) -> Result<Self, Self::Error> {
    let account = if let Some(account) = value.main_account() {
    account.to_owned()
    } else {
    return IndexingDirectiveSnafu {
    directive: value.clone(),
    }
    .fail();
    };
    let date = value.date();
    let year = date.year();
    let month = date.month();
    [6.3874]
    [6.4287]
    fn price_file(base: &Utf8Path, quote: &Commodity) -> Utf8PathBuf {
    let mut path = base.join("prices");
    path.push(&**quote);
    path.set_extension("bean");
  • replacement in common/beancount-tree-writer/src/lib.rs at line 164
    [6.4288][6.4288:4381]()
    Ok(Self {
    account,
    year,
    month,
    })
    }
    [6.4288]
    [6.1170]
    path
  • replacement in common/beancount-tree-writer/src/lib.rs at line 175
    [6.735][6.1395:1487](),[6.1395][6.1395:1487]()
    #[snafu(display("error while pretty printing directives for key {index:?} to {file}"))]
    [6.735]
    [6.1487]
    #[snafu(display("error while pretty printing directives to {file}"))]
  • edit in common/beancount-tree-writer/src/lib.rs at line 179
    [6.1565][6.1565:1596]()
    index: DirectiveIndex,
  • edit in common/beancount-tree-writer/Cargo.toml at line 26
    [21.766]
    tracing.workspace = true
  • edit in common/beancount-pretty-printer/src/lib.rs at line 13
    [6.274][2.0:42]()
    use beancount_types::TransactionMetadata;
  • edit in common/beancount-pretty-printer/src/lib.rs at line 157
    [6.1456]
    [6.1456]
    meta,
  • replacement in common/beancount-pretty-printer/src/lib.rs at line 161
    [6.1653][6.1653:1707]()
    self.print_amount(self.config.amount, amount)
    [6.1653]
    [6.1632]
    self.print_amount(self.config.amount, amount)?;
    for (key, value) in meta {
    write!(self.inner, "\n {key}: {value}")?;
    }
    Ok(())
  • replacement in common/beancount-pretty-printer/src/lib.rs at line 207
    [6.2681][2.43:65]()
    metadata,
    [6.2681]
    [6.2681]
    links,
    meta,
  • replacement in common/beancount-pretty-printer/src/lib.rs at line 215
    [6.2811][6.2811:3066]()
    (Some(payee), Some(narration)) => write!(self.inner, r#" "{payee}" "{narration}""#)?,
    (Some(payee), None) => write!(self.inner, r#" "{payee}" """#)?,
    (None, Some(narration)) => write!(self.inner, r#" "{narration}""#)?,
    [6.2811]
    [6.3066]
    (Some(payee), Some(narration)) => write!(self.inner, r" {payee:?} {narration:?}")?,
    (Some(payee), None) => write!(self.inner, r#" {payee:?} """#)?,
    (None, Some(narration)) => write!(self.inner, r" {narration:?}")?,
  • replacement in common/beancount-pretty-printer/src/lib.rs at line 221
    [6.3108][2.66:118]()
    self.print_transaction_metadata(metadata)?;
    [6.3108]
    [2.118]
    for link in links {
    write!(self.inner, "\n {link}")?;
    }
    for (key, value) in meta {
    write!(self.inner, "\n {key}: {value}")?;
    }
  • edit in common/beancount-pretty-printer/src/lib.rs at line 259
    [6.3850][2.120:516]()
    fn print_transaction_metadata(&mut self, metadata: &TransactionMetadata) -> Result<()> {
    let TransactionMetadata {
    key_value, links, ..
    } = metadata;
    for link in links {
    write!(self.inner, "\n {link}")?;
    }
    for (key, value) in key_value {
    write!(self.inner, "\n {key}: {value}")?;
    }
    Ok(())
    }