rename old Account module to AccountName, extract new Account module from Models
This commit is contained in:
		
							parent
							
								
									5475a3868c
								
							
						
					
					
						commit
						1524dffbe2
					
				
							
								
								
									
										162
									
								
								Account.hs
									
									
									
									
									
								
							
							
						
						
									
										162
									
								
								Account.hs
									
									
									
									
									
								
							| @ -1,89 +1,101 @@ | |||||||
| 
 |  | ||||||
| module Account | module Account | ||||||
| where | where | ||||||
| import Utils | import Utils | ||||||
| import BasicTypes | import BasicTypes | ||||||
| 
 | import AccountName | ||||||
| -- AccountNames are strings like "assets:cash:petty"; from these we build | import Entry | ||||||
| -- the chart of accounts, which should be a simple hierarchy.  | import Transaction | ||||||
| type AccountName = String | import EntryTransaction | ||||||
| 
 | import Ledger | ||||||
| accountNameComponents :: AccountName -> [String] |  | ||||||
| accountNameComponents = splitAtElement ':' |  | ||||||
| 
 |  | ||||||
| accountNameFromComponents :: [String] -> AccountName |  | ||||||
| accountNameFromComponents = concat . intersperse ":" |  | ||||||
| 
 |  | ||||||
| accountLeafName :: AccountName -> String |  | ||||||
| accountLeafName = rhead . accountNameComponents |  | ||||||
| 
 |  | ||||||
| accountNameLevel :: AccountName -> Int |  | ||||||
| accountNameLevel = length . accountNameComponents |  | ||||||
| 
 |  | ||||||
| -- ["a:b:c","d:e"] -> ["a","a:b","a:b:c","d","d:e"] |  | ||||||
| expandAccountNames :: [AccountName] -> [AccountName] |  | ||||||
| expandAccountNames as = nub $ concat $ map expand as |  | ||||||
|     where expand as = map accountNameFromComponents (tail $ inits $ accountNameComponents as) |  | ||||||
| 
 |  | ||||||
| -- ["a:b:c","d:e"] -> ["a","d"] |  | ||||||
| topAccountNames :: [AccountName] -> [AccountName] |  | ||||||
| topAccountNames as = [a | a <- expandAccountNames as, accountNameLevel a == 1] |  | ||||||
| 
 |  | ||||||
| parentAccountName :: AccountName -> Maybe AccountName |  | ||||||
| parentAccountName a =  |  | ||||||
|     case accountNameLevel a > 1 of |  | ||||||
|       True -> Just $ accountNameFromComponents $ rtail $ accountNameComponents a |  | ||||||
|       False -> Nothing |  | ||||||
| 
 |  | ||||||
