packages feed

hledger 0.25.1 → 0.26

raw patch · 16 files changed

+325/−109 lines, 16 filesdep +criteriondep +timeitdep +unordered-containersdep −regexprdep ~hledgerdep ~hledger-libdep ~shakespearePVP ok

version bump matches the API change (PVP)

Dependencies added: criterion, timeit, unordered-containers

Dependencies removed: regexpr

Dependency ranges changed: hledger, hledger-lib, shakespeare

API changes (from Hackage documentation)

- Hledger.Cli.Options: CliOpts :: RawOpts -> String -> Maybe FilePath -> Maybe FilePath -> Maybe FilePath -> Maybe String -> [String] -> Bool -> Int -> Bool -> Maybe String -> Int -> ReportOpts -> CliOpts
+ Hledger.Cli.Options: CliOpts :: RawOpts -> String -> [FilePath] -> Maybe FilePath -> Maybe FilePath -> Maybe String -> [String] -> Bool -> Int -> Bool -> Maybe String -> Int -> ReportOpts -> CliOpts
- Hledger.Cli.Options: aliasesFromOpts :: CliOpts -> [(AccountName, AccountName)]
+ Hledger.Cli.Options: aliasesFromOpts :: CliOpts -> [AccountAlias]
- Hledger.Cli.Options: file_ :: CliOpts -> Maybe FilePath
+ Hledger.Cli.Options: file_ :: CliOpts -> [FilePath]
- Hledger.Cli.Options: journalFilePathFromOpts :: CliOpts -> IO String
+ Hledger.Cli.Options: journalFilePathFromOpts :: CliOpts -> IO [String]

Files

