strip trailing whitespace from all Haskell files
This commit is contained in:
		
							parent
							
								
									22279978af
								
							
						
					
					
						commit
						d1618aaca8
					
				| @ -9,7 +9,7 @@ import Hledger.Cli | |||||||
| import Text.CSV | import Text.CSV | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| argsmode =  | argsmode = | ||||||
|   (defCommandMode ["balance-csv"]) { |   (defCommandMode ["balance-csv"]) { | ||||||
|      modeHelp = "show matched postings accounts and their balances as CSV" |      modeHelp = "show matched postings accounts and their balances as CSV" | ||||||
|     ,modeGroupFlags = Group { |     ,modeGroupFlags = Group { | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ main = do | |||||||
|   opts <- getCliOpts (defCommandMode ["hledger-print-unique"]) |   opts <- getCliOpts (defCommandMode ["hledger-print-unique"]) | ||||||
|   withJournalDo opts $ |   withJournalDo opts $ | ||||||
|     \opts j@Journal{jtxns=ts} -> print' opts j{jtxns=uniquify ts} |     \opts j@Journal{jtxns=ts} -> print' opts j{jtxns=uniquify ts} | ||||||
|     where  |     where | ||||||
|       uniquify = nubBy (\t1 t2 -> thingToCompare t1 == thingToCompare t2) . sortBy (comparing thingToCompare) |       uniquify = nubBy (\t1 t2 -> thingToCompare t1 == thingToCompare t2) . sortBy (comparing thingToCompare) | ||||||
|       thingToCompare = tdescription |       thingToCompare = tdescription | ||||||
|       -- thingToCompare = tdate |       -- thingToCompare = tdate | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ cmdmode = (defCommandMode ["hledger-rewrite"]) { | |||||||
|                   ,("Reporting", reportflags) |                   ,("Reporting", reportflags) | ||||||
|                   ,("Misc",      helpflags) |                   ,("Misc",      helpflags) | ||||||
|                  ] |                  ] | ||||||
|     ,groupUnnamed = [flagReq ["add-posting"] (\s opts -> Right $ setopt "add-posting" s opts) "'ACCT  AMTEXPR'"  |     ,groupUnnamed = [flagReq ["add-posting"] (\s opts -> Right $ setopt "add-posting" s opts) "'ACCT  AMTEXPR'" | ||||||
|                      "add a posting to ACCT, which may be parenthesised. AMTEXPR is either a literal amount, or *N which means the transaction's first matched amount multiplied by N (a decimal number). Two spaces separate ACCT and AMTEXPR."] |                      "add a posting to ACCT, which may be parenthesised. AMTEXPR is either a literal amount, or *N which means the transaction's first matched amount multiplied by N (a decimal number). Two spaces separate ACCT and AMTEXPR."] | ||||||
|     ,groupHidden = [] |     ,groupHidden = [] | ||||||
|     } |     } | ||||||
| @ -66,7 +66,7 @@ amountexprp = | |||||||
| 
 | 
 | ||||||
| amountExprRenderer :: Query -> AmountExpr -> (Transaction -> MixedAmount) | amountExprRenderer :: Query -> AmountExpr -> (Transaction -> MixedAmount) | ||||||
| amountExprRenderer q aex = | amountExprRenderer q aex = | ||||||
|   case aex of  |   case aex of | ||||||
|     AmountLiteral s    -> either parseerror (const . mixed) $ parseWithCtx nullctx amountp s |     AmountLiteral s    -> either parseerror (const . mixed) $ parseWithCtx nullctx amountp s | ||||||
|     AmountMultiplier n -> (`divideMixedAmount` (1 / n)) . (`firstAmountMatching` q) |     AmountMultiplier n -> (`divideMixedAmount` (1 / n)) . (`firstAmountMatching` q) | ||||||
|   where |   where | ||||||
| @ -93,4 +93,4 @@ main = do | |||||||
|     let j' = j{jtxns=map (\t -> if q `matchesTransaction` t then rewriteTransaction t addps else t) ts} |     let j' = j{jtxns=map (\t -> if q `matchesTransaction` t then rewriteTransaction t addps else t) ts} | ||||||
|     -- run the print command, showing all transactions |     -- run the print command, showing all transactions | ||||||
|     print' opts{reportopts_=ropts{query_=""}} j' |     print' opts{reportopts_=ropts{query_=""}} j' | ||||||
|        | 
 | ||||||
|  | |||||||
| @ -93,7 +93,7 @@ vty opts j = do | |||||||
|                  ,abuf=[] |                  ,abuf=[] | ||||||
|                  ,alocs=[] |                  ,alocs=[] | ||||||
|                  } |                  } | ||||||
|   go a  |   go a | ||||||
| 
 | 
 | ||||||
| -- | Update the screen, wait for the next event, repeat. | -- | Update the screen, wait for the next event, repeat. | ||||||
| go :: AppState -> IO () | go :: AppState -> IO () | ||||||
| @ -101,7 +101,7 @@ go a@AppState{av=av,aopts=opts} = do | |||||||
|   when (not $ debug_vty_ opts) $ update av (renderScreen a) |   when (not $ debug_vty_ opts) $ update av (renderScreen a) | ||||||
|   k <- next_event av |   k <- next_event av | ||||||
|   d <- getCurrentDay |   d <- getCurrentDay | ||||||
|   case k of  |   case k of | ||||||
|     EvResize x y                -> go $ resize x y a |     EvResize x y                -> go $ resize x y a | ||||||
|     EvKey (KASCII 'l') [MCtrl]  -> refresh av >> go a{amsg=helpmsg} |     EvKey (KASCII 'l') [MCtrl]  -> refresh av >> go a{amsg=helpmsg} | ||||||
|     EvKey (KASCII 'b') []       -> go $ resetTrailAndEnter d BalanceScreen a |     EvKey (KASCII 'b') []       -> go $ resetTrailAndEnter d BalanceScreen a | ||||||
| @ -151,7 +151,7 @@ setScrollY y a@AppState{alocs=(l:locs)} = a{alocs=(l':locs)} where l' = setLocSc | |||||||
| 
 | 
 | ||||||
| setPosY _ AppState{alocs=[]}    = error' "shouldn't happen" -- silence warnings | setPosY _ AppState{alocs=[]}    = error' "shouldn't happen" -- silence warnings | ||||||
| setPosY y a@AppState{alocs=(l:locs)} = a{alocs=(l':locs)} | setPosY y a@AppState{alocs=(l:locs)} = a{alocs=(l':locs)} | ||||||
|     where  |     where | ||||||
|       l' = setLocScrollY sy $ setLocCursorY cy l |       l' = setLocScrollY sy $ setLocCursorY cy l | ||||||
|       ph = pageHeight a |       ph = pageHeight a | ||||||
|       cy = y `mod` ph |       cy = y `mod` ph | ||||||
| @ -186,7 +186,7 @@ moveDownAndPushEdge a | |||||||
|     | sy+cy >= bh = a |     | sy+cy >= bh = a | ||||||
|     | cy < ph-1 = updateCursorY (+1) a |     | cy < ph-1 = updateCursorY (+1) a | ||||||
|     | otherwise = updateScrollY (+1) a |     | otherwise = updateScrollY (+1) a | ||||||
|     where  |     where | ||||||
|       Loc{sy=sy,cy=cy} = head $ alocs a |       Loc{sy=sy,cy=cy} = head $ alocs a | ||||||
|       ph = pageHeight a |       ph = pageHeight a | ||||||
|       bh = length $ abuf a |       bh = length $ abuf a | ||||||
| @ -332,7 +332,7 @@ renderScreen (a@AppState{aw=w,ah=h,abuf=buf,amsg=msg}) = | |||||||
|                          renderStatus w msg |                          renderStatus w msg | ||||||
|             ,pic_background = Background ' ' def_attr |             ,pic_background = Background ' ' def_attr | ||||||
|             } |             } | ||||||
|     where  |     where | ||||||
|       (cx, cy) = (0, cursorY a) |       (cx, cy) = (0, cursorY a) | ||||||
|       sy = scrollY a |       sy = scrollY a | ||||||
| --       mainimg = (renderString attr $ unlines $ above) | --       mainimg = (renderString attr $ unlines $ above) | ||||||
| @ -381,8 +381,8 @@ theme = Restrained | |||||||
| 
 | 
 | ||||||
| data UITheme = Restrained | Colorful | Blood | data UITheme = Restrained | Colorful | Blood | ||||||
| 
 | 
 | ||||||