| s `isSubAccountNameOf` p =  |  | ||||||
|     ((p ++ ":") `isPrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1)) |  | ||||||
| 
 |  | ||||||
| subAccountNamesFrom :: [AccountName] -> AccountName -> [AccountName] |  | ||||||
| subAccountNamesFrom accts a = filter (`isSubAccountNameOf` a) accts |  | ||||||
| 
 |  | ||||||
| matchAccountName :: String -> AccountName -> Bool |  | ||||||
| matchAccountName s a = |  | ||||||
|     case matchRegex (mkRegex s) a of |  | ||||||
|       Nothing -> False |  | ||||||
|       otherwise -> True |  | ||||||
| 
 |  | ||||||
| indentAccountName :: AccountName -> String |  | ||||||
| indentAccountName a = replicate (((accountNameLevel a) - 1) * 2) ' ' ++ (accountLeafName a) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| -- We could almost get by with just the above, but we need smarter | -- an Account caches an account's name, balance and transactions for convenience | ||||||
| -- structures to eg display the account tree with boring accounts elided. | type Account = (AccountName,[EntryTransaction],Amount) | ||||||
| -- first, here is a tree of AccountNames; Account and Account tree are |  | ||||||
| -- defined later. |  | ||||||
| 
 | 
 | ||||||
| antacctname = fst . node | aname (a,_,_) = a | ||||||
| antsubs = snd . node | atransactions (_,ts,_) = ts | ||||||
|  | abalance (_,_,b) = b | ||||||
| 
 | 
 | ||||||
| accountNameTreeFrom_props = | mkAccount :: Ledger -> AccountName -> Account | ||||||
|     [ | mkAccount l a = (a, accountNameTransactionsNoSubs l a, accountNameBalance l a) | ||||||
|      accountNameTreeFrom ["a"] == Tree ("top", [Tree ("a",[])]), | 
 | ||||||
|      accountNameTreeFrom ["a","b"] == Tree ("top", [Tree ("a", []), Tree ("b", [])]), | accountNameBalance :: Ledger -> AccountName -> Amount | ||||||
|      accountNameTreeFrom ["a","a:b"] == Tree ("top", [Tree ("a", [Tree ("a:b", [])])]), | accountNameBalance l a = sumEntryTransactions (accountNameTransactions l a) | ||||||
|      accountNameTreeFrom ["a:b"] == Tree ("top", [Tree ("a", [Tree ("a:b", [])])]) | 
 | ||||||
|     ] | accountNameTransactions :: Ledger -> AccountName -> [EntryTransaction] | ||||||
| accountNameTreeFrom :: [AccountName] -> Tree AccountName | accountNameTransactions l a = ledgerTransactionsMatching (["^" ++ a ++ "(:.+)?$"], []) l | ||||||
| accountNameTreeFrom accts =  | 
 | ||||||
|     Tree ("top", accountsFrom (topAccountNames accts)) | accountNameBalanceNoSubs :: Ledger -> AccountName -> Amount | ||||||
|  | accountNameBalanceNoSubs l a = sumEntryTransactions (accountNameTransactionsNoSubs l a) | ||||||
|  | 
 | ||||||
|  | accountNameTransactionsNoSubs :: Ledger -> AccountName -> [EntryTransaction] | ||||||
|  | accountNameTransactionsNoSubs l a = ledgerTransactionsMatching (["^" ++ a ++ "$"], []) l | ||||||
|  | 
 | ||||||
|  | -- showAccountNamesWithBalances :: [(AccountName,String)] -> Ledger -> String | ||||||
|  | -- showAccountNamesWithBalances as l = | ||||||
|  | --     unlines $ map (showAccountNameAndBalance l) as | ||||||
|  | 
 | ||||||
|  | -- showAccountNameAndBalance :: Ledger -> (AccountName, String) -> String | ||||||
|  | -- showAccountNameAndBalance l (a, adisplay) = | ||||||
|  | --     printf "%20s  %s" (showBalance $ accountBalance l a) adisplay | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- a tree of Accounts | ||||||
|  | 
 | ||||||
|  | atacct = fst . node | ||||||
|  | 
 | ||||||
|  | addDataToAccountNameTree :: Ledger -> Tree AccountName -> Tree Account | ||||||
|  | addDataToAccountNameTree l ant =  | ||||||
|  |     Tree (mkAccount l aname, map (addDataToAccountNameTree l) (branches ant)) | ||||||
|         where  |         where  | ||||||
|           accountsFrom :: [AccountName] -> [Tree AccountName] |           aname = antacctname ant | ||||||
|           accountsFrom [] = [] |  | ||||||
|           accountsFrom as = [Tree (a, accountsFrom $ subs a) | a <- as] |  | ||||||
|           subs = (subAccountNamesFrom accts) |  | ||||||
| 
 | 
 | ||||||
| showAccountNameTree :: Tree AccountName -> String | showAccountTreeWithBalances :: Ledger -> Int -> Tree Account -> String | ||||||
| showAccountNameTree at = showAccountNameTrees $ antsubs at | showAccountTreeWithBalances l depth at = (showAccountTreesWithBalances l depth) (branches at) | ||||||
| 
 | 
 | ||||||
| showAccountNameTrees :: [Tree AccountName] -> String | showAccountTreesWithBalances :: Ledger -> Int -> [Tree Account] -> String | ||||||
| showAccountNameTrees ats = | showAccountTreesWithBalances _ 0 _ = "" | ||||||
|     concatMap showAccountNameBranch ats | showAccountTreesWithBalances l depth ats = | ||||||
|  |     concatMap showAccountBranch ats | ||||||
|         where |         where | ||||||
|           showAccountNameBranch at = topacct ++ "\n" ++ subs |           showAccountBranch :: Tree Account -> String | ||||||
|  |           showAccountBranch at =  | ||||||
|  |               topacct ++ "\n" ++ subaccts | ||||||
|  | --               case boring of | ||||||
|  | --                 True  ->  | ||||||
|  | --                 False ->  | ||||||
|               where |               where | ||||||
|                 topacct = indentAccountName $ antacctname at |                 topacct = (showAmount bal) ++ "  " ++ (indentAccountName name) | ||||||
|                 subs = showAccountNameTrees $ antsubs at |                 showAmount amt = printf "%20s" (show amt) | ||||||
|  |                 name = aname $ atacct at | ||||||
|  |                 txns = atransactions $ atacct at | ||||||
|  |                 bal = abalance $ atacct at | ||||||
|  |                 subaccts = (showAccountTreesWithBalances l (depth - 1)) $ branches at | ||||||
|  |                 boring = (length txns == 0) && ((length subaccts) == 1) | ||||||
|  | 
 | ||||||
|  | -- we want to elide boring accounts in the account tree | ||||||
|  | -- | ||||||
|  | -- a (2 txns) | ||||||
|  | --   b (boring acct - 0 txns, exactly 1 sub) | ||||||
|  | --     c (5 txns) | ||||||
|  | --       d | ||||||
|  | -- to: | ||||||
|  | -- a (2 txns) | ||||||
|  | --   b:c (5 txns) | ||||||
|  | --     d | ||||||
|  | 
 | ||||||
|  | -- elideAccountTree at = at | ||||||
|  | 
 | ||||||
|  | elideAccountTree :: Tree Account -> Tree Account | ||||||
|  | elideAccountTree = id | ||||||
|  | 
 | ||||||
|  | ledgerAccountTree :: Ledger -> Tree Account | ||||||
|  | ledgerAccountTree l = elideAccountTree $ addDataToAccountNameTree l (ledgerAccountNameTree l) | ||||||
|  | 
 | ||||||
|  | ledgerAccountsMatching :: Ledger -> [String] -> [Account] | ||||||
|  | ledgerAccountsMatching l acctpats = undefined | ||||||
|  | 
 | ||||||
|  | showLedgerAccounts :: Ledger -> Int -> String | ||||||
|  | showLedgerAccounts l depth =  | ||||||
|  |     showAccountTreeWithBalances l depth (ledgerAccountTree l) | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										88
									
								
								AccountName.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								AccountName.hs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | |||||||
|  | 
 | ||||||
|  | module AccountName | ||||||
|  | where | ||||||
|  | import Utils | ||||||
|  | import BasicTypes | ||||||
|  | 
 | ||||||
|  | -- AccountNames are strings like "assets:cash:petty"; from these we build | ||||||
|  | -- the chart of accounts, which should be a simple hierarchy.  | ||||||
|  | type AccountName = String | ||||||
|  | 
 | ||||||
|  | accountNameComponents :: AccountName -> [String] | ||||||
|  | accountNameComponents = splitAtElement ':' | ||||||
|  | 
 | ||||||
|  | accountNameFromComponents :: [String] -> AccountName | ||||||
|  | accountNameFromComponents = concat . intersperse ":" | ||||||
|  | 
 | ||||||
|  | accountLeafName :: AccountName -> String | ||||||
|  | accountLeafName = rhead . accountNameComponents | ||||||
|  | 
 | ||||||
|  | accountNameLevel :: AccountName -> Int | ||||||
|  | accountNameLevel = length . accountNameComponents | ||||||
|  | 
 | ||||||
|  | -- ["a:b:c","d:e"] -> ["a","a:b","a:b:c","d","d:e"] | ||||||
|  | expandAccountNames :: [AccountName] -> [AccountName] | ||||||
|  | expandAccountNames as = nub $ concat $ map expand as | ||||||
|  |     where expand as = map accountNameFromComponents (tail $ inits $ accountNameComponents as) | ||||||
|  | 
 | ||||||
|  | -- ["a:b:c","d:e"] -> ["a","d"] | ||||||
|  | topAccountNames :: [AccountName] -> [AccountName] | ||||||
|  | topAccountNames as = [a | a <- expandAccountNames as, accountNameLevel a == 1] | ||||||
|  | 
 | ||||||
|  | parentAccountName :: AccountName -> Maybe AccountName | ||||||
|  | parentAccountName a =  | ||||||
|  |     case accountNameLevel a > 1 of | ||||||
|  |       True -> Just $ accountNameFromComponents $ rtail $ accountNameComponents a | ||||||
|  |       False -> Nothing | ||||||
|  | 
 | ||||||
|  | s `isSubAccountNameOf` p =  | ||||||
|  |     ((p ++ ":") `isPrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1)) | ||||||
|  | 
 | ||||||