CHANGES view
@@ -1,9 +1,151 @@ User-visible changes in hledger and hledger-lib.  +0.26 (2015/7/12)++Account aliases:++- Account aliases are once again non-regular-expression-based, by default. (#252)+    +    The regex account aliases added in 0.24 trip up people switching between+    hledger and Ledger. (Also they are currently slow).+    +    This change makes the old non-regex aliases the default; they are+    unsurprising, useful, and pretty close in functionality to Ledger's.+    +    The new regex aliases are still available; they must be enclosed+    in forward slashes. (Ledger effectively ignores these.)+    +Journal format:++- We now parse, and also print, journal entries with no postings, as+  proposed on the mail lists.  These are not well-formed General+  Journal entries/transactions, but here is my rationale:+    +    - Ledger and beancount parse them+    - if they are parsed, they should be printed+    - they provide a convenient way to record (and report) non-transaction events+    - they permit more gradual introduction and learning of the concepts.+      So eg a beginner can keep a simple journal before learning about accounts and postings.++- Trailing whitespace after a `comment` directive is now ignored.++Command-line interface:++- The -f/file option may now be used multiple times. +  This is equivalent to concatenating the input files before running hledger.+  The add command adds entries to the first file specified.++Queries:++- real: (no argument) is now a synonym for real:1++- tag: now matches tag names with a regular expression, like most other queries++- empty: is no longer supported, as it overlaps a bit confusingly with+  amt:0. The --empty flag is still available.++- You can now match on pending status (#250)+    +    A transaction/posting status of ! (pending) was effectively equivalent+    to * (cleared). Now it's a separate state, not matched by --cleared.+    The new Ledger-compatible --pending flag matches it, and so does+    --uncleared.++    The relevant search query terms are now status:*, status:! and+    status: (the old status:1 and status:0 spellings are deprecated).+    +    Since we interpret --uncleared and status: as "any state except cleared",+    it's not currently possible to match things which are neither cleared+    nor pending.++activity:+- activity no longer excludes 0-amount postings by default.++add:+- Don't show quotes around the journal file path in the "Creating..."+  message, for consistency with the subsequent "Adding..." message.++balancesheet:+- Accounts beginning with "debt" or now also recognised as liabilities.++print:+- We now limit the display precision of inferred prices. (#262)+    +    When a transaction posts to two commodities without specifying the+    conversion price, we generate a price which makes it balance (cf+    http://hledger.org/manual.html#prices). The print command showed+    this with full precision (so that manual calculations with the+    displayed numbers would look right), but this sometimes meant we+    showed 255 digits (when there are multiple postings in the+    commodity being priced, and the averaged unit price is an+    irrational number). In this case we now set the price's display+    precision to the sum of the (max) display precisions of the+    commodities involved. An example:+    +    hledgerdev -f- print+    <<<+    1/1+        c    C 10.00+        c    C 11.00+        d  D -320.00+    >>>+    2015/01/01+        c  C 10.00 @ D 15.2381+        c  C 11.00 @ D 15.2381+        d     D -320.00+    +    >>>=0+    +    There might still be cases where this will show more price decimal+    places than necessary. ++- We now show inferred unit prices with at least 2 decimal places.+    +    When inferring prices, if the commodities involved have low+    display precisions, we don't do a good job of rendering+    accurate-looking unit prices. Eg if the journal doesn't use any+    decimal places, any inferred unit prices are also displayed with+    no decimal places, which makes them look wrong to the user.  Now,+    we always give inferred unit prices a minimum display precision of+    2, which helps a bit.++register:+- Postings with no amounts could give a runtime error in some obscure case, now fixed.++stats: +- stats now supports -o/--outputfile, like register/balance/print.+- An O(n^2) performance slowdown has been fixed, it's now much faster on large journals.++      +--------------------------------------++--------+--------++      |                                      ||   0.25 |   0.26 |+      +======================================++========+========++      | -f data/100x100x10.journal     stats ||   0.10 |   0.16 |+      | -f data/1000x1000x10.journal   stats ||   0.45 |   0.21 |+      | -f data/10000x1000x10.journal  stats ||  58.92 |   2.16 |+      +--------------------------------------++--------+--------+++Miscellaneous:++- The June 30 day span was not being rendered correctly; fixed. (#272)++- The bench script invoked by "cabal bench" or "stack bench" now runs+  some simple benchmarks.+    +    You can get more accurate benchmark times by running with --criterion.+    This will usually give much the same numbers and takes much longer.+    +    Or with --simplebench, it benchmarks whatever commands are+    configured in bench/default.bench. This mode uses the first+    "hledger" executable in $PATH.++- The deprecated shakespeare-text dependency has been removed more thoroughly.++ 0.25.1 (2015/4/29)  - timelog: support the description field (#247)+  0.25 (2015/4/7) 
Hledger/Cli.hs view
@@ -346,7 +346,7 @@              tsourcepos=nullsourcepos,              tdate=parsedate "2007/01/01",              tdate2=Nothing,-             tstatus=False,+             tstatus=Uncleared,              tcode="*",              tdescription="opening balance",              tcomment="",@@ -362,7 +362,7 @@              tsourcepos=nullsourcepos,              tdate=parsedate "2007/02/01",              tdate2=Nothing,-             tstatus=False,+             tstatus=Uncleared,              tcode="*",              tdescription="ayres suites",              tcomment="",@@ -378,7 +378,7 @@              tsourcepos=nullsourcepos,              tdate=parsedate "2007/01/02",              tdate2=Nothing,-             tstatus=False,+             tstatus=Uncleared,              tcode="*",              tdescription="auto transfer to savings",              tcomment="",@@ -394,7 +394,7 @@              tsourcepos=nullsourcepos,              tdate=parsedate "2007/01/03",              tdate2=Nothing,-             tstatus=False,+             tstatus=Uncleared,              tcode="*",              tdescription="poquito mas",              tcomment="",@@ -410,7 +410,7 @@              tsourcepos=nullsourcepos,              tdate=parsedate "2007/01/03",              tdate2=Nothing,-             tstatus=False,+             tstatus=Uncleared,              tcode="*",              tdescription="verizon",              tcomment="",@@ -426,7 +426,7 @@              tsourcepos=nullsourcepos,              tdate=parsedate "2007/01/03",              tdate2=Nothing,-             tstatus=False,+             tstatus=Uncleared,              tcode="*",              tdescription="discover",              tcomment="",
Hledger/Cli/Accounts.hs view
@@ -49,10 +49,10 @@ accounts CliOpts{reportopts_=ropts} j = do   d <- getCurrentDay   let q = queryFromOpts d ropts-      nodepthq = dbg "nodepthq" $ filterQuery (not . queryIsDepth) q-      depth    = dbg "depth" $ queryDepth $ filterQuery queryIsDepth q-      ps = dbg "ps" $ journalPostings $ filterJournalPostings nodepthq j-      as = dbg "as" $ nub $ filter (not . null) $ map (clipAccountName depth) $ sort $ map paccount ps+      nodepthq = dbg1 "nodepthq" $ filterQuery (not . queryIsDepth) q+      depth    = dbg1 "depth" $ queryDepth $ filterQuery queryIsDepth q+      ps = dbg1 "ps" $ journalPostings $ filterJournalPostings nodepthq j+      as = dbg1 "as" $ nub $ filter (not . null) $ map (clipAccountName depth) $ sort $ map paccount ps       as' | tree_ ropts = expandAccountNames as           | otherwise   = as       render a | tree_ ropts = replicate (2 * (accountNameLevel a - 1)) ' ' ++ accountLeafName a
Hledger/Cli/Add.hs view
@@ -147,7 +147,7 @@       balancedPostingsWizard = do         ps <- postingsWizard es2{esPostings=[]}         let t = nulltransaction{tdate=date-                               ,tstatus=False+                               ,tstatus=Uncleared                                ,tcode=code                                ,tdescription=desc                                ,tcomment=comment@@ -241,11 +241,11 @@    line $ green $ printf "Account %d%s%s: " pnum (endmsg::String) (showDefault def)     where       canfinish = not (null esPostings) && postingsBalanced esPostings-      parseAccountOrDotOrNull _  _ "."       = dbg $ Just "." -- . always signals end of txn-      parseAccountOrDotOrNull "" True ""     = dbg $ Just ""  -- when there's no default and txn is balanced, "" also signals end of txn-      parseAccountOrDotOrNull def@(_:_) _ "" = dbg $ Just def -- when there's a default, "" means use that-      parseAccountOrDotOrNull _ _ s          = dbg $ either (const Nothing) validateAccount $ runParser (accountnamep <* eof) (jContext esJournal) "" s -- otherwise, try to parse the input as an accountname-      dbg = id -- strace+      parseAccountOrDotOrNull _  _ "."       = dbg1 $ Just "." -- . always signals end of txn+      parseAccountOrDotOrNull "" True ""     = dbg1 $ Just ""  -- when there's no default and txn is balanced, "" also signals end of txn+      parseAccountOrDotOrNull def@(_:_) _ "" = dbg1 $ Just def -- when there's a default, "" means use that+      parseAccountOrDotOrNull _ _ s          = dbg1 $ either (const Nothing) validateAccount $ runParser (accountnamep <* eof) (jContext esJournal) "" s -- otherwise, try to parse the input as an accountname+      dbg1 = id -- strace       validateAccount s | no_new_accounts_ esOpts && not (s `elem` journalAccountNames esJournal) = Nothing                         | otherwise = Just s 
Hledger/Cli/Balance.hs view
@@ -434,7 +434,7 @@                   ++ (if row_total_ opts then ["  Total"] else [])                   ++ (if average_ opts then ["Average"] else [])     items' | empty_ opts = items-           | otherwise   = items -- dbg "2" $ filter (any (not . isZeroMixedAmount) . snd) $ dbg "1" items+           | otherwise   = items -- dbg1 "2" $ filter (any (not . isZeroMixedAmount) . snd) $ dbg1 "1" items     accts = map renderacct items'     renderacct ((a,a',i),_,_,_)       | tree_ opts = replicate ((i-1)*2) ' ' ++ a'
Hledger/Cli/Histogram.hs view
@@ -13,10 +13,8 @@ import System.Console.CmdArgs.Explicit import Text.Printf +import Hledger import Hledger.Cli.Options-import Hledger.Data-import Hledger.Reports-import Hledger.Query import Prelude hiding (putStr) import Hledger.Utils.UTF8IOCompat (putStr) @@ -54,10 +52,7 @@       -- same as Register       -- should count transactions, not postings ?       -- ps = sortBy (comparing postingDate) $ filterempties $ filter matchapats $ filterdepth $ journalPostings j-      ps = sortBy (comparing postingDate) $ filterempties $ filter (q `matchesPosting`) $ journalPostings j-      filterempties-          | queryEmpty q = id-          | otherwise = filter (not . isZeroMixedAmount . pamount)+      ps = sortBy (comparing postingDate) $ filter (q `matchesPosting`) $ journalPostings j  printDayWith f (DateSpan b _, ps) = printf "%s %s\n" (show $ fromJust b) (f ps) 
Hledger/Cli/Main.hs view
@@ -199,15 +199,15 @@     isNullCommand        = null rawcmd     (argsbeforecmd, argsaftercmd') = break (==rawcmd) args     argsaftercmd         = drop 1 argsaftercmd'-    dbgM :: Show a => String -> a -> IO ()-    dbgM = dbgAtM 2+    dbgIO :: Show a => String -> a -> IO ()+    dbgIO = tracePrettyAtIO 2 -  dbgM "running" prognameandversion-  dbgM "raw args" args-  dbgM "raw args rearranged for cmdargs" args'-  dbgM "raw command is probably" rawcmd-  dbgM "raw args before command" argsbeforecmd-  dbgM "raw args after command" argsaftercmd+  dbgIO "running" prognameandversion+  dbgIO "raw args" args+  dbgIO "raw args rearranged for cmdargs" args'+  dbgIO "raw command is probably" rawcmd+  dbgIO "raw args before command" argsbeforecmd+  dbgIO "raw args after command" argsaftercmd    -- Search PATH for add-ons, excluding any that match built-in names.   -- The precise addon names (including file extension) are used for command@@ -231,32 +231,32 @@     generalHelp          = putStr $ showModeHelp $ mainmode addonDisplayNames     badCommandError      = error' ("command "++rawcmd++" is not recognized, run with no command to see a list") >> exitFailure     f `orShowHelp` mode  = if hasHelp args then putStr (showModeHelp mode) else f-  dbgM "processed opts" opts-  dbgM "command matched" cmd-  dbgM "isNullCommand" isNullCommand-  dbgM "isInternalCommand" isInternalCommand-  dbgM "isExternalCommand" isExternalCommand-  dbgM "isBadCommand" isBadCommand+  dbgIO "processed opts" opts+  dbgIO "command matched" cmd+  dbgIO "isNullCommand" isNullCommand+  dbgIO "isInternalCommand" isInternalCommand+  dbgIO "isExternalCommand" isExternalCommand+  dbgIO "isBadCommand" isBadCommand   d <- getCurrentDay-  dbgM "date span from opts" (dateSpanFromOpts d $ reportopts_ opts)-  dbgM "interval from opts" (intervalFromOpts $ reportopts_ opts)-  dbgM "query from opts & args" (queryFromOpts d $ reportopts_ opts)+  dbgIO "date span from opts" (dateSpanFromOpts d $ reportopts_ opts)+  dbgIO "interval from opts" (intervalFromOpts $ reportopts_ opts)+  dbgIO "query from opts & args" (queryFromOpts d $ reportopts_ opts)   let     runHledgerCommand       -- high priority flags and situations. --help should be highest priority.-      | hasHelp argsbeforecmd    = dbgM "" "--help before command, showing general help" >> generalHelp+      | hasHelp argsbeforecmd    = dbgIO "" "--help before command, showing general help" >> generalHelp       | not (hasHelp argsaftercmd) && (hasVersion argsbeforecmd || (hasVersion argsaftercmd && isInternalCommand))                                  = putStrLn prognameandversion       | not (hasHelp argsaftercmd) && (hasDetailedVersion argsbeforecmd || (hasDetailedVersion argsaftercmd && isInternalCommand))                                  = putStrLn prognameanddetailedversion       -- \| (null externalcmd) && "binary-filename" `inRawOpts` rawopts = putStrLn $ binaryfilename progname       -- \| "--browse-args" `elem` args     = System.Console.CmdArgs.Helper.execute "cmdargs-browser" mainmode' args >>= (putStr . show)-      | isNullCommand            = dbgM "" "no command, showing general help" >> generalHelp+      | isNullCommand            = dbgIO "" "no command, showing general help" >> generalHelp       | isBadCommand             = badCommandError        -- internal commands       | cmd == "activity"        = withJournalDo opts histogram       `orShowHelp` activitymode-      | cmd == "add"             = (journalFilePathFromOpts opts >>= ensureJournalFileExists >> withJournalDo opts add) `orShowHelp` addmode+      | cmd == "add"             = (journalFilePathFromOpts opts >>= (ensureJournalFileExists . head) >> withJournalDo opts add) `orShowHelp` addmode       | cmd == "accounts"        = withJournalDo opts accounts        `orShowHelp` accountsmode       | cmd == "balance"         = withJournalDo opts balance         `orShowHelp` balancemode       | cmd == "balancesheet"    = withJournalDo opts balancesheet    `orShowHelp` balancesheetmode@@ -271,9 +271,9 @@       | isExternalCommand = do           let externalargs = argsbeforecmd ++ filter (not.(=="--")) argsaftercmd           let shellcmd = printf "%s-%s %s" progname cmd (unwords' externalargs) :: String-          dbgM "external command selected" cmd-          dbgM "external command arguments" (map quoteIfNeeded externalargs)-          dbgM "running shell command" shellcmd+          dbgIO "external command selected" cmd+          dbgIO "external command arguments" (map quoteIfNeeded externalargs)+          dbgIO "running shell command" shellcmd           system shellcmd >>= exitWith        -- deprecated commands
Hledger/Cli/Options.hs view
@@ -64,6 +64,7 @@ import qualified Control.Exception as C import Control.Monad (when) import Data.List.Compat+import Data.List.Split (splitOneOf) import Data.Maybe import Safe import System.Console.CmdArgs@@ -121,8 +122,9 @@  ,flagReq  ["period","p"]    (\s opts -> Right $ setopt "period" s opts) "PERIODEXP" "set start date, end date, and/or reporting interval all at once (overrides the flags above)"  ,flagNone ["date2","aux-date"] (setboolopt "date2") "use postings/txns' secondary dates instead" - ,flagNone ["cleared","C"]   (setboolopt "cleared") "include only pending/cleared postings/txns"- ,flagNone ["uncleared","U"] (setboolopt "uncleared") "include only uncleared postings/txns"+ ,flagNone ["cleared","C"]   (setboolopt "cleared") "include only cleared postings/txns"+ ,flagNone ["pending"]       (setboolopt "pending") "include only pending postings/txns"+ ,flagNone ["uncleared","U"] (setboolopt "uncleared") "include only uncleared (and pending) postings/txns"  ,flagNone ["real","R"]      (setboolopt "real") "include only non-virtual postings"  ,flagReq  ["depth"]         (\s opts -> Right $ setopt "depth" s opts) "N" "hide accounts/postings deeper than N"  ,flagNone ["empty","E"]     (setboolopt "empty") "show empty/zero things which are normally omitted"@@ -248,7 +250,7 @@ data CliOpts = CliOpts {      rawopts_         :: RawOpts     ,command_         :: String-    ,file_            :: Maybe FilePath+    ,file_            :: [FilePath]     ,rules_file_      :: Maybe FilePath     ,output_file_     :: Maybe FilePath     ,output_format_   :: Maybe String@@ -309,7 +311,7 @@   return defcliopts {               rawopts_         = rawopts              ,command_         = stringopt "command" rawopts-             ,file_            = maybestringopt "file" rawopts+             ,file_            = map stripquotes $ listofstringopt "file" rawopts              ,rules_file_      = maybestringopt "rules-file" rawopts              ,output_file_     = maybestringopt "output-file" rawopts              ,output_format_   = maybestringopt "output-format" rawopts@@ -360,26 +362,22 @@ -- CliOpts accessors  -- | Get the account name aliases from options, if any.-aliasesFromOpts :: CliOpts -> [(AccountName,AccountName)]-aliasesFromOpts = map parseAlias . alias_-    where-      -- similar to ledgerAlias-      parseAlias :: String -> (AccountName,AccountName)-      parseAlias s = (accountNameWithoutPostingType $ strip orig-                     ,accountNameWithoutPostingType $ strip alias')-          where-            (orig, alias) = break (=='=') s-            alias' = case alias of ('=':rest) -> rest-                                   _ -> orig+aliasesFromOpts :: CliOpts -> [AccountAlias]+aliasesFromOpts = map (\a -> fromparse $ runParser accountaliasp () ("--alias "++quoteIfNeeded a) a)+                  . alias_  -- | Get the (tilde-expanded, absolute) journal file path from -- 1. options, 2. an environment variable, or 3. the default.-journalFilePathFromOpts :: CliOpts -> IO String+-- Actually, returns one or more file paths. There will be more+-- than one if multiple -f options were provided.+journalFilePathFromOpts :: CliOpts -> IO [String] journalFilePathFromOpts opts = do   f <- defaultJournalPath   d <- getCurrentDirectory-  expandPath d $ fromMaybe f $ file_ opts-+  mapM (expandPath d) $ ifEmpty (file_ opts) [f]+ where+    ifEmpty [] d = d+    ifEmpty l _ = l  -- | Get the expanded, absolute output file path from options, -- or the default (-, meaning stdout).@@ -521,7 +519,7 @@ -- directory) or whether it has execute permission. hledgerExecutablesInPath :: IO [String] hledgerExecutablesInPath = do-  pathdirs <- regexSplit "[:;]" `fmap` getEnvSafe "PATH"+  pathdirs <- splitOneOf "[:;]" `fmap` getEnvSafe "PATH"   pathfiles <- concat `fmap` mapM getDirectoryContentsSafe pathdirs   return $ nub $ sort $ filter isHledgerExeName pathfiles   -- XXX should exclude directories and files without execute permission.
Hledger/Cli/Print.hs view
@@ -100,7 +100,7 @@     description = tdescription t     date = showDate (tdate t)     date2 = maybe "" showDate (tdate2 t)-    status = if tstatus t then "*" else ""+    status = show $ tstatus t     code = tcode t     comment = chomp $ strip $ tcomment t @@ -116,7 +116,7 @@    amounts   where     Mixed amounts = pamount p-    status = if pstatus p then "*" else ""+    status = show $ pstatus p     account = showAccountName Nothing (ptype p) (paccount p)     comment = chomp $ strip $ pcomment p 
Hledger/Cli/Register.hs view
@@ -149,9 +149,12 @@                                _                      -> (id,acctwidth)       amt = showMixedAmountWithoutPrice $ pamount p       bal = showMixedAmountWithoutPrice b+      -- alternate behaviour, show null amounts as 0 instead of blank+      -- amt = if null amt' then "0" else amt'+      -- bal = if null bal' then "0" else bal'       (amtlines, ballines) = (lines amt, lines bal)       (amtlen, ballen) = (length amtlines, length ballines)-      numlines = max amtlen ballen+      numlines = max 1 (max amtlen ballen)       (amtfirstline:amtrest) = take numlines $ amtlines ++ repeat "" -- posting amount is top-aligned       (balfirstline:balrest) = take numlines $ replicate (numlines - ballen) "" ++ ballines -- balance amount is bottom-aligned       spacer = replicate (totalwidth - (amtwidth + 2 + balwidth)) ' '
Hledger/Cli/Stats.hs view
@@ -13,6 +13,8 @@ import Data.List import Data.Maybe import Data.Ord+import Data.HashSet (size, fromList)+import Data.Text (pack) import Data.Time.Calendar import System.Console.CmdArgs.Explicit import Text.Printf@@ -21,13 +23,15 @@ import Hledger import Hledger.Cli.Options import Prelude hiding (putStr)-import Hledger.Utils.UTF8IOCompat (putStr)+import Hledger.Cli.Utils (writeOutput)   statsmode = (defCommandMode $ ["stats"] ++ aliases) {   modeHelp = "show some journal statistics" `withAliases` aliases  ,modeGroupFlags = Group {-     groupUnnamed = []+     groupUnnamed = [+        flagReq  ["output-file","o"]   (\s opts -> Right $ setopt "output-file" s opts) "FILE[.FMT]" "write output to FILE instead of stdout. A recognised FMT suffix influences the format."+        ]     ,groupHidden = []     ,groupNamed = [generalflagsgroup1]     }@@ -37,7 +41,7 @@ -- like Register.summarisePostings -- | Print various statistics for the journal. stats :: CliOpts -> Journal -> IO ()-stats CliOpts{reportopts_=reportopts_} j = do+stats opts@CliOpts{reportopts_=reportopts_} j = do   d <- getCurrentDay   let q = queryFromOpts d reportopts_       l = ledgerFromJournal q j@@ -45,7 +49,7 @@       intervalspans = splitSpan (intervalFromOpts reportopts_) reportspan       showstats = showLedgerStats l d       s = intercalate "\n" $ map showstats intervalspans-  putStr s+  writeOutput opts s  showLedgerStats :: Ledger -> Day -> DateSpan -> String showLedgerStats l today span =@@ -63,7 +67,7 @@         ,("Transactions", printf "%d (%0.1f per day)" tnum txnrate)         ,("Transactions last 30 days", printf "%d (%0.1f per day)" tnum30 txnrate30)         ,("Transactions last 7 days", printf "%d (%0.1f per day)" tnum7 txnrate7)-        ,("Payees/descriptions", show $ length $ nub $ map tdescription ts)+        ,("Payees/descriptions", show $ size $ fromList $ map (pack . tdescription) ts)         ,("Accounts", printf "%d (depth %d)" acctnum acctdepth)         ,("Commodities", printf "%s (%s)" (show $ length cs) (intercalate ", " cs))       -- Transactions this month     : %(monthtxns)s (last month in the same period: %(lastmonthtxns)s)
Hledger/Cli/Utils.hs view
@@ -68,7 +68,7 @@   -- to let the add command work.   rulespath <- rulesFilePathFromOpts opts   journalpath <- journalFilePathFromOpts opts-  ej <- readJournalFile Nothing rulespath (not $ ignore_assertions_ opts) journalpath+  ej <- readJournalFiles Nothing rulespath (not $ ignore_assertions_ opts) journalpath   either error' (cmd opts . journalApplyAliases (aliasesFromOpts opts)) ej  -- | Write some output to stdout or to a file selected by --output-file.
+ bench/bench.hs view
@@ -0,0 +1,70 @@+-- bench+-- By default, show approximate times for some standard hledger operations on a sample journal.+-- With --criterion, show accurate times (slow).+-- With --simplebench, show approximate times for the commands in default.bench, using the first hledger executable on $PATH.++import Criterion.Main     (defaultMainWith, defaultConfig, bench, nfIO)+import SimpleBench        (defaultMain)+import System.Directory   (getCurrentDirectory)+import System.Environment (getArgs, withArgs)+import System.Info        (os)+import System.Process     (readProcess)+import System.TimeIt      (timeItT)+import Text.Printf+import Hledger.Cli++-- sample journal file to use for benchmarks+inputfile = "bench/10000x1000x10.journal"++outputfile = "/dev/null" -- hide output of benchmarked commands (XXX unixism)+-- outputfile = "-" -- show output of benchmarked commands++main = do+ -- withArgs ["--simplebench"] $ do+ -- withArgs ["--criterion"] $ do+  args <- getArgs+  if "--criterion" `elem` args+    then withArgs [] benchWithCriterion+    else if "--simplebench" `elem` args+         then benchWithSimplebench+         else benchWithTimeit++benchWithTimeit = do+  getCurrentDirectory >>= printf "Benchmarking hledger in %s with timeit\n"+  let opts = defcliopts{output_file_=Just outputfile}+  (t0,j) <- timeit ("read "++inputfile) $ either error id <$> readJournalFile Nothing Nothing True inputfile+  (t1,_) <- timeit ("print") $ print' opts j+  (t2,_) <- timeit ("register") $ register opts j+  (t3,_) <- timeit ("balance") $ balance  opts j+  (t4,_) <- timeit ("stats") $ stats opts j+  printf "Total: %0.2fs\n" (sum [t0,t1,t2,t3,t4])++timeit :: String -> IO a -> IO (Double, a)+timeit name action = do+  printf "%s%s" name (replicate (40 - length name) ' ')+  (t,a) <- timeItT action+  printf "[%.2fs]\n" t+  return (t,a)++benchWithCriterion = do+  getCurrentDirectory >>= printf "Benchmarking hledger in %s with criterion\n"+  let opts = defcliopts{output_file_=Just "/dev/null"}+  j <- either error id <$> readJournalFile Nothing Nothing True inputfile+  Criterion.Main.defaultMainWith defaultConfig $ [+    bench ("read "++inputfile) $ nfIO $ (either error const <$> readJournalFile Nothing Nothing True inputfile),+    bench ("print")            $ nfIO $ print'   opts j,+    bench ("register")         $ nfIO $ register opts j,+    bench ("balance")          $ nfIO $ balance  opts j,+    bench ("stats")            $ nfIO $ stats    opts j+    ]++benchWithSimplebench = do+  let whichcmd = if os == "mingw32" then "where" else "which"+  exe <- init <$> readProcess whichcmd ["hledger"] ""+  pwd <- getCurrentDirectory+  printf "Benchmarking %s in %s with simplebench and shell\n" exe pwd+  flip withArgs SimpleBench.defaultMain [+     "-fbench/default.bench"+    ,"-v"+    ,"hledger"+    ] 
hledger.cabal view
@@ -1,5 +1,5 @@ name:           hledger-version: 0.25.1+version: 0.26 stability:      stable category:       Finance, Console synopsis:       The main command-line interface for the hledger accounting tool.@@ -17,22 +17,16 @@ maintainer:     Simon Michael <simon@joyful.com> homepage:       http://hledger.org bug-reports:    http://hledger.org/bugs-tested-with:    GHC==7.8.2, GHC==7.10.1+tested-with:    GHC==7.8.4, GHC==7.10.1 cabal-version:  >= 1.10 build-type:     Simple -- data-dir:       data -- data-files: extra-tmp-files: extra-source-files: -                    tests/suite.hs+                    test/test.hs                     CHANGES --- Cabal-Version:  >= 1.9.2--- Test-Suite test-hledger---     type:       exitcode-stdio-1.0---     main-is:    test-hledger.hs---     build-depends: base- source-repository head   type:     git   location: https://github.com/simonmichael/hledger@@ -53,7 +47,7 @@   library-  cpp-options: -DVERSION="0.25.1"+  cpp-options: -DVERSION="0.26"   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures   ghc-options: -fno-warn-type-defaults -fno-warn-orphans   default-language: Haskell2010@@ -75,11 +69,12 @@                   Hledger.Cli.Register                   Hledger.Cli.Stats   build-depends:-                  hledger-lib == 0.25.1+                  hledger-lib == 0.26                  ,base >= 4.3 && < 5                  ,base-compat >= 0.8.1                  -- ,cabal-file-th                  ,containers+                 ,unordered-containers                  ,cmdargs >= 0.10 && < 0.11                  ,csv                  -- ,data-pprint >= 0.2.1 && < 0.3@@ -93,7 +88,6 @@                  ,parsec >= 3                  ,process                  ,regex-tdfa-                 ,regexpr >= 0.5.1                  ,safe >= 0.2                  ,split >= 0.1 && < 0.3                  ,text >= 0.11@@ -104,7 +98,7 @@     -- ghc 7.10 requires shakespeare 2.0.2.2+     build-depends: shakespeare      >= 2.0.2.2 && < 2.1   else-    -- for older ghcs, allow shakespeare 2.x or 1.x (which also requires shakespeare-text)+    -- for older ghcs, allow shakespeare 1.x (which also requires shakespeare-text)     -- http://www.yesodweb.com/blog/2014/04/consolidation-progress     build-depends:                   shakespeare      >= 1.0 && < 2.1@@ -123,18 +117,19 @@   main-is:        hledger-cli.hs   hs-source-dirs: app   default-language: Haskell2010-  cpp-options: -DVERSION="0.25.1"+  cpp-options: -DVERSION="0.26"   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures   ghc-options: -fno-warn-type-defaults -fno-warn-orphans   if flag(threaded)        ghc-options:   -threaded   -- same as above:   build-depends:-                  hledger-lib == 0.25.1-                 ,hledger == 0.25.1+                  hledger-lib == 0.26+                 ,hledger == 0.26                  ,base >= 4.3 && < 5                  ,base-compat >= 0.8.1                  ,containers+                 ,unordered-containers                  ,cmdargs >= 0.10 && < 0.11                  ,csv                  -- ,data-pprint >= 0.2.1 && < 0.3@@ -148,15 +143,19 @@                  ,parsec >= 3                  ,process                  ,regex-tdfa-                 ,regexpr >= 0.5.1                  ,safe >= 0.2-                 ,shakespeare-text >= 1.0 && < 1.2-                 ,shakespeare      >= 1.0 && < 2.1                  ,split >= 0.1 && < 0.3                  ,tabular >= 0.2 && < 0.3                  ,text >= 0.11                  ,utf8-string >= 0.3.5 && < 1.1                  ,wizards == 1.0.*+  -- as above+  if impl(ghc >= 7.10)+    build-depends: shakespeare      >= 2.0.2.2 && < 2.1+  else+    build-depends:+                  shakespeare      >= 1.0 && < 2.1+                 ,shakespeare-text >= 1.0 && < 1.2   if flag(old-locale)     build-depends: time < 1.5, old-locale   else@@ -165,10 +164,10 @@     build-depends: pretty-show >= 1.6.4  -test-suite tests+test-suite test   type:     exitcode-stdio-1.0-  main-is:  suite.hs-  hs-source-dirs: tests+  main-is:  test.hs+  hs-source-dirs: test   default-language: Haskell2010   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures   ghc-options: -fno-warn-type-defaults -fno-warn-orphans@@ -191,10 +190,7 @@                , parsec >= 3                , process                , regex-tdfa-               , regexpr                , safe-               , shakespeare-text >= 1.0 && < 1.2-               , shakespeare      >= 1.0 && < 2.1                , split                ,tabular >= 0.2 && < 0.3                , test-framework@@ -202,6 +198,13 @@                , text                , transformers                , wizards == 1.0.*+  -- as above+  if impl(ghc >= 7.10)+    build-depends: shakespeare      >= 2.0.2.2 && < 2.1+  else+    build-depends:+                  shakespeare      >= 1.0 && < 2.1+                 ,shakespeare-text >= 1.0 && < 1.2   if impl(ghc >= 7.4)     build-depends: pretty-show >= 1.6.4   if flag(old-locale)@@ -210,11 +213,10 @@     build-depends: time >= 1.5  --- not a standard cabal bench test, I think benchmark bench   type:             exitcode-stdio-1.0-  -- hs-source-dirs:   -  main-is:          ../tools/simplebench.hs+  hs-source-dirs:   bench+  main-is:          bench.hs   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures   ghc-options: -fno-warn-type-defaults -fno-warn-orphans   default-language: Haskell2010@@ -222,8 +224,10 @@                     hledger,                     base >= 4.3 && < 5,                     base-compat >= 0.8.1,+                    criterion,                     html,                     tabular >= 0.2 && < 0.3,+                    timeit,                     process,                     filepath,                     directory
+ test/test.hs view
@@ -0,0 +1,6 @@+import Hledger.Cli (tests_Hledger_Cli)+import Test.Framework.Providers.HUnit (hUnitTestToTests)+import Test.Framework.Runners.Console (defaultMain)++main :: IO ()+main = defaultMain $ hUnitTestToTests tests_Hledger_Cli
− tests/suite.hs
@@ -1,6 +0,0 @@-import Hledger.Cli (tests_Hledger_Cli)-import Test.Framework.Providers.HUnit (hUnitTestToTests)-import Test.Framework.Runners.Console (defaultMain)--main :: IO ()-main = defaultMain $ hUnitTestToTests tests_Hledger_Cli