| (defaultattr,  | (defaultattr, | ||||||
|  currentlineattr,  |  currentlineattr, | ||||||
|  statusattr |  statusattr | ||||||
|  ) = case theme of |  ) = case theme of | ||||||
|        Restrained -> (def_attr |        Restrained -> (def_attr | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| {-|  | {-| | ||||||
| 
 | 
 | ||||||
| The Hledger.Data library allows parsing and querying of C++ ledger-style | The Hledger.Data library allows parsing and querying of C++ ledger-style | ||||||
| journal files.  It generally provides a compatible subset of C++ ledger's | journal files.  It generally provides a compatible subset of C++ ledger's | ||||||
|  | |||||||
| @ -115,7 +115,7 @@ sumAccounts a | |||||||
| 
 | 
 | ||||||
| -- | Remove all subaccounts below a certain depth. | -- | Remove all subaccounts below a certain depth. | ||||||
| clipAccounts :: Int -> Account -> Account | clipAccounts :: Int -> Account -> Account | ||||||
| clipAccounts 0 a = a{asubs=[]}  | clipAccounts 0 a = a{asubs=[]} | ||||||
| clipAccounts d a = a{asubs=subs} | clipAccounts d a = a{asubs=subs} | ||||||
|     where |     where | ||||||
|       subs = map (clipAccounts (d-1)) $ asubs a |       subs = map (clipAccounts (d-1)) $ asubs a | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ isAccountNamePrefixOf :: AccountName -> AccountName -> Bool | |||||||
| isAccountNamePrefixOf = isPrefixOf . (++ [acctsepchar]) | isAccountNamePrefixOf = isPrefixOf . (++ [acctsepchar]) | ||||||
| 
 | 
 | ||||||
| isSubAccountNameOf :: AccountName -> AccountName -> Bool | isSubAccountNameOf :: AccountName -> AccountName -> Bool | ||||||
| s `isSubAccountNameOf` p =  | s `isSubAccountNameOf` p = | ||||||
|     (p `isAccountNamePrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1)) |     (p `isAccountNamePrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1)) | ||||||
| 
 | 
 | ||||||
| -- | From a list of account names, select those which are direct | -- | From a list of account names, select those which are direct | ||||||
| @ -73,7 +73,7 @@ subAccountNamesFrom accts a = filter (`isSubAccountNameOf` a) accts | |||||||
| 
 | 
 | ||||||
| -- | Convert a list of account names to a tree. | -- | Convert a list of account names to a tree. | ||||||
| accountNameTreeFrom :: [AccountName] -> Tree AccountName | accountNameTreeFrom :: [AccountName] -> Tree AccountName | ||||||
| accountNameTreeFrom accts =  | accountNameTreeFrom accts = | ||||||
|     Node "root" (accounttreesfrom (topAccountNames accts)) |     Node "root" (accounttreesfrom (topAccountNames accts)) | ||||||
|         where |         where | ||||||
|           accounttreesfrom :: [AccountName] -> [Tree AccountName] |           accounttreesfrom :: [AccountName] -> [Tree AccountName] | ||||||
| @ -85,7 +85,7 @@ nullaccountnametree = Node "root" [] | |||||||
| 
 | 
 | ||||||
| -- | Elide an account name to fit in the specified width. | -- | Elide an account name to fit in the specified width. | ||||||
| -- From the ledger 2.6 news: | -- From the ledger 2.6 news: | ||||||
| --  | -- | ||||||
| -- @ | -- @ | ||||||
| --   What Ledger now does is that if an account name is too long, it will | --   What Ledger now does is that if an account name is too long, it will | ||||||
| --   start abbreviating the first parts of the account name down to two | --   start abbreviating the first parts of the account name down to two | ||||||
| @ -99,7 +99,7 @@ nullaccountnametree = Node "root" [] | |||||||
| --     ..:Af:Lu:Sn:Ca:Ch:Cash  ; Abbreviated and elided! | --     ..:Af:Lu:Sn:Ca:Ch:Cash  ; Abbreviated and elided! | ||||||
| -- @ | -- @ | ||||||
| elideAccountName :: Int -> AccountName -> AccountName | elideAccountName :: Int -> AccountName -> AccountName | ||||||
| elideAccountName width s =  | elideAccountName width s = | ||||||
|     elideLeft width $ accountNameFromComponents $ elideparts width [] $ accountNameComponents s |     elideLeft width $ accountNameFromComponents $ elideparts width [] $ accountNameComponents s | ||||||
|       where |       where | ||||||
|         elideparts :: Int -> [String] -> [String] -> [String] |         elideparts :: Int -> [String] -> [String] -> [String] | ||||||
|  | |||||||
| @ -4,13 +4,13 @@ A simple 'Amount' is some quantity of money, shares, or anything else. | |||||||
| It has a (possibly null) 'Commodity' and a numeric quantity: | It has a (possibly null) 'Commodity' and a numeric quantity: | ||||||
| 
 | 
 | ||||||
| @ | @ | ||||||
|   $1  |   $1 | ||||||
|   £-50 |   £-50 | ||||||
|   EUR 3.44  |   EUR 3.44 | ||||||
|   GOOG 500 |   GOOG 500 | ||||||
|   1.5h |   1.5h | ||||||
|   90 apples |   90 apples | ||||||
|   0  |   0 | ||||||
| @ | @ | ||||||
| 
 | 
 | ||||||
| It may also have an assigned 'Price', representing this amount's per-unit | It may also have an assigned 'Price', representing this amount's per-unit | ||||||
| @ -166,7 +166,7 @@ similarAmountsOp op Amount{acommodity=_,  aquantity=q1, astyle=AmountStyle{aspre | |||||||
|                     Amount{acommodity=c2, aquantity=q2, astyle=s2@AmountStyle{asprecision=p2}} = |                     Amount{acommodity=c2, aquantity=q2, astyle=s2@AmountStyle{asprecision=p2}} = | ||||||
|    -- trace ("a1:"++showAmountDebug a1) $ trace ("a2:"++showAmountDebug a2) $ traceWith (("= :"++).showAmountDebug) |    -- trace ("a1:"++showAmountDebug a1) $ trace ("a2:"++showAmountDebug a2) $ traceWith (("= :"++).showAmountDebug) | ||||||
|    amount{acommodity=c2, aquantity=q1 `op` q2, astyle=s2{asprecision=max p1 p2}} |    amount{acommodity=c2, aquantity=q1 `op` q2, astyle=s2{asprecision=max p1 p2}} | ||||||
|   --  c1==c2 || q1==0 || q2==0 =  |   --  c1==c2 || q1==0 || q2==0 = | ||||||
|   --  otherwise = error "tried to do simple arithmetic with amounts in different commodities" |   --  otherwise = error "tried to do simple arithmetic with amounts in different commodities" | ||||||
| 
 | 
 | ||||||
| -- | Convert an amount to the specified commodity, ignoring and discarding | -- | Convert an amount to the specified commodity, ignoring and discarding | ||||||
| @ -605,7 +605,7 @@ tests_Hledger_Data_Amount = TestList $ | |||||||
|              ,usd (-0.25) |              ,usd (-0.25) | ||||||
|              ]) |              ]) | ||||||
|       `is` Mixed [usd 0 `withPrecision` 0] |       `is` Mixed [usd 0 `withPrecision` 0] | ||||||
|    | 
 | ||||||
|   ,"adding mixed amounts with total prices" ~: do |   ,"adding mixed amounts with total prices" ~: do | ||||||
|     (sum $ map (Mixed . (:[])) |     (sum $ map (Mixed . (:[])) | ||||||
|      [usd 1 @@ eur 1 |      [usd 1 @@ eur 1 | ||||||
|  | |||||||
| @ -43,8 +43,8 @@ commoditysymbols = | |||||||
| 
 | 
 | ||||||
| -- | Look up one of the sample commodities' symbol by name. | -- | Look up one of the sample commodities' symbol by name. | ||||||
| comm :: String -> Commodity | comm :: String -> Commodity | ||||||
| comm name = snd $ fromMaybe  | comm name = snd $ fromMaybe | ||||||
|               (error' "commodity lookup failed")  |               (error' "commodity lookup failed") | ||||||
|               (find (\n -> fst n == name) commoditysymbols) |               (find (\n -> fst n == name) commoditysymbols) | ||||||
| 
 | 
 | ||||||
| -- | Find the conversion rate between two commodities. Currently returns 1. | -- | Find the conversion rate between two commodities. Currently returns 1. | ||||||
|  | |||||||
| @ -153,7 +153,7 @@ spanStart (DateSpan d _) = d | |||||||
| spanEnd :: DateSpan -> Maybe Day | spanEnd :: DateSpan -> Maybe Day | ||||||
| spanEnd (DateSpan _ d) = d | spanEnd (DateSpan _ d) = d | ||||||
| 
 | 
 | ||||||
| -- might be useful later: http://en.wikipedia.org/wiki/Allen%27s_interval_algebra  | -- might be useful later: http://en.wikipedia.org/wiki/Allen%27s_interval_algebra | ||||||
| 
 | 
 | ||||||
| -- | Get overall span enclosing multiple sequentially ordered spans. | -- | Get overall span enclosing multiple sequentially ordered spans. | ||||||
| spansSpan :: [DateSpan] -> DateSpan | spansSpan :: [DateSpan] -> DateSpan | ||||||
| @ -204,7 +204,7 @@ spanContainsDate (DateSpan Nothing Nothing)   _ = True | |||||||
| spanContainsDate (DateSpan Nothing (Just e))  d = d < e | spanContainsDate (DateSpan Nothing (Just e))  d = d < e | ||||||
| spanContainsDate (DateSpan (Just b) Nothing)  d = d >= b | spanContainsDate (DateSpan (Just b) Nothing)  d = d >= b | ||||||
| spanContainsDate (DateSpan (Just b) (Just e)) d = d >= b && d < e | spanContainsDate (DateSpan (Just b) (Just e)) d = d >= b && d < e | ||||||
|      | 
 | ||||||
| -- | Calculate the intersection of a number of datespans. | -- | Calculate the intersection of a number of datespans. | ||||||
| spansIntersect [] = nulldatespan | spansIntersect [] = nulldatespan | ||||||
| spansIntersect [d] = d | spansIntersect [d] = d | ||||||
| @ -255,7 +255,7 @@ maybePeriod refdate = either (const Nothing) Just . parsePeriodExpr refdate | |||||||
| -- dateSpanAsText (DateSpan Nothing (Just e))  = printf "to %s" (show e) | -- dateSpanAsText (DateSpan Nothing (Just e))  = printf "to %s" (show e) | ||||||
| -- dateSpanAsText (DateSpan (Just b) Nothing)  = printf "from %s" (show b) | -- dateSpanAsText (DateSpan (Just b) Nothing)  = printf "from %s" (show b) | ||||||
| -- dateSpanAsText (DateSpan (Just b) (Just e)) = printf "%s to %s" (show b) (show e) | -- dateSpanAsText (DateSpan (Just b) (Just e)) = printf "%s to %s" (show b) (show e) | ||||||
|      | 
 | ||||||
| -- | Convert a single smart date string to a date span using the provided | -- | Convert a single smart date string to a date span using the provided | ||||||
| -- reference date, or raise an error. | -- reference date, or raise an error. | ||||||
| -- spanFromSmartDateString :: Day -> String -> DateSpan | -- spanFromSmartDateString :: Day -> String -> DateSpan | ||||||
| @ -400,9 +400,9 @@ nthdayofweekcontaining n d | d1 >= d    = d1 | |||||||
| 
 | 
 | ||||||
| -- | Parse a couple of date string formats to a time type. | -- | Parse a couple of date string formats to a time type. | ||||||
| parsedateM :: String -> Maybe Day | parsedateM :: String -> Maybe Day | ||||||
| parsedateM s = firstJust [  | parsedateM s = firstJust [ | ||||||
|      parseTime defaultTimeLocale "%Y/%m/%d" s, |      parseTime defaultTimeLocale "%Y/%m/%d" s, | ||||||
|      parseTime defaultTimeLocale "%Y-%m-%d" s  |      parseTime defaultTimeLocale "%Y-%m-%d" s | ||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
| -- -- | Parse a date-time string to a time type, or raise an error. | -- -- | Parse a date-time string to a time type, or raise an error. | ||||||
| @ -420,7 +420,7 @@ parsedate s =  fromMaybe (error' $ "could not parse date \"" ++ s ++ "\"") | |||||||
| parsetimewith :: ParseTime t => String -> String -> t -> t | parsetimewith :: ParseTime t => String -> String -> t -> t | ||||||
| parsetimewith pat s def = fromMaybe def $ parseTime defaultTimeLocale pat s | parsetimewith pat s def = fromMaybe def $ parseTime defaultTimeLocale pat s | ||||||
| 
 | 
 | ||||||
| {-|  | {-| | ||||||
| Parse a date in any of the formats allowed in ledger's period expressions, | Parse a date in any of the formats allowed in ledger's period expressions, | ||||||
| and maybe some others: | and maybe some others: | ||||||
| 
 | 
 | ||||||
| @ -557,7 +557,7 @@ lastthisnextthing = do | |||||||
|       ] |       ] | ||||||
| -- XXX support these in fixSmartDate | -- XXX support these in fixSmartDate | ||||||
| --       ++ (map string $ months ++ monthabbrevs ++ weekdays ++ weekdayabbrevs) | --       ++ (map string $ months ++ monthabbrevs ++ weekdays ++ weekdayabbrevs) | ||||||
|              | 
 | ||||||
|   return ("",r,p) |   return ("",r,p) | ||||||
| 
 | 
 | ||||||
| periodexpr :: Day -> GenParser Char st (Interval, DateSpan) | periodexpr :: Day -> GenParser Char st (Interval, DateSpan) | ||||||
|  | |||||||
| @ -463,7 +463,7 @@ splitAssertions ps | |||||||
|   | otherwise = (ps'++[head rest]):splitAssertions (tail rest) |   | otherwise = (ps'++[head rest]):splitAssertions (tail rest) | ||||||
|   where |   where | ||||||
|     (ps',rest) = break (isJust . pbalanceassertion) ps |     (ps',rest) = break (isJust . pbalanceassertion) ps | ||||||
|      | 
 | ||||||
| -- | Fill in any missing amounts and check that all journal transactions | -- | Fill in any missing amounts and check that all journal transactions | ||||||
| -- balance, or return an error message. This is done after parsing all | -- balance, or return an error message. This is done after parsing all | ||||||
| -- amounts and working out the canonical commodities, since balancing | -- amounts and working out the canonical commodities, since balancing | ||||||
| @ -654,7 +654,7 @@ abspat pat = if isnegativepat pat then drop (length negateprefix) pat else pat | |||||||
| --     liabilities:debts  $1 | --     liabilities:debts  $1 | ||||||
| --     assets:bank:checking | --     assets:bank:checking | ||||||
| -- | -- | ||||||
| Right samplejournal = journalBalanceTransactions $  | Right samplejournal = journalBalanceTransactions $ | ||||||
|          nulljournal |          nulljournal | ||||||
|          {jtxns = [ |          {jtxns = [ | ||||||
|            txnTieKnot $ Transaction { |            txnTieKnot $ Transaction { | ||||||
|  | |||||||
| @ -122,7 +122,7 @@ sumPostings = sum . map pamount | |||||||
| -- there is no parent transaction. | -- there is no parent transaction. | ||||||
| postingDate :: Posting -> Day | postingDate :: Posting -> Day | ||||||
| postingDate p = fromMaybe txndate $ pdate p | postingDate p = fromMaybe txndate $ pdate p | ||||||
|     where  |     where | ||||||
|       txndate = maybe nulldate tdate $ ptransaction p |       txndate = maybe nulldate tdate $ ptransaction p | ||||||
| 
 | 
 | ||||||
| -- | Get a posting's secondary (secondary) date, which is the first of: | -- | Get a posting's secondary (secondary) date, which is the first of: | ||||||
| @ -251,4 +251,4 @@ tests_Hledger_Data_Posting = TestList [ | |||||||
|     concatAccountNames ["a","(b)","[c:d]"] `is` "(a:b:c:d)" |     concatAccountNames ["a","(b)","[c:d]"] `is` "(a:b:c:d)" | ||||||
| 
 | 
 | ||||||
|  ] |  ] | ||||||
|   | 
 | ||||||
|  | |||||||
| @ -24,17 +24,17 @@ import Hledger.Data.Amount | |||||||
| import Hledger.Data.Posting | import Hledger.Data.Posting | ||||||
| import Hledger.Data.Transaction | import Hledger.Data.Transaction | ||||||
| 
 | 
 | ||||||
| instance Show TimeLogEntry where  | instance Show TimeLogEntry where | ||||||
|     show t = printf "%s %s %s" (show $ tlcode t) (show $ tldatetime t) (tlcomment t) |     show t = printf "%s %s %s" (show $ tlcode t) (show $ tldatetime t) (tlcomment t) | ||||||
| 
 | 
 | ||||||
| instance Show TimeLogCode where  | instance Show TimeLogCode where | ||||||
|     show SetBalance = "b" |     show SetBalance = "b" | ||||||
|     show SetRequiredHours = "h" |     show SetRequiredHours = "h" | ||||||
|     show In = "i" |     show In = "i" | ||||||
|     show Out = "o" |     show Out = "o" | ||||||
|     show FinalOut = "O" |     show FinalOut = "O" | ||||||
| 
 | 
 | ||||||
| instance Read TimeLogCode where  | instance Read TimeLogCode where | ||||||
|     readsPrec _ ('b' : xs) = [(SetBalance, xs)] |     readsPrec _ ('b' : xs) = [(SetBalance, xs)] | ||||||
|     readsPrec _ ('h' : xs) = [(SetRequiredHours, xs)] |     readsPrec _ ('h' : xs) = [(SetRequiredHours, xs)] | ||||||
|     readsPrec _ ('i' : xs) = [(In, xs)] |     readsPrec _ ('i' : xs) = [(In, xs)] | ||||||
| @ -72,7 +72,7 @@ timeLogEntriesToTransactions now (i:o:rest) | |||||||
| entryFromTimeLogInOut :: TimeLogEntry -> TimeLogEntry -> Transaction | entryFromTimeLogInOut :: TimeLogEntry -> TimeLogEntry -> Transaction | ||||||
| entryFromTimeLogInOut i o | entryFromTimeLogInOut i o | ||||||
|     | otime >= itime = t |     | otime >= itime = t | ||||||
|     | otherwise =  |     | otherwise = | ||||||
|         error' $ "clock-out time less than clock-in time in:\n" ++ showTransaction t |         error' $ "clock-out time less than clock-in time in:\n" ++ showTransaction t | ||||||
|     where |     where | ||||||
|       t = Transaction { |       t = Transaction { | ||||||
| @ -119,8 +119,8 @@ tests_Hledger_Data_TimeLog = TestList [ | |||||||
|      assertEntriesGiveStrings "split multi-day sessions at each midnight" |      assertEntriesGiveStrings "split multi-day sessions at each midnight" | ||||||
|                                   [clockin (mktime (addDays (-2) today) "23:00:00") ""] |                                   [clockin (mktime (addDays (-2) today) "23:00:00") ""] | ||||||
|                                   ["23:00-23:59","00:00-23:59","00:00-"++nowstr] |                                   ["23:00-23:59","00:00-23:59","00:00-"++nowstr] | ||||||
|      assertEntriesGiveStrings "auto-clock-out if needed"  |      assertEntriesGiveStrings "auto-clock-out if needed" | ||||||
|                                   [clockin (mktime today "00:00:00") ""]  |                                   [clockin (mktime today "00:00:00") ""] | ||||||
|                                   ["00:00-"++nowstr] |                                   ["00:00-"++nowstr] | ||||||
|      let future = utcToLocalTime tz $ addUTCTime 100 now' |      let future = utcToLocalTime tz $ addUTCTime 100 now' | ||||||
|          futurestr = showtime future |          futurestr = showtime future | ||||||
|  | |||||||
| @ -50,10 +50,10 @@ import Hledger.Data.Amount | |||||||
| 
 | 
 | ||||||
| instance Show Transaction where show = showTransactionUnelided | instance Show Transaction where show = showTransactionUnelided | ||||||
| 
 | 
 | ||||||
| instance Show ModifierTransaction where  | instance Show ModifierTransaction where | ||||||
|     show t = "= " ++ mtvalueexpr t ++ "\n" ++ unlines (map show (mtpostings t)) |     show t = "= " ++ mtvalueexpr t ++ "\n" ++ unlines (map show (mtpostings t)) | ||||||
| 
 | 
 | ||||||
| instance Show PeriodicTransaction where  | instance Show PeriodicTransaction where | ||||||
|     show t = "~ " ++ ptperiodicexpr t ++ "\n" ++ unlines (map show (ptpostings t)) |     show t = "~ " ++ ptperiodicexpr t ++ "\n" ++ unlines (map show (ptpostings t)) | ||||||
| 
 | 
 | ||||||
| nullsourcepos :: SourcePos | nullsourcepos :: SourcePos | ||||||
| @ -64,9 +64,9 @@ nulltransaction = Transaction { | |||||||
|                     tsourcepos=nullsourcepos, |                     tsourcepos=nullsourcepos, | ||||||
|                     tdate=nulldate, |                     tdate=nulldate, | ||||||
|                     tdate2=Nothing, |                     tdate2=Nothing, | ||||||
|                     tstatus=False,  |                     tstatus=False, | ||||||
|                     tcode="",  |                     tcode="", | ||||||
|                     tdescription="",  |                     tdescription="", | ||||||
|                     tcomment="", |                     tcomment="", | ||||||
|                     ttags=[], |                     ttags=[], | ||||||
|                     tpostings=[], |                     tpostings=[], | ||||||
| @ -286,7 +286,7 @@ balanceTransaction styles t@Transaction{tpostings=ps} | |||||||
|       ramounts  = map pamount rwithamounts |       ramounts  = map pamount rwithamounts | ||||||
|       bvamounts = map pamount bvwithamounts |       bvamounts = map pamount bvwithamounts | ||||||
|       t' = t{tpostings=map inferamount ps} |       t' = t{tpostings=map inferamount ps} | ||||||
|           where  |           where | ||||||
|             inferamount p | not (hasAmount p) && isReal p            = p{pamount = costOfMixedAmount (- sum ramounts)} |             inferamount p | not (hasAmount p) && isReal p            = p{pamount = costOfMixedAmount (- sum ramounts)} | ||||||
|                           | not (hasAmount p) && isBalancedVirtual p = p{pamount = costOfMixedAmount (- sum bvamounts)} |                           | not (hasAmount p) && isBalancedVirtual p = p{pamount = costOfMixedAmount (- sum bvamounts)} | ||||||
|                           | otherwise                             = p |                           | otherwise                             = p | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ type AccountName = String | |||||||
| data Side = L | R deriving (Eq,Show,Read,Ord,Typeable,Data) | data Side = L | R deriving (Eq,Show,Read,Ord,Typeable,Data) | ||||||
| 
 | 
 | ||||||
| type Commodity = String | type Commodity = String | ||||||
|        | 
 | ||||||
| type Quantity = Double | type Quantity = Double | ||||||
| 
 | 
 | ||||||
| -- | An amount's price (none, per unit, or total) in another commodity. | -- | An amount's price (none, per unit, or total) in another commodity. | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| {-# LANGUAGE ScopedTypeVariables #-} | {-# LANGUAGE ScopedTypeVariables #-} | ||||||
| {-|  | {-| | ||||||
| 
 | 
 | ||||||
| This is the entry point to hledger's reading system, which can read | This is the entry point to hledger's reading system, which can read | ||||||
| Journals from various data formats. Use this module if you want to parse | Journals from various data formats. Use this module if you want to parse | ||||||
| @ -138,7 +138,7 @@ readJournal format rulesfile assrt path s = | |||||||
| readersFor :: (Maybe StorageFormat, Maybe FilePath, String) -> [Reader] | readersFor :: (Maybe StorageFormat, Maybe FilePath, String) -> [Reader] | ||||||
| readersFor (format,path,s) = | readersFor (format,path,s) = | ||||||
|     dbg ("possible readers for "++show (format,path,elideRight 30 s)) $ |     dbg ("possible readers for "++show (format,path,elideRight 30 s)) $ | ||||||
|     case format of  |     case format of | ||||||
|      Just f  -> case readerForStorageFormat f of Just r  -> [r] |      Just f  -> case readerForStorageFormat f of Just r  -> [r] | ||||||
|                                                  Nothing -> [] |                                                  Nothing -> [] | ||||||
|      Nothing -> case path of Nothing  -> readers |      Nothing -> case path of Nothing  -> readers | ||||||
| @ -149,7 +149,7 @@ readersFor (format,path,s) = | |||||||
| readerForStorageFormat :: StorageFormat -> Maybe Reader | readerForStorageFormat :: StorageFormat -> Maybe Reader | ||||||
| readerForStorageFormat s | null rs = Nothing | readerForStorageFormat s | null rs = Nothing | ||||||
|                   | otherwise = Just $ head rs |                   | otherwise = Just $ head rs | ||||||
|     where  |     where | ||||||
|       rs = filter ((s==).rFormat) readers :: [Reader] |       rs = filter ((s==).rFormat) readers :: [Reader] | ||||||
| 
 | 
 | ||||||
| -- | Find the readers which think they can handle the given file path and data, if any. | -- | Find the readers which think they can handle the given file path and data, if any. | ||||||
|  | |||||||
| @ -154,7 +154,7 @@ journal = do | |||||||
|   eof |   eof | ||||||
|   finalctx <- getState |   finalctx <- getState | ||||||
|   return $ (combineJournalUpdates journalupdates, finalctx) |   return $ (combineJournalUpdates journalupdates, finalctx) | ||||||
|     where  |     where | ||||||
|       -- As all journal line types can be distinguished by the first |       -- As all journal line types can be distinguished by the first | ||||||
|       -- character, excepting transactions versus empty (blank or |       -- character, excepting transactions versus empty (blank or | ||||||
|       -- comment-only) lines, can use choice w/o try |       -- comment-only) lines, can use choice w/o try | ||||||
| @ -354,7 +354,7 @@ test_transaction = do | |||||||
|                         assertEqual (ttags t) (ttags t2) |                         assertEqual (ttags t) (ttags t2) | ||||||
|                         assertEqual (tpreceding_comment_lines t) (tpreceding_comment_lines t2) |                         assertEqual (tpreceding_comment_lines t) (tpreceding_comment_lines t2) | ||||||
|                         assertEqual (show $ tpostings t) (show $ tpostings t2) |                         assertEqual (show $ tpostings t) (show $ tpostings t2) | ||||||
|     -- "0000/01/01\n\n" `gives` nulltransaction  |     -- "0000/01/01\n\n" `gives` nulltransaction | ||||||
|     unlines [ |     unlines [ | ||||||
|       "2012/05/14=2012/05/15 (code) desc  ; tcomment1", |       "2012/05/14=2012/05/15 (code) desc  ; tcomment1", | ||||||
|       "    ; tcomment2", |       "    ; tcomment2", | ||||||
| @ -412,7 +412,7 @@ test_transaction = do | |||||||
|         ,"  b" |         ,"  b" | ||||||
|         ," " |         ," " | ||||||
|         ] |         ] | ||||||
|                      | 
 | ||||||
|     let p = parseWithCtx nullctx transaction $ unlines |     let p = parseWithCtx nullctx transaction $ unlines | ||||||
|              ["2009/1/1 x  ; transaction comment" |              ["2009/1/1 x  ; transaction comment" | ||||||
|              ," a  1  ; posting 1 comment" |              ," a  1  ; posting 1 comment" | ||||||
| @ -422,7 +422,7 @@ test_transaction = do | |||||||
|              ] |              ] | ||||||
|     assertRight p |     assertRight p | ||||||
|     assertEqual 2 (let Right t = p in length $ tpostings t) |     assertEqual 2 (let Right t = p in length $ tpostings t) | ||||||
| #endif        | #endif | ||||||
| 
 | 
 | ||||||
| -- | Parse a date in YYYY/MM/DD format. Fewer digits are allowed. The year | -- | Parse a date in YYYY/MM/DD format. Fewer digits are allowed. The year | ||||||
| -- may be omitted if a default year has already been set. | -- may be omitted if a default year has already been set. | ||||||
| @ -501,7 +501,7 @@ codep = try (do { many1 spacenonewline; char '(' <?> "codep"; code <- anyChar `m | |||||||
| -- Parse the following whitespace-beginning lines as postings, posting tags, and/or comments. | -- Parse the following whitespace-beginning lines as postings, posting tags, and/or comments. | ||||||
| postings :: GenParser Char JournalContext [Posting] | postings :: GenParser Char JournalContext [Posting] | ||||||
| postings = many1 (try postingp) <?> "postings" | postings = many1 (try postingp) <?> "postings" | ||||||
|              | 
 | ||||||
| -- linebeginningwithspaces :: GenParser Char JournalContext String | -- linebeginningwithspaces :: GenParser Char JournalContext String | ||||||
| -- linebeginningwithspaces = do | -- linebeginningwithspaces = do | ||||||
| --   sp <- many1 spacenonewline | --   sp <- many1 spacenonewline | ||||||
| @ -532,7 +532,7 @@ postingp = do | |||||||
| test_postingp = do | test_postingp = do | ||||||
|     let s `gives` ep = do |     let s `gives` ep = do | ||||||
|                          let parse = parseWithCtx nullctx postingp s |                          let parse = parseWithCtx nullctx postingp s | ||||||
|                          assertBool -- "postingp parser"  |                          assertBool -- "postingp parser" | ||||||
|                            $ isRight parse |                            $ isRight parse | ||||||
|                          let Right ap = parse |                          let Right ap = parse | ||||||
|                              same f = assertEqual (f ep) (f ap) |                              same f = assertEqual (f ep) (f ap) | ||||||
| @ -547,21 +547,21 @@ test_postingp = do | |||||||
|     "  expenses:food:dining  $10.00   ; a: a a \n   ; b: b b \n" `gives` |     "  expenses:food:dining  $10.00   ; a: a a \n   ; b: b b \n" `gives` | ||||||
|       posting{paccount="expenses:food:dining", pamount=Mixed [usd 10], pcomment=" a: a a \n b: b b \n", ptags=[("a","a a"), ("b","b b")]} |       posting{paccount="expenses:food:dining", pamount=Mixed [usd 10], pcomment=" a: a a \n b: b b \n", ptags=[("a","a a"), ("b","b b")]} | ||||||
| 
 | 
 | ||||||
|     " a  1 ; [2012/11/28]\n" `gives`  |     " a  1 ; [2012/11/28]\n" `gives` | ||||||
|       ("a" `post` num 1){pcomment=" [2012/11/28]\n" |       ("a" `post` num 1){pcomment=" [2012/11/28]\n" | ||||||
|                         ,ptags=[("date","2012/11/28")] |                         ,ptags=[("date","2012/11/28")] | ||||||
|                         ,pdate=parsedateM "2012/11/28"} |                         ,pdate=parsedateM "2012/11/28"} | ||||||
| 
 | 
 | ||||||
|     " a  1 ; a:a, [=2012/11/28]\n" `gives`  |     " a  1 ; a:a, [=2012/11/28]\n" `gives` | ||||||
|       ("a" `post` num 1){pcomment=" a:a, [=2012/11/28]\n" |       ("a" `post` num 1){pcomment=" a:a, [=2012/11/28]\n" | ||||||
|                         ,ptags=[("a","a"), ("date2","2012/11/28")] |                         ,ptags=[("a","a"), ("date2","2012/11/28")] | ||||||
|                         ,pdate=Nothing} |                         ,pdate=Nothing} | ||||||
| 
 | 
 | ||||||
|     " a  1 ; a:a\n  ; [2012/11/28=2012/11/29],b:b\n" `gives`  |     " a  1 ; a:a\n  ; [2012/11/28=2012/11/29],b:b\n" `gives` | ||||||
|       ("a" `post` num 1){pcomment=" a:a\n [2012/11/28=2012/11/29],b:b\n" |       ("a" `post` num 1){pcomment=" a:a\n [2012/11/28=2012/11/29],b:b\n" | ||||||
|                         ,ptags=[("a","a"), ("date","2012/11/28"), ("date2","2012/11/29"), ("b","b")] |                         ,ptags=[("a","a"), ("date","2012/11/28"), ("date2","2012/11/29"), ("b","b")] | ||||||
|                         ,pdate=parsedateM "2012/11/28"} |                         ,pdate=parsedateM "2012/11/28"} | ||||||
|       | 
 | ||||||
|     assertBool -- "postingp parses a quoted commodity with numbers" |     assertBool -- "postingp parses a quoted commodity with numbers" | ||||||
|       (isRight $ parseWithCtx nullctx postingp "  a  1 \"DE123\"\n") |       (isRight $ parseWithCtx nullctx postingp "  a  1 \"DE123\"\n") | ||||||
| 
 | 
 | ||||||
| @ -573,7 +573,7 @@ test_postingp = do | |||||||
|     -- let Right p = parse |     -- let Right p = parse | ||||||
|     -- assertEqual "next-line comment\n" (pcomment p) |     -- assertEqual "next-line comment\n" (pcomment p) | ||||||
|     -- assertEqual (Just nullmixedamt) (pbalanceassertion p) |     -- assertEqual (Just nullmixedamt) (pbalanceassertion p) | ||||||
| #endif        | #endif | ||||||
| 
 | 
 | ||||||
| -- | Parse an account name, then apply any parent account prefix and/or account aliases currently in effect. | -- | Parse an account name, then apply any parent account prefix and/or account aliases currently in effect. | ||||||
| modifiedaccountname :: GenParser Char JournalContext AccountName | modifiedaccountname :: GenParser Char JournalContext AccountName | ||||||
| @ -595,7 +595,7 @@ accountnamep = do | |||||||
|     when (accountNameFromComponents (accountNameComponents a') /= a') |     when (accountNameFromComponents (accountNameComponents a') /= a') | ||||||
|          (fail $ "account name seems ill-formed: "++a') |          (fail $ "account name seems ill-formed: "++a') | ||||||
|     return a' |     return a' | ||||||
|     where  |     where | ||||||
|       singlespace = try (do {spacenonewline; do {notFollowedBy spacenonewline; return ' '}}) |       singlespace = try (do {spacenonewline; do {notFollowedBy spacenonewline; return ' '}}) | ||||||
|       -- couldn't avoid consuming a final space sometimes, harmless |       -- couldn't avoid consuming a final space sometimes, harmless | ||||||
|       striptrailingspace s = if last s == ' ' then init s else s |       striptrailingspace s = if last s == ' ' then init s else s | ||||||
| @ -625,7 +625,7 @@ test_spaceandamountormissing = do | |||||||
|     assertParseEqual' (parseWithCtx nullctx spaceandamountormissing "$47.18") missingmixedamt |     assertParseEqual' (parseWithCtx nullctx spaceandamountormissing "$47.18") missingmixedamt | ||||||
|     assertParseEqual' (parseWithCtx nullctx spaceandamountormissing " ") missingmixedamt |     assertParseEqual' (parseWithCtx nullctx spaceandamountormissing " ") missingmixedamt | ||||||
|     assertParseEqual' (parseWithCtx nullctx spaceandamountormissing "") missingmixedamt |     assertParseEqual' (parseWithCtx nullctx spaceandamountormissing "") missingmixedamt | ||||||
| #endif        | #endif | ||||||
| 
 | 
 | ||||||
| -- | Parse a single-commodity amount, with optional symbol on the left or | -- | Parse a single-commodity amount, with optional symbol on the left or | ||||||
| -- right, optional unit or total price, and optional (ignored) | -- right, optional unit or total price, and optional (ignored) | ||||||
| @ -645,7 +645,7 @@ test_amountp = do | |||||||
|     assertParseEqual' |     assertParseEqual' | ||||||
|      (parseWithCtx nullctx amountp "$10 @@ €5") |      (parseWithCtx nullctx amountp "$10 @@ €5") | ||||||
|      (usd 10 `withPrecision` 0 @@ (eur 5 `withPrecision` 0)) |      (usd 10 `withPrecision` 0 @@ (eur 5 `withPrecision` 0)) | ||||||
| #endif        | #endif | ||||||
| 
 | 
 | ||||||
| -- | Parse an amount from a string, or get an error. | -- | Parse an amount from a string, or get an error. | ||||||
| amountp' :: String -> Amount | amountp' :: String -> Amount | ||||||
| @ -664,7 +664,7 @@ signp = do | |||||||
| leftsymbolamount :: GenParser Char JournalContext Amount | leftsymbolamount :: GenParser Char JournalContext Amount | ||||||
| leftsymbolamount = do | leftsymbolamount = do | ||||||
|   sign <- signp |   sign <- signp | ||||||
|   c <- commoditysymbol  |   c <- commoditysymbol | ||||||
|   sp <- many spacenonewline |   sp <- many spacenonewline | ||||||
|   (q,prec,mdec,mgrps) <- numberp |   (q,prec,mdec,mgrps) <- numberp | ||||||
|   let s = amountstyle{ascommodityside=L, ascommodityspaced=not $ null sp, asprecision=prec, asdecimalpoint=mdec, asdigitgroups=mgrps} |   let s = amountstyle{ascommodityside=L, ascommodityspaced=not $ null sp, asprecision=prec, asdecimalpoint=mdec, asdigitgroups=mgrps} | ||||||
| @ -761,16 +761,16 @@ fixedlotprice = | |||||||
| 
 | 
 | ||||||
| -- | Parse a string representation of a number for its value and display | -- | Parse a string representation of a number for its value and display | ||||||
| -- attributes. | -- attributes. | ||||||
| --  | -- | ||||||
| -- Some international number formats are accepted, eg either period or comma | -- Some international number formats are accepted, eg either period or comma | ||||||
| -- may be used for the decimal point, and the other of these may be used for | -- may be used for the decimal point, and the other of these may be used for | ||||||
| -- separating digit groups in the integer part. See | -- separating digit groups in the integer part. See | ||||||
| -- http://en.wikipedia.org/wiki/Decimal_separator for more examples. | -- http://en.wikipedia.org/wiki/Decimal_separator for more examples. | ||||||
| --  | -- | ||||||
| -- This returns: the parsed numeric value, the precision (number of digits | -- This returns: the parsed numeric value, the precision (number of digits | ||||||
| -- seen following the decimal point), the decimal point character used if any, | -- seen following the decimal point), the decimal point character used if any, | ||||||
| -- and the digit group style if any. | -- and the digit group style if any. | ||||||
| --  | -- | ||||||
| numberp :: GenParser Char JournalContext (Quantity, Int, Maybe Char, Maybe DigitGroupStyle) | numberp :: GenParser Char JournalContext (Quantity, Int, Maybe Char, Maybe DigitGroupStyle) | ||||||
| numberp = do | numberp = do | ||||||
|   -- a number is an optional sign followed by a sequence of digits possibly |   -- a number is an optional sign followed by a sequence of digits possibly | ||||||
| @ -820,11 +820,11 @@ numberp = do | |||||||
|   <?> "numberp" |   <?> "numberp" | ||||||
|   where |   where | ||||||
|     numeric = isNumber . headDef '_' |     numeric = isNumber . headDef '_' | ||||||
|        | 
 | ||||||
| #ifdef TESTS | #ifdef TESTS | ||||||
| test_numberp = do | test_numberp = do | ||||||
|       let s `is` n = assertParseEqual' (parseWithCtx nullctx numberp s) n |       let s `is` n = assertParseEqual' (parseWithCtx nullctx numberp s) n | ||||||
|           assertFails = assertBool . isLeft . parseWithCtx nullctx numberp  |           assertFails = assertBool . isLeft . parseWithCtx nullctx numberp | ||||||
|       assertFails "" |       assertFails "" | ||||||
|       "0"          `is` (0, 0, '.', ',', []) |       "0"          `is` (0, 0, '.', ',', []) | ||||||
|       "1"          `is` (1, 0, '.', ',', []) |       "1"          `is` (1, 0, '.', ',', []) | ||||||
| @ -843,7 +843,7 @@ test_numberp = do | |||||||
|       assertFails "1..1" |       assertFails "1..1" | ||||||
|       assertFails ".1," |       assertFails ".1," | ||||||
|       assertFails ",1." |       assertFails ",1." | ||||||
| #endif        | #endif | ||||||
| 
 | 
 | ||||||
| -- comment parsers | -- comment parsers | ||||||
| 
 | 
 | ||||||
| @ -878,7 +878,7 @@ tagsInComment :: String -> [Tag] | |||||||
| tagsInComment c = concatMap tagsInCommentLine $ lines c' | tagsInComment c = concatMap tagsInCommentLine $ lines c' | ||||||
|   where |   where | ||||||
|     c' = ledgerDateSyntaxToTags c |     c' = ledgerDateSyntaxToTags c | ||||||
|      | 
 | ||||||
| tagsInCommentLine :: String -> [Tag] | tagsInCommentLine :: String -> [Tag] | ||||||
| tagsInCommentLine = catMaybes . map maybetag . map strip . splitAtElement ',' | tagsInCommentLine = catMaybes . map maybetag . map strip . splitAtElement ',' | ||||||
|   where |   where | ||||||
| @ -913,7 +913,7 @@ ledgerDateSyntaxToTags = regexReplaceBy "\\[[-.\\/0-9=]+\\]" replace | |||||||
|     replace' ('=':s) | isdate s = date2tag s |     replace' ('=':s) | isdate s = date2tag s | ||||||
|     replace' s | last s =='=' && isdate (init s) = datetag (init s) |     replace' s | last s =='=' && isdate (init s) = datetag (init s) | ||||||
|     replace' s | length ds == 2 && isdate d1 && isdate d1 = datetag d1 ++ date2tag d2 |     replace' s | length ds == 2 && isdate d1 && isdate d1 = datetag d1 ++ date2tag d2 | ||||||
|       where  |       where | ||||||
|         ds = splitAtElement '=' s |         ds = splitAtElement '=' s | ||||||
|         d1 = headDef "" ds |         d1 = headDef "" ds | ||||||
|         d2 = lastDef "" ds |         d2 = lastDef "" ds | ||||||
| @ -922,17 +922,17 @@ ledgerDateSyntaxToTags = regexReplaceBy "\\[[-.\\/0-9=]+\\]" replace | |||||||
|     isdate = isJust . parsedateM |     isdate = isJust . parsedateM | ||||||
|     datetag s = "date:"++s++", " |     datetag s = "date:"++s++", " | ||||||
|     date2tag s = "date2:"++s++", " |     date2tag s = "date2:"++s++", " | ||||||
|      | 
 | ||||||
| #ifdef TESTS | #ifdef TESTS | ||||||
| test_ledgerDateSyntaxToTags = do | test_ledgerDateSyntaxToTags = do | ||||||
|      assertEqual "date2:2012/11/28, " $ ledgerDateSyntaxToTags "[=2012/11/28]" |      assertEqual "date2:2012/11/28, " $ ledgerDateSyntaxToTags "[=2012/11/28]" | ||||||
| #endif        | #endif | ||||||
|    | 
 | ||||||
| dateValueFromTags, date2ValueFromTags :: [Tag] -> Maybe String | dateValueFromTags, date2ValueFromTags :: [Tag] -> Maybe String | ||||||
| dateValueFromTags  ts = maybe Nothing (Just . snd) $ find ((=="date") . fst) ts | dateValueFromTags  ts = maybe Nothing (Just . snd) $ find ((=="date") . fst) ts | ||||||
| date2ValueFromTags ts = maybe Nothing (Just . snd) $ find ((=="date2") . fst) ts | date2ValueFromTags ts = maybe Nothing (Just . snd) $ find ((=="date2") . fst) ts | ||||||
| 
 | 
 | ||||||
|      | 
 | ||||||
| {- old hunit tests | {- old hunit tests | ||||||
| 
 | 
 | ||||||
| test_Hledger_Read_JournalReader = TestList $ concat [ | test_Hledger_Read_JournalReader = TestList $ concat [ | ||||||
|  | |||||||
| @ -86,7 +86,7 @@ timelogFile = do items <- many timelogItem | |||||||
|                  eof |                  eof | ||||||
|                  ctx <- getState |                  ctx <- getState | ||||||
|                  return (liftM (foldr (.) id) $ sequence items, ctx) |                  return (liftM (foldr (.) id) $ sequence items, ctx) | ||||||
|     where  |     where | ||||||
|       -- As all ledger line types can be distinguished by the first |       -- As all ledger line types can be distinguished by the first | ||||||
|       -- character, excepting transactions versus empty (blank or |       -- character, excepting transactions versus empty (blank or | ||||||
|       -- comment-only) lines, can use choice w/o try |       -- comment-only) lines, can use choice w/o try | ||||||
|  | |||||||
| @ -39,9 +39,9 @@ type BalanceReportItem = (RenderableAccountName, MixedAmount) | |||||||
| -- It has: | -- It has: | ||||||
| -- | -- | ||||||
| -- * The full account name | -- * The full account name | ||||||
| --  | -- | ||||||
| -- * The ledger-style short elided account name (the leaf name, prefixed by any boring parents immediately above) | -- * The ledger-style short elided account name (the leaf name, prefixed by any boring parents immediately above) | ||||||
| --  | -- | ||||||
| -- * The number of indentation steps to use when rendering a ledger-style account tree | -- * The number of indentation steps to use when rendering a ledger-style account tree | ||||||
| --   (normally the 0-based depth of this account excluding boring parents, or 0 with --flat). | --   (normally the 0-based depth of this account excluding boring parents, or 0 with --flat). | ||||||
| type RenderableAccountName = (AccountName, AccountName, Int) | type RenderableAccountName = (AccountName, AccountName, Int) | ||||||
| @ -67,14 +67,14 @@ balanceReport opts q j = (items, total) | |||||||
| 
 | 
 | ||||||
|       accts = ledgerRootAccount $ ledgerFromJournal q $ journalSelectingAmountFromOpts opts j |       accts = ledgerRootAccount $ ledgerFromJournal q $ journalSelectingAmountFromOpts opts j | ||||||
|       accts' :: [Account] |       accts' :: [Account] | ||||||
|           | flat_ opts = dbg "accts" $  |           | flat_ opts = dbg "accts" $ | ||||||
|                          filterzeros $ |                          filterzeros $ | ||||||
|                          filterempty $ |                          filterempty $ | ||||||
|                          drop 1 $ clipAccountsAndAggregate (queryDepth q) $ flattenAccounts accts |                          drop 1 $ clipAccountsAndAggregate (queryDepth q) $ flattenAccounts accts | ||||||
|           | otherwise  = dbg "accts" $  |           | otherwise  = dbg "accts" $ | ||||||
|                          filter (not.aboring) $ |                          filter (not.aboring) $ | ||||||
|                          drop 1 $ flattenAccounts $ |                          drop 1 $ flattenAccounts $ | ||||||
|                          markboring $  |                          markboring $ | ||||||
|                          prunezeros $ clipAccounts (queryDepth q) accts |                          prunezeros $ clipAccounts (queryDepth q) accts | ||||||
|           where |           where | ||||||
|             balance     = if flat_ opts then aebalance else aibalance |             balance     = if flat_ opts then aebalance else aibalance | ||||||
| @ -247,7 +247,7 @@ tests_balanceReport = | |||||||
|      ,"                   0" |      ,"                   0" | ||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|     ,"accounts report with unmatched parent of two matched subaccounts" ~:  |     ,"accounts report with unmatched parent of two matched subaccounts" ~: | ||||||
|      defreportopts{patterns_=["cash","saving"]} `gives` |      defreportopts{patterns_=["cash","saving"]} `gives` | ||||||
|      ["                 $-1  assets" |      ["                 $-1  assets" | ||||||
|      ,"                  $1    bank:saving" |      ,"                  $1    bank:saving" | ||||||
| @ -256,7 +256,7 @@ tests_balanceReport = | |||||||
|      ,"                 $-1" |      ,"                 $-1" | ||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|     ,"accounts report with multi-part account name" ~:  |     ,"accounts report with multi-part account name" ~: | ||||||
|      defreportopts{patterns_=["expenses:food"]} `gives` |      defreportopts{patterns_=["expenses:food"]} `gives` | ||||||
|      ["                  $1  expenses:food" |      ["                  $1  expenses:food" | ||||||
|      ,"--------------------" |      ,"--------------------" | ||||||
| @ -276,13 +276,13 @@ tests_balanceReport = | |||||||
|      ,"                  $1" |      ,"                  $1" | ||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|     ,"accounts report negative account pattern always matches full name" ~:  |     ,"accounts report negative account pattern always matches full name" ~: | ||||||
|      defreportopts{patterns_=["not:e"]} `gives` |      defreportopts{patterns_=["not:e"]} `gives` | ||||||
|      ["--------------------" |      ["--------------------" | ||||||
|      ,"                   0" |      ,"                   0" | ||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|     ,"accounts report negative patterns affect totals" ~:  |     ,"accounts report negative patterns affect totals" ~: | ||||||
|      defreportopts{patterns_=["expenses","not:food"]} `gives` |      defreportopts{patterns_=["expenses","not:food"]} `gives` | ||||||
|      ["                  $1  expenses:supplies" |      ["                  $1  expenses:supplies" | ||||||
|      ,"--------------------" |      ,"--------------------" | ||||||
| @ -317,7 +317,7 @@ tests_balanceReport = | |||||||
| -} | -} | ||||||
|  ] |  ] | ||||||
| 
 | 
 | ||||||
| Right samplejournal2 = journalBalanceTransactions $  | Right samplejournal2 = journalBalanceTransactions $ | ||||||
|          nulljournal |          nulljournal | ||||||
|          {jtxns = [ |          {jtxns = [ | ||||||
|            txnTieKnot $ Transaction { |            txnTieKnot $ Transaction { | ||||||
| @ -337,12 +337,12 @@ Right samplejournal2 = journalBalanceTransactions $ | |||||||
|            } |            } | ||||||
|           ] |           ] | ||||||
|          } |          } | ||||||
|           | 
 | ||||||
| -- tests_isInterestingIndented = [ | -- tests_isInterestingIndented = [ | ||||||
| --   "isInterestingIndented" ~: do  | --   "isInterestingIndented" ~: do | ||||||
| --    let (opts, journal, acctname) `gives` r = isInterestingIndented opts l acctname `is` r | --    let (opts, journal, acctname) `gives` r = isInterestingIndented opts l acctname `is` r | ||||||
| --           where l = ledgerFromJournal (queryFromOpts nulldate opts) journal | --           where l = ledgerFromJournal (queryFromOpts nulldate opts) journal | ||||||
|       | 
 | ||||||
| --    (defreportopts, samplejournal, "expenses") `gives` True | --    (defreportopts, samplejournal, "expenses") `gives` True | ||||||
| --  ] | --  ] | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -107,7 +107,7 @@ multiBalanceReport opts q j = MultiBalanceReport (displayspans, items, totals) | |||||||
|             postingAcctBals :: [Posting] -> [(ClippedAccountName, MixedAmount)] |             postingAcctBals :: [Posting] -> [(ClippedAccountName, MixedAmount)] | ||||||
|             postingAcctBals ps = [(aname a, (if tree_ opts then aibalance else aebalance) a) | a <- as] |             postingAcctBals ps = [(aname a, (if tree_ opts then aibalance else aebalance) a) | a <- as] | ||||||
|                 where |                 where | ||||||
|                   as = depthLimit $  |                   as = depthLimit $ | ||||||
|                        (if tree_ opts then id else filter ((>0).anumpostings)) $ |                        (if tree_ opts then id else filter ((>0).anumpostings)) $ | ||||||
|                        drop 1 $ accountsFromPostings ps |                        drop 1 $ accountsFromPostings ps | ||||||
|                   depthLimit |                   depthLimit | ||||||
|  | |||||||
| @ -70,7 +70,7 @@ postingsReport opts q j = (totallabel, items) | |||||||
|       beforeendq     = dbg "beforeendq"     $ dateqcons $ DateSpan Nothing reportend |       beforeendq     = dbg "beforeendq"     $ dateqcons $ DateSpan Nothing reportend | ||||||
|       reportq        = dbg "reportq"        $ depthless $ And [datelessq, beforeendq] -- user's query with no start date, end date on an interval boundary and no depth limit |       reportq        = dbg "reportq"        $ depthless $ And [datelessq, beforeendq] -- user's query with no start date, end date on an interval boundary and no depth limit | ||||||
| 
 | 
 | ||||||
|       pstoend =  |       pstoend = | ||||||
|           dbg "ps4" $ sortBy (comparing pdate) $                                  -- sort postings by date (or date2) |           dbg "ps4" $ sortBy (comparing pdate) $                                  -- sort postings by date (or date2) | ||||||
|           dbg "ps3" $ map (filterPostingAmount symq) $                            -- remove amount parts which the query's cur: terms would exclude |           dbg "ps3" $ map (filterPostingAmount symq) $                            -- remove amount parts which the query's cur: terms would exclude | ||||||
|           dbg "ps2" $ (if related_ opts then concatMap relatedPostings else id) $ -- with -r, replace each with its sibling postings |           dbg "ps2" $ (if related_ opts then concatMap relatedPostings else id) $ -- with -r, replace each with its sibling postings | ||||||
| @ -172,7 +172,7 @@ summarisePostingsInDateSpan (DateSpan b e) wd depth showempty ps | |||||||
|       anames = sort $ nub $ map paccount ps |       anames = sort $ nub $ map paccount ps | ||||||
|       -- aggregate balances by account, like ledgerFromJournal, then do depth-clipping |       -- aggregate balances by account, like ledgerFromJournal, then do depth-clipping | ||||||
|       accts = accountsFromPostings ps |       accts = accountsFromPostings ps | ||||||
|       balance a = maybe nullmixedamt bal $ lookupAccount a accts  |       balance a = maybe nullmixedamt bal $ lookupAccount a accts | ||||||
|         where |         where | ||||||
|           bal = if isclipped a then aibalance else aebalance |           bal = if isclipped a then aibalance else aebalance | ||||||
|           isclipped a = accountNameLevel a >= depth |           isclipped a = accountNameLevel a >= depth | ||||||
| @ -262,7 +262,7 @@ tests_postingsReport = [ | |||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|   ,"postings report with cleared option" ~: |   ,"postings report with cleared option" ~: | ||||||
|    do  |    do | ||||||
|     let opts = defreportopts{cleared_=True} |     let opts = defreportopts{cleared_=True} | ||||||
|     j <- readJournal' sample_journal_str |     j <- readJournal' sample_journal_str | ||||||
|     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines |     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines | ||||||
| @ -274,7 +274,7 @@ tests_postingsReport = [ | |||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|   ,"postings report with uncleared option" ~: |   ,"postings report with uncleared option" ~: | ||||||
|    do  |    do | ||||||
|     let opts = defreportopts{uncleared_=True} |     let opts = defreportopts{uncleared_=True} | ||||||
|     j <- readJournal' sample_journal_str |     j <- readJournal' sample_journal_str | ||||||
|     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines |     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines | ||||||
| @ -287,7 +287,7 @@ tests_postingsReport = [ | |||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|   ,"postings report sorts by date" ~: |   ,"postings report sorts by date" ~: | ||||||
|    do  |    do | ||||||
|     j <- readJournal' $ unlines |     j <- readJournal' $ unlines | ||||||
|         ["2008/02/02 a" |         ["2008/02/02 a" | ||||||
|         ,"  b  1" |         ,"  b  1" | ||||||
| @ -309,7 +309,7 @@ tests_postingsReport = [ | |||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|   ,"postings report with account pattern, case insensitive" ~: |   ,"postings report with account pattern, case insensitive" ~: | ||||||
|    do  |    do | ||||||
|     j <- samplejournal |     j <- samplejournal | ||||||
|     let opts = defreportopts{patterns_=["cAsH"]} |     let opts = defreportopts{patterns_=["cAsH"]} | ||||||
|     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines |     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines | ||||||
| @ -317,9 +317,9 @@ tests_postingsReport = [ | |||||||
|      ] |      ] | ||||||
| 
 | 
 | ||||||
|   ,"postings report with display expression" ~: |   ,"postings report with display expression" ~: | ||||||
|    do  |    do | ||||||
|     j <- samplejournal |     j <- samplejournal | ||||||
|     let gives displayexpr =  |     let gives displayexpr = | ||||||
|             (registerdates (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is`) |             (registerdates (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is`) | ||||||
|                 where opts = defreportopts{display_=Just displayexpr} |                 where opts = defreportopts{display_=Just displayexpr} | ||||||
|     "d<[2008/6/2]"  `gives` ["2008/01/01","2008/06/01"] |     "d<[2008/6/2]"  `gives` ["2008/01/01","2008/06/01"] | ||||||
| @ -329,7 +329,7 @@ tests_postingsReport = [ | |||||||
|     "d>[2008/6/2]"  `gives` ["2008/06/03","2008/12/31"] |     "d>[2008/6/2]"  `gives` ["2008/06/03","2008/12/31"] | ||||||
| 
 | 
 | ||||||
|   ,"postings report with period expression" ~: |   ,"postings report with period expression" ~: | ||||||
|    do  |    do | ||||||
|     j <- samplejournal |     j <- samplejournal | ||||||
|     let periodexpr `gives` dates = do |     let periodexpr `gives` dates = do | ||||||
|           j' <- samplejournal |           j' <- samplejournal | ||||||
| @ -359,7 +359,7 @@ tests_postingsReport = [ | |||||||
|   ] |   ] | ||||||
| 
 | 
 | ||||||
|   , "postings report with depth arg" ~: |   , "postings report with depth arg" ~: | ||||||
|    do  |    do | ||||||
|     j <- samplejournal |     j <- samplejournal | ||||||
|     let opts = defreportopts{depth_=Just 2} |     let opts = defreportopts{depth_=Just 2} | ||||||
|     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines |     (postingsReportAsText opts $ postingsReport opts (queryFromOpts date1 opts) j) `is` unlines | ||||||
|  | |||||||
| @ -120,7 +120,7 @@ accountTransactionsReport opts j q thisacctquery = (label, items) | |||||||
|      ts3 = map (setTransactionDateToPostingDate q thisacctquery) ts2 |      ts3 = map (setTransactionDateToPostingDate q thisacctquery) ts2 | ||||||
|      -- and sorted |      -- and sorted | ||||||
|      ts = sortBy (comparing tdate) ts3 |      ts = sortBy (comparing tdate) ts3 | ||||||
|            | 
 | ||||||
|      -- starting balance: if we are filtering by a start date and nothing else, |      -- starting balance: if we are filtering by a start date and nothing else, | ||||||
|      -- the sum of postings to this account before that date; otherwise zero. |      -- the sum of postings to this account before that date; otherwise zero. | ||||||
|      (startbal,label) | queryIsNull q                        = (nullmixedamt,        balancelabel) |      (startbal,label) | queryIsNull q                        = (nullmixedamt,        balancelabel) | ||||||
|  | |||||||
| @ -251,7 +251,7 @@ difforzero a b = maximum [(a - b), 0] | |||||||
| -- lists | -- lists | ||||||
| 
 | 
 | ||||||
| splitAtElement :: Eq a => a -> [a] -> [[a]] | splitAtElement :: Eq a => a -> [a] -> [[a]] | ||||||
| splitAtElement e l =  | splitAtElement e l = | ||||||
|     case dropWhile (e==) l of |     case dropWhile (e==) l of | ||||||
|       [] -> [] |       [] -> [] | ||||||
|       l' -> first : splitAtElement e rest |       l' -> first : splitAtElement e rest | ||||||
| @ -285,7 +285,7 @@ subtreeinforest _ [] = Nothing | |||||||
| subtreeinforest v (t:ts) = case (subtreeat v t) of | subtreeinforest v (t:ts) = case (subtreeat v t) of | ||||||
|                              Just t' -> Just t' |                              Just t' -> Just t' | ||||||
|                              Nothing -> subtreeinforest v ts |                              Nothing -> subtreeinforest v ts | ||||||
|            | 
 | ||||||
| -- | remove all nodes past a certain depth | -- | remove all nodes past a certain depth | ||||||
| treeprune :: Int -> Tree a -> Tree a | treeprune :: Int -> Tree a -> Tree a | ||||||
| treeprune 0 t = Node (root t) [] | treeprune 0 t = Node (root t) [] | ||||||
| @ -297,15 +297,15 @@ treemap f t = Node (f $ root t) (map (treemap f) $ branches t) | |||||||
| 
 | 
 | ||||||
| -- | remove all subtrees whose nodes do not fulfill predicate | -- | remove all subtrees whose nodes do not fulfill predicate | ||||||
| treefilter :: (a -> Bool) -> Tree a -> Tree a | treefilter :: (a -> Bool) -> Tree a -> Tree a | ||||||
| treefilter f t = Node  | treefilter f t = Node | ||||||
|                  (root t)  |                  (root t) | ||||||
|                  (map (treefilter f) $ filter (treeany f) $ branches t) |                  (map (treefilter f) $ filter (treeany f) $ branches t) | ||||||
|      | 
 | ||||||
| -- | is predicate true in any node of tree ? | -- | is predicate true in any node of tree ? | ||||||
| treeany :: (a -> Bool) -> Tree a -> Bool | treeany :: (a -> Bool) -> Tree a -> Bool | ||||||
| treeany f t = f (root t) || any (treeany f) (branches t) | treeany f t = f (root t) || any (treeany f) (branches t) | ||||||
|      | 
 | ||||||
| -- treedrop -- remove the leaves which do fulfill predicate.  | -- treedrop -- remove the leaves which do fulfill predicate. | ||||||
| -- treedropall -- do this repeatedly. | -- treedropall -- do this repeatedly. | ||||||
| 
 | 
 | ||||||
| -- | show a compact ascii representation of a tree | -- | show a compact ascii representation of a tree | ||||||
| @ -605,7 +605,7 @@ applyN :: Int -> (a -> a) -> a -> a | |||||||
| applyN n f = (!! n) . iterate f | applyN n f = (!! n) . iterate f | ||||||
| 
 | 
 | ||||||
| -- | Convert a possibly relative, possibly tilde-containing file path to an absolute one, | -- | Convert a possibly relative, possibly tilde-containing file path to an absolute one, | ||||||
| -- given the current directory. ~username is not supported. Leave "-" unchanged.  | -- given the current directory. ~username is not supported. Leave "-" unchanged. | ||||||
| expandPath :: MonadIO m => FilePath -> FilePath -> m FilePath -- general type sig for use in reader parsers | expandPath :: MonadIO m => FilePath -> FilePath -> m FilePath -- general type sig for use in reader parsers | ||||||
| expandPath _ "-" = return "-" | expandPath _ "-" = return "-" | ||||||
| expandPath curdir p = (if isRelative p then (curdir </>) else id) `liftM` expandPath' p | expandPath curdir p = (if isRelative p then (curdir </>) else id) `liftM` expandPath' p | ||||||
|  | |||||||
| @ -116,7 +116,7 @@ replaceAll re f s = start end | |||||||
|   where |   where | ||||||
|     (_, end, start) = foldl' go (0, s, id) $ getAllMatches $ match re s |     (_, end, start) = foldl' go (0, s, id) $ getAllMatches $ match re s | ||||||
|     go (ind,read,write) (off,len) = |     go (ind,read,write) (off,len) = | ||||||
|       let (skip, start) = splitAt (off - ind) read  |       let (skip, start) = splitAt (off - ind) read | ||||||
|           (matched, remaining) = splitAt len start  |           (matched, remaining) = splitAt len start | ||||||
|       in (off + len, remaining, write . (skip++) . (f matched ++)) |       in (off + len, remaining, write . (skip++) . (f matched ++)) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -111,7 +111,7 @@ registerChartHtml percommoditytxnreports = | |||||||
|      \$('#register-chart-label').text('#{charttitle}'); |      \$('#register-chart-label').text('#{charttitle}'); | ||||||
|      var seriesData = [ |      var seriesData = [ | ||||||
|       $forall (c,(_,items)) <- percommoditytxnreports |       $forall (c,(_,items)) <- percommoditytxnreports | ||||||
|        /* we render each commodity using two series:  |        /* we render each commodity using two series: | ||||||
|         * one with extra data points added to show a stepped balance line */ |         * one with extra data points added to show a stepped balance line */ | ||||||
|        { |        { | ||||||
|         data: [ |         data: [ | ||||||
| @ -128,7 +128,7 @@ registerChartHtml percommoditytxnreports = | |||||||
|           show: true, |           show: true, | ||||||
|           steps: true, |           steps: true, | ||||||
|         }, |         }, | ||||||
|         points: {  |         points: { | ||||||
|           show: false, |           show: false, | ||||||
|         }, |         }, | ||||||
|         clickable: false, |         clickable: false, | ||||||
| @ -152,7 +152,7 @@ registerChartHtml percommoditytxnreports = | |||||||
|         lines: { |         lines: { | ||||||
|           show: false, |           show: false, | ||||||
|         }, |         }, | ||||||
|         points: {  |         points: { | ||||||
|           show: true, |           show: true, | ||||||
|         }, |         }, | ||||||
|        }, |        }, | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ webflags = [ | |||||||
|  ,flagReq  ["base-url"] (\s opts -> Right $ setopt "base-url" s opts) "BASEURL" ("set the base url (default: "++defbaseurlexample++")") |  ,flagReq  ["base-url"] (\s opts -> Right $ setopt "base-url" s opts) "BASEURL" ("set the base url (default: "++defbaseurlexample++")") | ||||||
|  ,flagReq  ["file-url"] (\s opts -> Right $ setopt "file-url" s opts) "FILEURL" ("set the static files url (default: BASEURL/static)") |  ,flagReq  ["file-url"] (\s opts -> Right $ setopt "file-url" s opts) "FILEURL" ("set the static files url (default: BASEURL/static)") | ||||||
|  ] |  ] | ||||||
|   | 
 | ||||||
| webmode :: Mode [([Char], [Char])] | webmode :: Mode [([Char], [Char])] | ||||||
| webmode =  (mode "hledger-web" [("command","web")] | webmode =  (mode "hledger-web" [("command","web")] | ||||||
|             "start serving the hledger web interface" |             "start serving the hledger web interface" | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| {-|  | {-| | ||||||
| 
 | 
 | ||||||
| Hledger.Cli re-exports the options, utilities and commands provided by | Hledger.Cli re-exports the options, utilities and commands provided by | ||||||
| the hledger command-line program. This module also aggregates the | the hledger command-line program. This module also aggregates the | ||||||
| @ -69,19 +69,19 @@ tests_Hledger_Cli = TestList | |||||||
|                                 j1 `is` j2{filereadtime=filereadtime j1, files=files j1, jContext=jContext j1} |                                 j1 `is` j2{filereadtime=filereadtime j1, files=files j1, jContext=jContext j1} | ||||||
|    in TestList |    in TestList | ||||||
|    [ |    [ | ||||||
|     "account directive 1" ~: sameParse  |     "account directive 1" ~: sameParse | ||||||
|                           "2008/12/07 One\n  test:from  $-1\n  test:to  $1\n" |                           "2008/12/07 One\n  test:from  $-1\n  test:to  $1\n" | ||||||
|                           "!account test\n2008/12/07 One\n  from  $-1\n  to  $1\n" |                           "!account test\n2008/12/07 One\n  from  $-1\n  to  $1\n" | ||||||
| 
 | 
 | ||||||
|    ,"account directive 2" ~: sameParse  |    ,"account directive 2" ~: sameParse | ||||||
|                            "2008/12/07 One\n  test:foo:from  $-1\n  test:foo:to  $1\n" |                            "2008/12/07 One\n  test:foo:from  $-1\n  test:foo:to  $1\n" | ||||||
|                            "!account test\n!account foo\n2008/12/07 One\n  from  $-1\n  to  $1\n" |                            "!account test\n!account foo\n2008/12/07 One\n  from  $-1\n  to  $1\n" | ||||||
| 
 | 
 | ||||||
|    ,"account directive 3" ~: sameParse  |    ,"account directive 3" ~: sameParse | ||||||
|                            "2008/12/07 One\n  test:from  $-1\n  test:to  $1\n" |                            "2008/12/07 One\n  test:from  $-1\n  test:to  $1\n" | ||||||
|                            "!account test\n!account foo\n!end\n2008/12/07 One\n  from  $-1\n  to  $1\n" |                            "!account test\n!account foo\n!end\n2008/12/07 One\n  from  $-1\n  to  $1\n" | ||||||
| 
 | 
 | ||||||
|    ,"account directive 4" ~: sameParse  |    ,"account directive 4" ~: sameParse | ||||||
|                            ("2008/12/07 One\n  alpha  $-1\n  beta  $1\n" ++ |                            ("2008/12/07 One\n  alpha  $-1\n  beta  $1\n" ++ | ||||||
|                             "!account outer\n2008/12/07 Two\n  aigh  $-2\n  bee  $2\n" ++ |                             "!account outer\n2008/12/07 Two\n  aigh  $-2\n  bee  $2\n" ++ | ||||||
|                             "!account inner\n2008/12/07 Three\n  gamma  $-3\n  delta  $3\n" ++ |                             "!account inner\n2008/12/07 Three\n  gamma  $-3\n  delta  $3\n" ++ | ||||||
| @ -136,7 +136,7 @@ tests_Hledger_Cli = TestList | |||||||
| 
 | 
 | ||||||
|  ] |  ] | ||||||
| 
 | 
 | ||||||
|    | 
 | ||||||
| -- fixtures/test data | -- fixtures/test data | ||||||
| 
 | 
 | ||||||
| -- date1 = parsedate "2008/11/26" | -- date1 = parsedate "2008/11/26" | ||||||
| @ -340,7 +340,7 @@ defaultyear_journal_str = unlines | |||||||
| --  ] | --  ] | ||||||
| 
 | 
 | ||||||
| journal7 :: Journal | journal7 :: Journal | ||||||
| journal7 = nulljournal {jtxns =  | journal7 = nulljournal {jtxns = | ||||||
|           [ |           [ | ||||||
|            txnTieKnot Transaction { |            txnTieKnot Transaction { | ||||||
|              tsourcepos=nullsourcepos, |              tsourcepos=nullsourcepos, | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ import Safe (headDef, headMay) | |||||||
| import System.Console.CmdArgs.Explicit | import System.Console.CmdArgs.Explicit | ||||||
| import System.Console.Haskeline (runInputT, defaultSettings, setComplete) | import System.Console.Haskeline (runInputT, defaultSettings, setComplete) | ||||||
| import System.Console.Haskeline.Completion | import System.Console.Haskeline.Completion | ||||||
| import System.Console.Wizard   | import System.Console.Wizard | ||||||
| import System.Console.Wizard.Haskeline | import System.Console.Wizard.Haskeline | ||||||
| import System.IO ( stderr, hPutStr, hPutStrLn ) | import System.IO ( stderr, hPutStr, hPutStrLn ) | ||||||
| import Text.ParserCombinators.Parsec hiding (Line) | import Text.ParserCombinators.Parsec hiding (Line) | ||||||
| @ -128,9 +128,9 @@ confirmedTransactionWizard es@EntryState{..} = do | |||||||
|   -- liftIO $ hPrintf stderr {- "Transaction entered:\n%s" -} (show t) |   -- liftIO $ hPrintf stderr {- "Transaction entered:\n%s" -} (show t) | ||||||
|   output $ show t |   output $ show t | ||||||
|   y <- let def = "y" in |   y <- let def = "y" in | ||||||
|        retryMsg "Please enter y or n." $  |        retryMsg "Please enter y or n." $ | ||||||
|         parser ((fmap ('y' ==)) . headMay . map toLower . strip) $  |         parser ((fmap ('y' ==)) . headMay . map toLower . strip) $ | ||||||
|         defaultTo' def $ nonEmpty $  |         defaultTo' def $ nonEmpty $ | ||||||
|         maybeRestartTransaction $ |         maybeRestartTransaction $ | ||||||
|         line $ green $ printf "Save this transaction to the journal ?%s: " (showDefault def) |         line $ green $ printf "Save this transaction to the journal ?%s: " (showDefault def) | ||||||
|   if y then return t else throw RestartTransactionException |   if y then return t else throw RestartTransactionException | ||||||
| @ -167,10 +167,10 @@ similarTransaction EntryState{..} desc = | |||||||
| 
 | 
 | ||||||
| dateAndCodeWizard EntryState{..} = do | dateAndCodeWizard EntryState{..} = do | ||||||
|   let def = headDef (showDate esDefDate) esArgs |   let def = headDef (showDate esDefDate) esArgs | ||||||
|   retryMsg "A valid hledger smart date is required. Eg: 2014/2/14, 14, yesterday." $  |   retryMsg "A valid hledger smart date is required. Eg: 2014/2/14, 14, yesterday." $ | ||||||
|    parser (parseSmartDateAndCode esToday) $  |    parser (parseSmartDateAndCode esToday) $ | ||||||
|    withCompletion (dateCompleter def) $ |    withCompletion (dateCompleter def) $ | ||||||
|    defaultTo' def $ nonEmpty $  |    defaultTo' def $ nonEmpty $ | ||||||
|    maybeExit $ |    maybeExit $ | ||||||
|    maybeRestartTransaction $ |    maybeRestartTransaction $ | ||||||
|    -- maybeShowHelp $ |    -- maybeShowHelp $ | ||||||
| @ -191,7 +191,7 @@ dateAndCodeWizard EntryState{..} = do | |||||||
| descriptionAndCommentWizard EntryState{..} = do | descriptionAndCommentWizard EntryState{..} = do | ||||||
|   let def = headDef "" esArgs |   let def = headDef "" esArgs | ||||||
|   s <- withCompletion (descriptionCompleter esJournal def) $ |   s <- withCompletion (descriptionCompleter esJournal def) $ | ||||||
|        defaultTo' def $ nonEmpty $  |        defaultTo' def $ nonEmpty $ | ||||||
|        maybeRestartTransaction $ |        maybeRestartTransaction $ | ||||||
|        line $ green $ printf "Description%s: " (showDefault def) |        line $ green $ printf "Description%s: " (showDefault def) | ||||||
|   let (desc,comment) = (strip a, strip $ dropWhile (==';') b) where (a,b) = break (==';') s |   let (desc,comment) = (strip a, strip $ dropWhile (==';') b) where (a,b) = break (==';') s | ||||||
| @ -233,7 +233,7 @@ accountWizard EntryState{..} = do | |||||||
|   retryMsg "A valid hledger account name is required. Eg: assets:cash, expenses:food:eating out." $ |   retryMsg "A valid hledger account name is required. Eg: assets:cash, expenses:food:eating out." $ | ||||||
|    parser (parseAccountOrDotOrNull def canfinish) $ |    parser (parseAccountOrDotOrNull def canfinish) $ | ||||||
|    withCompletion (accountCompleter esJournal def) $ |    withCompletion (accountCompleter esJournal def) $ | ||||||
|    defaultTo' def $ -- nonEmpty $  |    defaultTo' def $ -- nonEmpty $ | ||||||
|    maybeRestartTransaction $ |    maybeRestartTransaction $ | ||||||
|    line $ green $ printf "Account %d%s%s: " pnum (endmsg::String) (showDefault def) |    line $ green $ printf "Account %d%s%s: " pnum (endmsg::String) (showDefault def) | ||||||
|     where |     where | ||||||
| @ -259,12 +259,12 @@ amountAndCommentWizard EntryState{..} = do | |||||||
|               _  | pnum > 1 && not (isZeroMixedAmount balancingamt) -> showamt balancingamt |               _  | pnum > 1 && not (isZeroMixedAmount balancingamt) -> showamt balancingamt | ||||||
|               _                                                     -> "" |               _                                                     -> "" | ||||||
|   retryMsg "A valid hledger amount is required. Eg: 1, $2, 3 EUR, \"4 red apples\"." $ |   retryMsg "A valid hledger amount is required. Eg: 1, $2, 3 EUR, \"4 red apples\"." $ | ||||||
|    parser parseAmountAndComment $  |    parser parseAmountAndComment $ | ||||||
|    withCompletion (amountCompleter def) $ |    withCompletion (amountCompleter def) $ | ||||||
|    defaultTo' def $ nonEmpty $  |    defaultTo' def $ nonEmpty $ | ||||||
|    maybeRestartTransaction $ |    maybeRestartTransaction $ | ||||||
|    line $ green $ printf "Amount  %d%s: " pnum (showDefault def) |    line $ green $ printf "Amount  %d%s: " pnum (showDefault def) | ||||||
|     where   |     where | ||||||
|       parseAmountAndComment = either (const Nothing) Just . parseWithCtx nodefcommodityctx amountandcommentp |       parseAmountAndComment = either (const Nothing) Just . parseWithCtx nodefcommodityctx amountandcommentp | ||||||
|       nodefcommodityctx = (jContext esJournal){ctxDefaultCommodityAndStyle=Nothing} |       nodefcommodityctx = (jContext esJournal){ctxDefaultCommodityAndStyle=Nothing} | ||||||
|       amountandcommentp = do |       amountandcommentp = do | ||||||
| @ -298,7 +298,7 @@ maybeExit = parser (\s -> if s=="." then throw UnexpectedEOF else Just s) | |||||||
| maybeRestartTransaction = parser (\s -> if s=="<" then throw RestartTransactionException else Just s) | maybeRestartTransaction = parser (\s -> if s=="<" then throw RestartTransactionException else Just s) | ||||||
| 
 | 
 | ||||||
| -- maybeShowHelp :: Wizard Haskeline String -> Wizard Haskeline String | -- maybeShowHelp :: Wizard Haskeline String -> Wizard Haskeline String | ||||||
| -- maybeShowHelp wizard = maybe (liftIO showHelp >> wizard) return $  | -- maybeShowHelp wizard = maybe (liftIO showHelp >> wizard) return $ | ||||||
| --                        parser (\s -> if s=="?" then Nothing else Just s) wizard | --                        parser (\s -> if s=="?" then Nothing else Just s) wizard | ||||||
| 
 | 
 | ||||||
| -- Completion helpers | -- Completion helpers | ||||||
|  | |||||||
| @ -129,7 +129,7 @@ There are three kinds of multi-column balance report, indicated by the heading: | |||||||
|   period. Here, checking's balance increased by 10 in Feb: |   period. Here, checking's balance increased by 10 in Feb: | ||||||
| 
 | 
 | ||||||
|   > Change of balance (flow): |   > Change of balance (flow): | ||||||
|   >  |   > | ||||||
|   >                  Jan   Feb   Mar |   >                  Jan   Feb   Mar | ||||||
|   > assets:checking   20    10    -5 |   > assets:checking   20    10    -5 | ||||||
| 
 | 
 | ||||||
| @ -138,7 +138,7 @@ There are three kinds of multi-column balance report, indicated by the heading: | |||||||
|   Here, 30 is the sum of checking postings during Jan and Feb: |   Here, 30 is the sum of checking postings during Jan and Feb: | ||||||
| 
 | 
 | ||||||
|   > Ending balance (cumulative): |   > Ending balance (cumulative): | ||||||
|   >  |   > | ||||||
|   >                  Jan   Feb   Mar |   >                  Jan   Feb   Mar | ||||||
|   > assets:checking   20    30    25 |   > assets:checking   20    30    25 | ||||||
| 
 | 
 | ||||||
| @ -148,7 +148,7 @@ There are three kinds of multi-column balance report, indicated by the heading: | |||||||
|   pre-Jan postings which created a starting balance of 100: |   pre-Jan postings which created a starting balance of 100: | ||||||
| 
 | 
 | ||||||
|   > Ending balance (historical): |   > Ending balance (historical): | ||||||
|   >  |   > | ||||||
|   >                  Jan   Feb   Mar |   >                  Jan   Feb   Mar | ||||||
|   > assets:checking  120   130   125 |   > assets:checking  120   130   125 | ||||||
| 
 | 
 | ||||||
| @ -161,7 +161,7 @@ Here's a (imperfect?) specification for the eliding/omitting behaviour: | |||||||
| * An account less deep than the report's max depth, with just one | * An account less deep than the report's max depth, with just one | ||||||
| interesting subaccount, and the same balance as the subaccount, is | interesting subaccount, and the same balance as the subaccount, is | ||||||
| non-interesting, and prefixed to the subaccount's line, unless | non-interesting, and prefixed to the subaccount's line, unless | ||||||
| @--no-elide@ is in effect.  | @--no-elide@ is in effect. | ||||||
| 
 | 
 | ||||||
| * An account with a zero inclusive balance and less than two interesting | * An account with a zero inclusive balance and less than two interesting | ||||||
| subaccounts is not displayed at all, unless @--empty@ is in effect. | subaccounts is not displayed at all, unless @--empty@ is in effect. | ||||||
| @ -405,7 +405,7 @@ cumulativeBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, colto | |||||||
|   ([printf "Ending balances (cumulative) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $ |   ([printf "Ending balances (cumulative) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $ | ||||||
|   trimborder $ lines $ |   trimborder $ lines $ | ||||||
|    render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $ |    render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $ | ||||||
|     addtotalrow $  |     addtotalrow $ | ||||||
|      Table |      Table | ||||||
|        (T.Group NoLine $ map (Header . padright acctswidth) accts) |        (T.Group NoLine $ map (Header . padright acctswidth) accts) | ||||||
|        (T.Group NoLine $ map Header colspans) |        (T.Group NoLine $ map Header colspans) | ||||||
| @ -426,7 +426,7 @@ historicalBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, colto | |||||||
|   ([printf "Ending balances (historical) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $ |   ([printf "Ending balances (historical) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $ | ||||||
|   trimborder $ lines $ |   trimborder $ lines $ | ||||||
|    render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $ |    render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $ | ||||||
|     addtotalrow $  |     addtotalrow $ | ||||||
|      Table |      Table | ||||||
|        (T.Group NoLine $ map (Header . padright acctswidth) accts) |        (T.Group NoLine $ map (Header . padright acctswidth) accts) | ||||||
|        (T.Group NoLine $ map Header colspans) |        (T.Group NoLine $ map Header colspans) | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| {-|  | {-| | ||||||
| 
 | 
 | ||||||
| Print a histogram report. (The "activity" command). | Print a histogram report. (The "activity" command). | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ module Hledger.Cli.Options ( | |||||||
|   argsFlag, |   argsFlag, | ||||||
|   showModeHelp, |   showModeHelp, | ||||||
|   withAliases, |   withAliases, | ||||||
|    | 
 | ||||||
|   -- * CLI options |   -- * CLI options | ||||||
|   CliOpts(..), |   CliOpts(..), | ||||||
|   defcliopts, |   defcliopts, | ||||||
| @ -51,9 +51,9 @@ module Hledger.Cli.Options ( | |||||||
|   -- * Tests |   -- * Tests | ||||||
|   tests_Hledger_Cli_Options |   tests_Hledger_Cli_Options | ||||||
| 
 | 
 | ||||||
| )  | ) | ||||||
| where | where | ||||||
|    | 
 | ||||||
| import qualified Control.Exception as C | import qualified Control.Exception as C | ||||||
| import Control.Monad (when) | import Control.Monad (when) | ||||||
| import Data.List | import Data.List | ||||||
| @ -199,7 +199,7 @@ standardAddonsHelp = [ | |||||||
| 
 | 
 | ||||||
| -- | Get a mode's help message as a nicely wrapped string. | -- | Get a mode's help message as a nicely wrapped string. | ||||||
| showModeHelp :: Mode a -> String | showModeHelp :: Mode a -> String | ||||||
| showModeHelp = (showText defaultWrap :: [Text] -> String) .  | showModeHelp = (showText defaultWrap :: [Text] -> String) . | ||||||
|                (helpText [] HelpFormatDefault :: Mode a -> [Text]) |                (helpText [] HelpFormatDefault :: Mode a -> [Text]) | ||||||
| 
 | 
 | ||||||
| -- | Add command aliases to the command's help string. | -- | Add command aliases to the command's help string. | ||||||
| @ -275,7 +275,7 @@ rawOptsToCliOpts rawopts = do | |||||||
|              ,width_           = maybestringopt "width" rawopts    -- register |              ,width_           = maybestringopt "width" rawopts    -- register | ||||||
|              ,reportopts_      = ropts |              ,reportopts_      = ropts | ||||||
|              } |              } | ||||||
|    | 
 | ||||||
| -- | Do final validation of processed opts, raising an error if there is trouble. | -- | Do final validation of processed opts, raising an error if there is trouble. | ||||||
| checkCliOpts :: CliOpts -> IO CliOpts -- or pure.. | checkCliOpts :: CliOpts -> IO CliOpts -- or pure.. | ||||||
| checkCliOpts opts@CliOpts{reportopts_=ropts} = do | checkCliOpts opts@CliOpts{reportopts_=ropts} = do | ||||||
| @ -362,7 +362,7 @@ defaultBalanceFormat = [ | |||||||
| 
 | 
 | ||||||
| -- | Output width configuration (for register). | -- | Output width configuration (for register). | ||||||
| data OutputWidth = | data OutputWidth = | ||||||
|     TotalWidth Width    -- ^ specify the overall width  |     TotalWidth Width    -- ^ specify the overall width | ||||||
|   | FieldWidths [Width] -- ^ specify each field's width |   | FieldWidths [Width] -- ^ specify each field's width | ||||||
|   deriving Show |   deriving Show | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| {-|  | {-| | ||||||
| 
 | 
 | ||||||
| A ledger-compatible @print@ command. | A ledger-compatible @print@ command. | ||||||
| 
 | 
 | ||||||
| @ -46,7 +46,7 @@ entriesReportAsText _ _ items = concatMap showTransactionUnelided items | |||||||
| --   "showTransactions" ~: do | --   "showTransactions" ~: do | ||||||
| 
 | 
 | ||||||
| --    -- "print expenses" ~: | --    -- "print expenses" ~: | ||||||
| --    do  | --    do | ||||||
| --     let opts = defreportopts{query_="expenses"} | --     let opts = defreportopts{query_="expenses"} | ||||||
| --     d <- getCurrentDay | --     d <- getCurrentDay | ||||||
| --     showTransactions opts (queryFromOpts d opts) samplejournal `is` unlines | --     showTransactions opts (queryFromOpts d opts) samplejournal `is` unlines | ||||||
| @ -58,7 +58,7 @@ entriesReportAsText _ _ items = concatMap showTransactionUnelided items | |||||||
| --      ] | --      ] | ||||||
| 
 | 
 | ||||||
| --   -- , "print report with depth arg" ~: | --   -- , "print report with depth arg" ~: | ||||||
| --    do  | --    do | ||||||
| --     let opts = defreportopts{depth_=Just 2} | --     let opts = defreportopts{depth_=Just 2} | ||||||
| --     d <- getCurrentDay | --     d <- getCurrentDay | ||||||
| --     showTransactions opts (queryFromOpts d opts) samplejournal `is` unlines | --     showTransactions opts (queryFromOpts d opts) samplejournal `is` unlines | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| {-|  | {-| | ||||||
| 
 | 
 | ||||||
| A ledger-compatible @register@ command. | A ledger-compatible @register@ command. | ||||||
| 
 | 
 | ||||||
| @ -75,7 +75,7 @@ postingsReportItemAsText opts (mdate, menddate, mdesc, p, b) = | |||||||
|             date desc acct amtfirstline balfirstline] |             date desc acct amtfirstline balfirstline] | ||||||
|     ++ |     ++ | ||||||
|     [printf (spacer ++ "%"++amtw++"s  %"++balw++"s") a b | (a,b) <- zip amtrest balrest ] |     [printf (spacer ++ "%"++amtw++"s  %"++balw++"s") a b | (a,b) <- zip amtrest balrest ] | ||||||
|      | 
 | ||||||
|     where |     where | ||||||
|       totalwidth = case widthFromOpts opts of |       totalwidth = case widthFromOpts opts of | ||||||
|            Left _                       -> defaultWidth -- shouldn't happen |            Left _                       -> defaultWidth -- shouldn't happen | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| #!/usr/bin/env runhaskell | #!/usr/bin/env runhaskell | ||||||
| {-  | {- | ||||||
| generateledger.hs NUMTXNS NUMACCTS ACCTDEPTH | generateledger.hs NUMTXNS NUMACCTS ACCTDEPTH | ||||||
| 
 | 
 | ||||||
| Outputs a dummy ledger file with the specified number of transactions, | Outputs a dummy ledger file with the specified number of transactions, | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ allDeps base mod = allDeps' [mod] [mod] where | |||||||
|     allDeps' [] _        = return [] |     allDeps' [] _        = return [] | ||||||
| 
 | 
 | ||||||
| {- | {- | ||||||
|     Usage: OrderByComplexity   |     Usage: OrderByComplexity | ||||||
| 
 | 
 | ||||||
|         = directory where source code is found.  This MUST |         = directory where source code is found.  This MUST | ||||||
|                 end in '/' |                 end in '/' | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| #!/usr/bin/env runhaskell | #!/usr/bin/env runhaskell | ||||||
| {-  | {- | ||||||
| bench.hs - simple benchmarking of command-line programs. | bench.hs - simple benchmarking of command-line programs. | ||||||
| Requires html and tabular. | Requires html and tabular. | ||||||
| Simon Michael 2008-2013 | Simon Michael 2008-2013 | ||||||
| @ -63,14 +63,14 @@ usagehdr = "bench [-f testsfile] [-n iterations] [-p precision] executable1 [exe | |||||||
|            "Run some functional tests with each of the specified executables,\n" ++ |            "Run some functional tests with each of the specified executables,\n" ++ | ||||||
|            "where a test is \"zero or more arguments supported by all executables\",\n" ++ |            "where a test is \"zero or more arguments supported by all executables\",\n" ++ | ||||||
|            "and report the best execution times.\n" |            "and report the best execution times.\n" | ||||||
|             | 
 | ||||||
| options = [ | options = [ | ||||||
|   Option "f" ["testsfile"] (ReqArg File "testsfile") "file containing tests, one per line, default: bench.tests" |   Option "f" ["testsfile"] (ReqArg File "testsfile") "file containing tests, one per line, default: bench.tests" | ||||||
|  ,Option "n" ["iterations"] (ReqArg Num "iterations") "number of test iterations to run, default: 2" |  ,Option "n" ["iterations"] (ReqArg Num "iterations") "number of test iterations to run, default: 2" | ||||||
|  ,Option "p" ["precision"] (ReqArg Prec "precision") "show times with this precision, default: 2" |  ,Option "p" ["precision"] (ReqArg Prec "precision") "show times with this precision, default: 2" | ||||||
|  ,Option "v" ["verbose"] (NoArg Verbose) "show intermediate results" |  ,Option "v" ["verbose"] (NoArg Verbose) "show intermediate results" | ||||||
|  ,Option "h" ["help"] (NoArg Help) "show this help" |  ,Option "h" ["help"] (NoArg Help) "show this help" | ||||||
|  ]              |  ] | ||||||
| 
 | 
 | ||||||
| usageftr = "\n" ++ | usageftr = "\n" ++ | ||||||
|            "Tips:\n" ++ |            "Tips:\n" ++ | ||||||
| @ -81,10 +81,10 @@ usageftr = "\n" ++ | |||||||
| usage = usageInfo usagehdr options ++ usageftr | usage = usageInfo usagehdr options ++ usageftr | ||||||
| 
 | 
 | ||||||
| -- an option value | -- an option value | ||||||
| data Opt = File {value::String}  | data Opt = File {value::String} | ||||||
|          | Num  {value::String}  |          | Num  {value::String} | ||||||
|          | Prec {value::String}  |          | Prec {value::String} | ||||||
| -- I don't know how optValuesForConstructor etc. can have that  | -- I don't know how optValuesForConstructor etc. can have that | ||||||
| -- type signature with these, but it works.. | -- type signature with these, but it works.. | ||||||
| --       | Some Int | --       | Some Int | ||||||
|          | Verbose |          | Verbose | ||||||
| @ -112,7 +112,7 @@ parseargs as = | |||||||
|     (_,_,errs)     -> error (concat errs ++ usage) |     (_,_,errs)     -> error (concat errs ++ usage) | ||||||
| 
 | 
 | ||||||
| optValueWithDefault :: (String -> Opt) -> String -> [Opt] -> String | optValueWithDefault :: (String -> Opt) -> String -> [Opt] -> String | ||||||
| optValueWithDefault optcons def opts =  | optValueWithDefault optcons def opts = | ||||||
|     last $ def : optValuesForConstructor optcons opts |     last $ def : optValuesForConstructor optcons opts | ||||||
| 
 | 
 | ||||||
| optValuesForConstructor :: (String -> Opt) -> [Opt] -> [String] | optValuesForConstructor :: (String -> Opt) -> [Opt] -> [String] | ||||||
| @ -127,13 +127,13 @@ main = do | |||||||
|   tests <- liftM (filter istest . lines) (readFile file) |   tests <- liftM (filter istest . lines) (readFile file) | ||||||
|   now <- getCurrentTime |   now <- getCurrentTime | ||||||
|   putStrLn $ printf "Using %s" file |   putStrLn $ printf "Using %s" file | ||||||
|   putStrLn $ printf "Running %d tests %d times with %d executables at %s:"  |   putStrLn $ printf "Running %d tests %d times with %d executables at %s:" | ||||||
|                (length tests) num (length exes) (show now) |                (length tests) num (length exes) (show now) | ||||||
|   let doexe t e = mapM (doiteration opts t e) [1..num] |   let doexe t e = mapM (doiteration opts t e) [1..num] | ||||||
|   let dotest t = mapM (doexe t) exes |   let dotest t = mapM (doexe t) exes | ||||||
|   hSetBuffering stdout NoBuffering |   hSetBuffering stdout NoBuffering | ||||||
|   results <- mapM dotest tests |   results <- mapM dotest tests | ||||||
|   summarise opts tests exes results  |   summarise opts tests exes results | ||||||
| 
 | 
 | ||||||
| istest s = not (null s' || ("#" `isPrefixOf` s')) where s' = clean s | istest s = not (null s' || ("#" `isPrefixOf` s')) where s' = clean s | ||||||
| clean = unwords . words | clean = unwords . words | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ import System.Environment | |||||||
| import Text.Printf | import Text.Printf | ||||||
| 
 | 
 | ||||||
| main = do | main = do | ||||||
|   args <- getArgs  |   args <- getArgs | ||||||
|   let f = head args |   let f = head args | ||||||
|   s <- readFile f |   s <- readFile f | ||||||
|   let ls = lines s |   let ls = lines s | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user