|  | subAccountNamesFrom :: [AccountName] -> AccountName -> [AccountName] | ||||||
|  | subAccountNamesFrom accts a = filter (`isSubAccountNameOf` a) accts | ||||||
|  | 
 | ||||||
|  | matchAccountName :: String -> AccountName -> Bool | ||||||
|  | matchAccountName s a = | ||||||
|  |     case matchRegex (mkRegex s) a of | ||||||
|  |       Nothing -> False | ||||||
|  |       otherwise -> True | ||||||
|  | 
 | ||||||
|  | indentAccountName :: AccountName -> String | ||||||
|  | indentAccountName a = replicate (((accountNameLevel a) - 1) * 2) ' ' ++ (accountLeafName a) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- We could almost get by with just the above, but we need smarter | ||||||
|  | -- structures to eg display the account tree with boring accounts elided. | ||||||
|  | -- first, here is a tree of AccountNames; Account and Account tree are | ||||||
|  | -- defined later. | ||||||
|  | 
 | ||||||
|  | antacctname = fst . node | ||||||
|  | 
 | ||||||
|  | accountNameTreeFrom_props = | ||||||
|  |     [ | ||||||
|  |      accountNameTreeFrom ["a"] == Tree ("top", [Tree ("a",[])]), | ||||||
|  |      accountNameTreeFrom ["a","b"] == Tree ("top", [Tree ("a", []), Tree ("b", [])]), | ||||||
|  |      accountNameTreeFrom ["a","a:b"] == Tree ("top", [Tree ("a", [Tree ("a:b", [])])]), | ||||||
|  |      accountNameTreeFrom ["a:b"] == Tree ("top", [Tree ("a", [Tree ("a:b", [])])]) | ||||||
|  |     ] | ||||||
|  | accountNameTreeFrom :: [AccountName] -> Tree AccountName | ||||||
|  | accountNameTreeFrom accts =  | ||||||
|  |     Tree ("top", accountsFrom (topAccountNames accts)) | ||||||
|  |         where | ||||||
|  |           accountsFrom :: [AccountName] -> [Tree AccountName] | ||||||
|  |           accountsFrom [] = [] | ||||||
|  |           accountsFrom as = [Tree (a, accountsFrom $ subs a) | a <- as] | ||||||
|  |           subs = (subAccountNamesFrom accts) | ||||||
|  | 
 | ||||||
