ref: move Posting account name fns to AccountName
accountNamePostingType accountNameWithoutPostingType accountNameWithPostingType joinAccountNames concatAccountNames accountNameApplyAliases accountNameApplyAliasesMemo
This commit is contained in:
parent
5a0d61998a
commit
44211c1c57
@ -45,18 +45,28 @@ module Hledger.Data.AccountName (
|
||||
,subAccountNamesFrom
|
||||
,topAccountNames
|
||||
,unbudgetedAccountName
|
||||
,accountNamePostingType
|
||||
,accountNameWithoutPostingType
|
||||
,accountNameWithPostingType
|
||||
,joinAccountNames
|
||||
,concatAccountNames
|
||||
,accountNameApplyAliases
|
||||
,accountNameApplyAliasesMemo
|
||||
,tests_AccountName
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Applicative ((<|>))
|
||||
import Control.Monad (foldM)
|
||||
import Data.Foldable (asum, toList)
|
||||
import qualified Data.List.NonEmpty as NE
|
||||
import qualified Data.Map as M
|
||||
import Data.MemoUgly (memo)
|
||||
import qualified Data.Set as S
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Tree (Tree(..))
|
||||
import Safe
|
||||
import Text.DocLayout (realLength)
|
||||
|
||||
import Hledger.Data.Types
|
||||
@ -132,6 +142,65 @@ accountNameLevel a = T.length (T.filter (==acctsepchar) a) + 1
|
||||
unbudgetedAccountName :: T.Text
|
||||
unbudgetedAccountName = "<unbudgeted>"
|
||||
|
||||
accountNamePostingType :: AccountName -> PostingType
|
||||
accountNamePostingType a
|
||||
| T.null a = RegularPosting
|
||||
| T.head a == '[' && T.last a == ']' = BalancedVirtualPosting
|
||||
| T.head a == '(' && T.last a == ')' = VirtualPosting
|
||||
| otherwise = RegularPosting
|
||||
|
||||
accountNameWithoutPostingType :: AccountName -> AccountName
|
||||
accountNameWithoutPostingType a = case accountNamePostingType a of
|
||||
BalancedVirtualPosting -> textUnbracket a
|
||||
VirtualPosting -> textUnbracket a
|
||||
RegularPosting -> a
|
||||
|
||||
accountNameWithPostingType :: PostingType -> AccountName -> AccountName
|
||||
accountNameWithPostingType BalancedVirtualPosting = wrap "[" "]" . accountNameWithoutPostingType
|
||||
accountNameWithPostingType VirtualPosting = wrap "(" ")" . accountNameWithoutPostingType
|
||||
accountNameWithPostingType RegularPosting = accountNameWithoutPostingType
|
||||
|
||||
-- | Prefix one account name to another, preserving posting type
|
||||
-- indicators like concatAccountNames.
|
||||
joinAccountNames :: AccountName -> AccountName -> AccountName
|
||||
joinAccountNames a b = concatAccountNames $ filter (not . T.null) [a,b]
|
||||
|
||||
-- | Join account names into one. If any of them has () or [] posting type
|
||||
-- indicators, these (the first type encountered) will also be applied to
|
||||
-- the resulting account name.
|
||||
concatAccountNames :: [AccountName] -> AccountName
|
||||
concatAccountNames as = accountNameWithPostingType t $ T.intercalate ":" $ map accountNameWithoutPostingType as
|
||||
where t = headDef RegularPosting $ filter (/= RegularPosting) $ map accountNamePostingType as
|
||||
|
||||
-- | Rewrite an account name using all matching aliases from the given list, in sequence.
|
||||
-- Each alias sees the result of applying the previous aliases.
|
||||
-- Or, return any error arising from a bad regular expression in the aliases.
|
||||
accountNameApplyAliases :: [AccountAlias] -> AccountName -> Either RegexError AccountName
|
||||
accountNameApplyAliases aliases a =
|
||||
let (aname,atype) = (accountNameWithoutPostingType a, accountNamePostingType a)
|
||||
in foldM
|
||||
(\acct alias -> dbg6 "result" $ aliasReplace (dbg6 "alias" alias) (dbg6 "account" acct))
|
||||
aname
|
||||
aliases
|
||||
>>= Right . accountNameWithPostingType atype
|
||||
|
||||
-- | Memoising version of accountNameApplyAliases, maybe overkill.
|
||||
accountNameApplyAliasesMemo :: [AccountAlias] -> AccountName -> Either RegexError AccountName
|
||||
accountNameApplyAliasesMemo aliases = memo (accountNameApplyAliases aliases)
|
||||
-- XXX re-test this memoisation
|
||||
|
||||
-- aliasMatches :: AccountAlias -> AccountName -> Bool
|
||||
-- aliasMatches (BasicAlias old _) a = old `isAccountNamePrefixOf` a
|
||||
-- aliasMatches (RegexAlias re _) a = regexMatchesCI re a
|
||||
|
||||
aliasReplace :: AccountAlias -> AccountName -> Either RegexError AccountName
|
||||
aliasReplace (BasicAlias old new) a
|
||||
| old `isAccountNamePrefixOf` a || old == a =
|
||||
Right $ new <> T.drop (T.length old) a
|
||||
| otherwise = Right a
|
||||
aliasReplace (RegexAlias re repl) a =
|
||||
fmap T.pack . regexReplace re repl $ T.unpack a -- XXX
|
||||
|
||||
-- | Remove some number of account name components from the front of the account name.
|
||||
-- If the special "<unbudgeted>" top-level account is present, it is preserved and
|
||||
-- dropping affects the rest of the account name.
|
||||
|
||||
@ -48,13 +48,6 @@ module Hledger.Data.Posting (
|
||||
isPostingInDateSpan',
|
||||
-- * account name operations
|
||||
accountNamesFromPostings,
|
||||
accountNamePostingType,
|
||||
accountNameWithoutPostingType,
|
||||
accountNameWithPostingType,
|
||||
joinAccountNames,
|
||||
concatAccountNames,
|
||||
accountNameApplyAliases,
|
||||
accountNameApplyAliasesMemo,
|
||||
-- * comment/tag operations
|
||||
commentJoin,
|
||||
commentAddTag,
|
||||
@ -77,12 +70,10 @@ module Hledger.Data.Posting (
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Monad (foldM)
|
||||
import Data.Default (def)
|
||||
import Data.Foldable (asum)
|
||||
import qualified Data.Map as M
|
||||
import Data.Maybe (fromMaybe, isJust)
|
||||
import Data.MemoUgly (memo)
|
||||
import Data.List (foldl', sort, union)
|
||||
import qualified Data.Set as S
|
||||
import Data.Text (Text)
|
||||
@ -90,7 +81,7 @@ import qualified Data.Text as T
|
||||
import qualified Data.Text.Lazy as TL
|
||||
import qualified Data.Text.Lazy.Builder as TB
|
||||
import Data.Time.Calendar (Day)
|
||||
import Safe (headDef, maximumBound)
|
||||
import Safe (maximumBound)
|
||||
import Text.DocLayout (realLength)
|
||||
|
||||
import Text.Tabular.AsciiWide
|
||||
@ -395,38 +386,6 @@ isPostingInDateSpan' SecondaryDate s = spanContainsDate s . postingDate2
|
||||
isEmptyPosting :: Posting -> Bool
|
||||
isEmptyPosting = mixedAmountLooksZero . pamount
|
||||
|
||||
-- AccountName stuff that depends on PostingType
|
||||
|
||||
accountNamePostingType :: AccountName -> PostingType
|
||||
accountNamePostingType a
|
||||
| T.null a = RegularPosting
|
||||
| T.head a == '[' && T.last a == ']' = BalancedVirtualPosting
|
||||
| T.head a == '(' && T.last a == ')' = VirtualPosting
|
||||
| otherwise = RegularPosting
|
||||
|
||||
accountNameWithoutPostingType :: AccountName -> AccountName
|
||||
accountNameWithoutPostingType a = case accountNamePostingType a of
|
||||
BalancedVirtualPosting -> textUnbracket a
|
||||
VirtualPosting -> textUnbracket a
|
||||
RegularPosting -> a
|
||||
|
||||
accountNameWithPostingType :: PostingType -> AccountName -> AccountName
|
||||
accountNameWithPostingType BalancedVirtualPosting = wrap "[" "]" . accountNameWithoutPostingType
|
||||
accountNameWithPostingType VirtualPosting = wrap "(" ")" . accountNameWithoutPostingType
|
||||
accountNameWithPostingType RegularPosting = accountNameWithoutPostingType
|
||||
|
||||
-- | Prefix one account name to another, preserving posting type
|
||||
-- indicators like concatAccountNames.
|
||||
joinAccountNames :: AccountName -> AccountName -> AccountName
|
||||
joinAccountNames a b = concatAccountNames $ filter (not . T.null) [a,b]
|
||||
|
||||
-- | Join account names into one. If any of them has () or [] posting type
|
||||
-- indicators, these (the first type encountered) will also be applied to
|
||||
-- the resulting account name.
|
||||
concatAccountNames :: [AccountName] -> AccountName
|
||||
concatAccountNames as = accountNameWithPostingType t $ T.intercalate ":" $ map accountNameWithoutPostingType as
|
||||
where t = headDef RegularPosting $ filter (/= RegularPosting) $ map accountNamePostingType as
|
||||
|
||||
-- | Apply some account aliases to the posting's account name, as described by accountNameApplyAliases.
|
||||
-- This can fail due to a bad replacement pattern in a regular expression alias.
|
||||
postingApplyAliases :: [AccountAlias] -> Posting -> Either RegexError Posting
|
||||
@ -450,35 +409,6 @@ postingApplyCommodityStyles styles p = p{pamount=styleMixedAmount styles $ pamou
|
||||
postingAddTags :: Posting -> [Tag] -> Posting
|
||||
postingAddTags p@Posting{ptags} tags = p{ptags=ptags `union` tags}
|
||||
|
||||
-- | Rewrite an account name using all matching aliases from the given list, in sequence.
|
||||
-- Each alias sees the result of applying the previous aliases.
|
||||
-- Or, return any error arising from a bad regular expression in the aliases.
|
||||
accountNameApplyAliases :: [AccountAlias] -> AccountName -> Either RegexError AccountName
|
||||
accountNameApplyAliases aliases a =
|
||||
let (aname,atype) = (accountNameWithoutPostingType a, accountNamePostingType a)
|
||||
in foldM
|
||||
(\acct alias -> dbg6 "result" $ aliasReplace (dbg6 "alias" alias) (dbg6 "account" acct))
|
||||
aname
|
||||
aliases
|
||||
>>= Right . accountNameWithPostingType atype
|
||||
|
||||
-- | Memoising version of accountNameApplyAliases, maybe overkill.
|
||||
accountNameApplyAliasesMemo :: [AccountAlias] -> AccountName -> Either RegexError AccountName
|
||||
accountNameApplyAliasesMemo aliases = memo (accountNameApplyAliases aliases)
|
||||
-- XXX re-test this memoisation
|
||||
|
||||
-- aliasMatches :: AccountAlias -> AccountName -> Bool
|
||||
-- aliasMatches (BasicAlias old _) a = old `isAccountNamePrefixOf` a
|
||||
-- aliasMatches (RegexAlias re _) a = regexMatchesCI re a
|
||||
|
||||
aliasReplace :: AccountAlias -> AccountName -> Either RegexError AccountName
|
||||
aliasReplace (BasicAlias old new) a
|
||||
| old `isAccountNamePrefixOf` a || old == a =
|
||||
Right $ new <> T.drop (T.length old) a
|
||||
| otherwise = Right a
|
||||
aliasReplace (RegexAlias re repl) a =
|
||||
fmap T.pack . regexReplace re repl $ T.unpack a -- XXX
|
||||
|
||||
-- | Apply a specified valuation to this posting's amount, using the
|
||||
-- provided price oracle, commodity styles, and reference dates.
|
||||
-- See amountApplyValuation.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user