|  | showAccountNameTree :: Tree AccountName -> String | ||||||
|  | showAccountNameTree at = showAccountNameTrees $ branches at | ||||||
|  | 
 | ||||||
|  | showAccountNameTrees :: [Tree AccountName] -> String | ||||||
|  | showAccountNameTrees ats = | ||||||
|  |     concatMap showAccountNameBranch ats | ||||||
|  |         where | ||||||
|  |           showAccountNameBranch at = topacct ++ "\n" ++ subaccts | ||||||
|  |               where | ||||||
|  |                 topacct = indentAccountName $ antacctname at | ||||||
|  |                 subaccts = showAccountNameTrees $ branches at | ||||||
|  | 
 | ||||||
| @ -7,10 +7,10 @@ import Entry | |||||||
| import Transaction | import Transaction | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| -- We parse Entries containing Transactions and flatten them into | -- We convert Transactions into EntryTransactions, which are (entry, | ||||||
| -- (entry,transaction) pairs (entrytransactions, hereafter referred to as | -- transaction) pairs, since I couldn't easily just have transactions | ||||||
| -- "transactions") for easier processing. (So far, these types have | -- reference their entry like in OO.  These are referred to as just | ||||||
| -- morphed through E->T; (T,E); ET; E<->T; (E,T)). | -- "transactions" hereafter. | ||||||
| 
 | 
 | ||||||
| type EntryTransaction = (Entry,Transaction) | type EntryTransaction = (Entry,Transaction) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| module Ledger | module Ledger | ||||||
| where | where | ||||||
| import Utils | import Utils | ||||||
| import Account | import AccountName | ||||||
| import BasicTypes | import BasicTypes | ||||||
| import Entry | import Entry | ||||||
| import EntryTransaction | import EntryTransaction | ||||||
|  | |||||||
							
								
								
									
										99
									
								
								Models.hs
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								Models.hs
									
									
									
									
									
								
							| @ -1,112 +1,21 @@ | |||||||
| -- data types & behaviours | -- data types & behaviours | ||||||
| module Models ( | module Models ( | ||||||
|                module Models, |                module Models, | ||||||
|  |                module Account, | ||||||
|                module Ledger, |                module Ledger, | ||||||
|                module EntryTransaction, |                module EntryTransaction, | ||||||
|                module Transaction, |                module Transaction, | ||||||
|                module Entry, |                module Entry, | ||||||
|                module Account, |                module AccountName, | ||||||
|                module BasicTypes, |                module BasicTypes, | ||||||
|               ) |               ) | ||||||
| where | where | ||||||
| import Utils | import Utils | ||||||
| import BasicTypes | import BasicTypes | ||||||
| import Account | import AccountName | ||||||
| import Entry | import Entry | ||||||
| import Transaction | import Transaction | ||||||
| import EntryTransaction | import EntryTransaction | ||||||
| import Ledger | import Ledger | ||||||
| 
 | import Account | ||||||
| 
 |  | ||||||
| -- top-level stuff that mixes types |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| -- an Account caches an account's name, balance and transactions for convenience |  | ||||||
| type Account = (AccountName,[EntryTransaction],Amount) |  | ||||||
| aname (a,_,_) = a |  | ||||||
| atxns (_,ts,_) = ts |  | ||||||
| abal (_,_,b) = b |  | ||||||
| 
 |  | ||||||
| mkAccount :: Ledger -> AccountName -> Account |  | ||||||
| mkAccount l a = (a, accountNameTransactionsNoSubs l a, accountNameBalance l a) |  | ||||||
| 
 |  | ||||||
| accountNameBalance :: Ledger -> AccountName -> Amount |  | ||||||
| accountNameBalance l a = sumEntryTransactions (accountNameTransactions l a) |  | ||||||
| 
 |  | ||||||
| accountNameTransactions :: Ledger -> AccountName -> [EntryTransaction] |  | ||||||
| accountNameTransactions l a = ledgerTransactionsMatching (["^" ++ a ++ "(:.+)?$"], []) l |  | ||||||
| 
 |  | ||||||
| accountNameBalanceNoSubs :: Ledger -> AccountName -> Amount |  | ||||||
| accountNameBalanceNoSubs l a = sumEntryTransactions (accountNameTransactionsNoSubs l a) |  | ||||||
| 
 |  | ||||||
| accountNameTransactionsNoSubs :: Ledger -> AccountName -> [EntryTransaction] |  | ||||||
| accountNameTransactionsNoSubs l a = ledgerTransactionsMatching (["^" ++ a ++ "$"], []) l |  | ||||||
| 
 |  | ||||||
| -- showAccountNamesWithBalances :: [(AccountName,String)] -> Ledger -> String |  | ||||||
| -- showAccountNamesWithBalances as l = |  | ||||||
| --     unlines $ map (showAccountNameAndBalance l) as |  | ||||||
| 
 |  | ||||||
| -- showAccountNameAndBalance :: Ledger -> (AccountName, String) -> String |  | ||||||
| -- showAccountNameAndBalance l (a, adisplay) = |  | ||||||
| --     printf "%20s  %s" (showBalance $ accountBalance l a) adisplay |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| -- a tree of Accounts |  | ||||||
| 
 |  | ||||||
| atacct = fst . node |  | ||||||
| 
 |  | ||||||
| addDataToAccountNameTree :: Ledger -> Tree AccountName -> Tree Account |  | ||||||
| addDataToAccountNameTree l ant =  |  | ||||||
|     Tree (mkAccount l aname, map (addDataToAccountNameTree l) (antsubs ant)) |  | ||||||
|         where  |  | ||||||
|           aname = antacctname ant |  | ||||||
| 
 |  | ||||||
| showAccountTreeWithBalances :: Ledger -> Int -> Tree Account -> String |  | ||||||
| showAccountTreeWithBalances l depth at = (showAccountTreesWithBalances l depth) (branches at) |  | ||||||
| 
 |  | ||||||
| showAccountTreesWithBalances :: Ledger -> Int -> [Tree Account] -> String |  | ||||||
| showAccountTreesWithBalances _ 0 _ = "" |  | ||||||
| showAccountTreesWithBalances l depth ats = |  | ||||||
|     concatMap showAccountBranch ats |  | ||||||
|         where |  | ||||||
|           showAccountBranch :: Tree Account -> String |  | ||||||
|           showAccountBranch at =  |  | ||||||
|               topacct ++ "\n" ++ subaccts |  | ||||||
| --               case boring of |  | ||||||
| --                 True  ->  |  | ||||||
| --                 False ->  |  | ||||||
|               where |  | ||||||
|                 topacct = (showAmount bal) ++ "  " ++ (indentAccountName name) |  | ||||||
|                 showAmount amt = printf "%20s" (show amt) |  | ||||||
|                 name = aname $ atacct at |  | ||||||
|                 txns = atxns $ atacct at |  | ||||||
|                 bal = abal $ atacct at |  | ||||||
|                 subaccts = (showAccountTreesWithBalances l (depth - 1)) $ branches at |  | ||||||
|                 boring = (length txns == 0) && ((length subaccts) == 1) |  | ||||||
| 
 |  | ||||||
| -- we want to elide boring accounts in the account tree |  | ||||||
| -- |  | ||||||
| -- a (2 txns) |  | ||||||
| --   b (boring acct - 0 txns, exactly 1 sub) |  | ||||||
| --     c (5 txns) |  | ||||||
| --       d |  | ||||||
| -- to: |  | ||||||
| -- a (2 txns) |  | ||||||
| --   b:c (5 txns) |  | ||||||
| --     d |  | ||||||
| 
 |  | ||||||
| -- elideAccountTree at = at |  | ||||||
| 
 |  | ||||||
| elideAccountTree :: Tree Account -> Tree Account |  | ||||||
| elideAccountTree = id |  | ||||||
| 
 |  | ||||||
| ledgerAccountTree :: Ledger -> Tree Account |  | ||||||
| ledgerAccountTree l = elideAccountTree $ addDataToAccountNameTree l (ledgerAccountNameTree l) |  | ||||||
| 
 |  | ||||||
| ledgerAccountsMatching :: Ledger -> [String] -> [Account] |  | ||||||
| ledgerAccountsMatching l acctpats = undefined |  | ||||||
| 
 |  | ||||||
| showLedgerAccounts :: Ledger -> Int -> String |  | ||||||
| showLedgerAccounts l depth =  |  | ||||||
|     showAccountTreeWithBalances l depth (ledgerAccountTree l) |  | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										32
									
								
								Options.hs
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								Options.hs
									
									
									
									
									
								
							| @ -51,3 +51,35 @@ getDepth opts = | |||||||
|     maximum $ [1] ++ map depthval opts where |     maximum $ [1] ++ map depthval opts where | ||||||
|         depthval (ShowSubs) = 9999 |         depthval (ShowSubs) = 9999 | ||||||
|         depthval _ = 1 |         depthval _ = 1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- example: | ||||||
|  | --     module Opts where | ||||||
|  |      | ||||||
|  | --     import System.Console.GetOpt | ||||||
|  | --     import Data.Maybe ( fromMaybe ) | ||||||
|  |      | ||||||
|  | --     data Flag  | ||||||
|  | --      = Verbose  | Version  | ||||||
|  | --      | Input String | Output String | LibDir String | ||||||
|  | --        deriving Show | ||||||
|  |      | ||||||
|  | --     options :: [OptDescr Flag] | ||||||
|  | --     options = | ||||||
|  | --      [ Option ['v']     ["verbose"] (NoArg Verbose)       "chatty output on stderr" | ||||||
|  | --      , Option ['V','?'] ["version"] (NoArg Version)       "show version number" | ||||||
|  | --      , Option ['o']     ["output"]  (OptArg outp "FILE")  "output FILE" | ||||||
|  | --      , Option ['c']     []          (OptArg inp  "FILE")  "input FILE" | ||||||
|  | --      , Option ['L']     ["libdir"]  (ReqArg LibDir "DIR") "library directory" | ||||||
|  | --      ] | ||||||
|  |      | ||||||
|  | --     inp,outp :: Maybe String -> Flag | ||||||
|  | --     outp = Output . fromMaybe "stdout" | ||||||
|  | --     inp  = Input  . fromMaybe "stdin" | ||||||
|  |      | ||||||
|  | --     compilerOpts :: [String] -> IO ([Flag], [String]) | ||||||
|  | --     compilerOpts argv =  | ||||||
|  | --        case getOpt Permute options argv of | ||||||
|  | --           (o,n,[]  ) -> return (o,n) | ||||||
|  | --           (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options)) | ||||||
|  | --       where header = "Usage: ic [OPTION...] files..." | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								TODO
									
									
									
									
									
								
							| @ -1,23 +1,10 @@ | |||||||
| cleanup/reorganize | cleanup/reorganize | ||||||
|  Entry/Transaction/EntryTransaction |  Entry/Transaction/EntryTransaction | ||||||
| 
 | 
 | ||||||
| hledger |  | ||||||
|  Options |  | ||||||
|  Tests |  | ||||||
|   Parse |  | ||||||
|    Models |  | ||||||
|     Ledger |  | ||||||
|      EntryTransaction |  | ||||||
|       Entry |  | ||||||
|        Transaction |  | ||||||
|         Account |  | ||||||
|         BasicTypes |  | ||||||
|          Utils |  | ||||||
| 
 |  | ||||||
| basic features | basic features | ||||||
|  |  handle mixed amounts and currencies | ||||||
|  balance |  balance | ||||||
|   elide boring accounts |   elide boring accounts | ||||||
|  handle mixed amounts and currencies |  | ||||||
|  print |  print | ||||||
|  entry |  entry | ||||||
|  -j and -J graph data output |  -j and -J graph data output | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ module Transaction | |||||||
| where | where | ||||||
| import Utils | import Utils | ||||||
| import BasicTypes | import BasicTypes | ||||||
| import Account | import AccountName | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| data Transaction = Transaction { | data Transaction = Transaction { | ||||||
| @ -22,15 +22,6 @@ elideRight width s = | |||||||
|       True -> take (width - 2) s ++ ".." |       True -> take (width - 2) s ++ ".." | ||||||
|       False -> s |       False -> s | ||||||
| 
 | 
 | ||||||
| -- elideAccountRight width abbrevlen a =  |  | ||||||
| --     case length a > width of |  | ||||||
| --       False -> a |  | ||||||
| --       True -> abbreviateAccountComponent abbrevlen a  |  | ||||||
|          |  | ||||||
| -- abbreviateAccountComponent abbrevlen a = |  | ||||||
| --     let components = splitAtElement ':' a in |  | ||||||
| --     case  |  | ||||||
|      |  | ||||||
| autofillTransactions :: [Transaction] -> [Transaction] | autofillTransactions :: [Transaction] -> [Transaction] | ||||||
| autofillTransactions ts = | autofillTransactions ts = | ||||||
|     let (ns, as) = partition isNormal ts |     let (ns, as) = partition isNormal ts | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								hledger.hs
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								hledger.hs
									
									
									
									
									
								
							| @ -1,7 +1,26 @@ | |||||||
| #!/usr/bin/env runhaskell | #!/usr/bin/env runhaskell | ||||||
| -- hledger - ledger-compatible money management utilities (& haskell study) | {- | ||||||
| -- GPLv3, (c) Simon Michael & contributors,  | hledger - ledger-compatible money management utilities (& haskell study) | ||||||
| -- John Wiegley's ledger is at http://newartisans.com/ledger.html | GPLv3, (c) Simon Michael & contributors,  | ||||||
|  | John Wiegley's ledger is at http://newartisans.com/ledger.html | ||||||
|  | 
 | ||||||
|  | The model/type/class hierarchy is roughly like this: | ||||||
|  | 
 | ||||||
|  | hledger | ||||||
|  |  Options | ||||||
|  |  Tests | ||||||
|  |   Parse | ||||||
|  |    Models | ||||||
|  |     Account | ||||||
|  |      Ledger | ||||||
|  |       EntryTransaction | ||||||
|  |        Entry | ||||||
|  |         Transaction | ||||||
|  |          AccountName | ||||||
|  |          BasicTypes | ||||||
|  |           Utils | ||||||
|  | 
 | ||||||
|  | -} | ||||||
| 
 | 
 | ||||||
| -- application logic & most IO | -- application logic & most IO | ||||||
| module Main | module Main | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user