packages feed

hledger 0.24.1 → 0.25

raw patch · 7 files changed

+335/−165 lines, 7 filesdep +base-compatdep +mtl-compatdep +terminfodep ~hledgerdep ~hledger-libdep ~shakespearePVP ok

version bump matches the API change (PVP)

Dependencies added: base-compat, mtl-compat, terminfo

Dependency ranges changed: hledger, hledger-lib, shakespeare, time

API changes (from Hackage documentation)

- Hledger.Cli.Options: Auto :: Width
- Hledger.Cli.Options: FieldWidths :: [Width] -> OutputWidth
- Hledger.Cli.Options: TotalWidth :: Width -> OutputWidth
- Hledger.Cli.Options: Width :: Int -> Width
- Hledger.Cli.Options: data OutputWidth
- Hledger.Cli.Options: data Width
- Hledger.Cli.Options: defaultWidthWithFlag :: Int
- Hledger.Cli.Options: instance Show OutputWidth
- Hledger.Cli.Options: instance Show Width
+ Hledger.Cli.Options: available_width_ :: CliOpts -> Int
+ Hledger.Cli.Options: registerWidthsFromOpts :: CliOpts -> (Int, Maybe Int)
- Hledger.Cli.Options: CliOpts :: RawOpts -> String -> Maybe FilePath -> Maybe FilePath -> Maybe FilePath -> Maybe String -> [String] -> Bool -> Int -> Bool -> Maybe String -> ReportOpts -> CliOpts
+ 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: widthFromOpts :: CliOpts -> Either String OutputWidth
+ Hledger.Cli.Options: widthFromOpts :: CliOpts -> Int

Files

CHANGES view
@@ -1,10 +1,83 @@-User-visible changes in hledger (see also hledger-lib):+User-visible changes in hledger and hledger-lib. ++0.25 (2015/4/7)++- GHC 7.10 compatibility (#239)++- build with terminfo support on POSIX systems by default+    +    On non-windows systems, we now build with terminfo support by+    default, useful for detecting terminal width and other things.++    This requires the C curses dev libaries, which makes POSIX+    installation slightly harder; if it causes problems you can+    disable terminfo support with the new `curses` cabal flag, eg:+    cabal install -f-curses ... (or cabal might try this+    automatically, I'm not sure).++- register: use the full terminal width, respect COLUMNS, allow column width adjustment+    +    On POSIX systems, register now uses the full terminal width by+    default. Specifically, the output width is set from:+    +    1. a --width option+    2. or a COLUMNS environment variable (NB: not the same as a bash shell var)+    3. or on POSIX (non-windows) systems, the current terminal width+    4. or the default, 80 characters.+    +    Also, register's --width option now accepts an optional+    description column width following the overall width (--width+    WIDTH[,DESCWIDTH]). This also sets the account column width, since+    the available space (WIDTH-41) is divided up between these two+    columns. Here's a diagram:+    +    <--------------------------------- width (W) ---------------------------------->+    date (10)  description (D)       account (W-41-D)     amount (12)   balance (12)+    DDDDDDDDDD dddddddddddddddddddd  aaaaaaaaaaaaaaaaaaa  AAAAAAAAAAAA  AAAAAAAAAAAA+    +    Examples:+    $ hledger reg                 # use terminal width on posix+    $ hledger reg -w 100          # width 100, equal description/account widths+    $ hledger reg -w 100,40       # width 100, wider description+    $ hledger reg -w $COLUMNS,100 # terminal width and set description width++- balance: new -T/--row-total and -A/--average options++  In multicolumn balance reports, -T/--row-total now shows a row totals+  column and -A/--average shows a row averages column.+  This helps eg to see monthly average expenses (hledger bal ^expenses -MA).++  NB our use of -T deviates from Ledger's UI, where -T sets a custom+  final total expression.++- balance: -N is now short for --no-total+- balance: fix partially-visible totals row with --no-total+    +    A periodic (not using --cumulative or --historical) balance report+    with --no-total now hides the totals row properly.++- journal, csv: comment lines can also start with *+    +    As in Ledger. This means you can embed emacs org/outline-mode nodes in+    your journal file and manipulate it like an outline.+ 0.24.1 (2015/3/15) -- timelog: show hours with 2 decimal places, not 1 (#237)-- fix balance accumulation through assertions in several commodities (#195)-- fix rendering of week 52 heading in weekly reports+- journal: fix balance accumulation across assertions (#195)+    +    A sequence of balance assertions asserting first one commodity, then+    another, then the first again, was not working.++- timelog: show hours with two decimal places instead of one (#237)+- in weekly reports, simplify week 52's heading like the others+- disallow trailing garbage in a number of parsers++    Trailing garbage is no longer ignored when parsing the following:+    balance --format option, register --width option, hledger-rewrite+    options, hledger add's inputs, CSV amounts, posting amounts,+    posting dates in tags.+ - allow utf8-string-1 (fpco/stackage/#426)  0.24 (2014/12/25)
Hledger/Cli/Add.hs view
@@ -3,12 +3,14 @@ |-}  {-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-unused-do-bind #-}-{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable, RecordWildCards, TypeOperators, FlexibleContexts #-}+{-# LANGUAGE CPP, ScopedTypeVariables, DeriveDataTypeable, RecordWildCards, TypeOperators, FlexibleContexts #-}  module Hledger.Cli.Add where -import Control.Applicative ((<*))+#if !MIN_VERSION_base(4,8,0)+import Control.Applicative.Compat ((<*))+#endif import Control.Exception as E import Control.Monad import Control.Monad.Trans (liftIO)
Hledger/Cli/Balance.hs view
@@ -261,13 +261,15 @@  ,modeGroupFlags = C.Group {      groupUnnamed = [       flagNone ["tree"] (\opts -> setboolopt "tree" opts) "show accounts as a tree (default in simple reports)"-     ,flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show accounts as a list (default in multicolumn)"+     ,flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show accounts as a list (default in multicolumn mode)"      ,flagReq  ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "flat mode: omit N leading account name parts"      ,flagReq  ["format"] (\s opts -> Right $ setopt "format" s opts) "FORMATSTR" "tree mode: use this custom line format"      ,flagNone ["no-elide"] (\opts -> setboolopt "no-elide" opts) "tree mode: don't squash boring parent accounts"-     ,flagNone ["no-total"] (\opts -> setboolopt "no-total" opts) "don't show the final total"-     ,flagNone ["cumulative"] (\opts -> setboolopt "cumulative" opts) "multicolumn mode: show accumulated ending balances"      ,flagNone ["historical","H"] (\opts -> setboolopt "historical" opts) "multicolumn mode: show historical ending balances"+     ,flagNone ["cumulative"] (\opts -> setboolopt "cumulative" opts) "multicolumn mode: show accumulated ending balances"+     ,flagNone ["average","A"] (\opts -> setboolopt "average" opts) "multicolumn mode: show a row average column"+     ,flagNone ["row-total","T"] (\opts -> setboolopt "row-total" opts) "multicolumn mode: show a row total column"+     ,flagNone ["no-total","N"] (\opts -> setboolopt "no-total" opts) "don't show the final total row"      ]      ++ outputflags     ,groupHidden = []@@ -393,85 +395,124 @@  -- | Render a multi-column balance report as CSV. multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV-multiBalanceReportAsCsv opts (MultiBalanceReport (colspans, items, coltotals)) =-  ("account" : "short account" : "indent" : map showDateSpan colspans) :-  [a : a' : show i : map showMixedAmountOneLineWithoutPrice amts | ((a,a',i), amts) <- items]+multiBalanceReportAsCsv opts (MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =+  ("account" : "short account" : "indent" : map showDateSpan colspans+   ++ (if row_total_ opts then ["total"] else [])+   ++ (if average_ opts then ["average"] else [])+  ) :+  [a : a' : show i :+   map showMixedAmountOneLineWithoutPrice+   (amts+    ++ (if row_total_ opts then [rowtot] else [])+    ++ (if average_ opts then [rowavg] else []))+  | ((a,a',i), amts, rowtot, rowavg) <- items]   ++   if no_total_ opts   then []-  else [["totals", "", ""] ++ map showMixedAmountOneLineWithoutPrice coltotals]+  else [["totals", "", ""]+        ++ map showMixedAmountOneLineWithoutPrice (+           coltotals+           ++ (if row_total_ opts then [tot] else [])+           ++ (if average_ opts then [avg] else [])+           )]  -- | Render a multi-column period balance report as plain text suitable for console output. periodBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String-periodBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, coltotals)) =+periodBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =   unlines $   ([printf "Balance changes in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $   trimborder $ lines $-   render-    id-    ((" "++) . showDateSpan)-    showMixedAmountOneLineWithoutPrice-    $ Table-      (T.Group NoLine $ map (Header . padright acctswidth) accts)-      (T.Group NoLine $ map Header colspans)-      (map snd items')-    +----+-    totalrow+   render id (" "++) showMixedAmountOneLineWithoutPrice $+    addtotalrow $+     Table+     (T.Group NoLine $ map (Header . padright acctswidth) accts)+     (T.Group NoLine $ map Header colheadings)+     (map rowvals items')   where     trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)+    colheadings = map showDateSpan colspans+                  ++ (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     accts = map renderacct items'-    renderacct ((a,a',i),_)+    renderacct ((a,a',i),_,_,_)       | tree_ opts = replicate ((i-1)*2) ' ' ++ a'       | otherwise  = maybeAccountNameDrop opts a     acctswidth = maximum $ map length $ accts-    totalrow | no_total_ opts = row "" []-             | otherwise      = row "" coltotals+    rowvals (_,as,rowtot,rowavg) = as+                                   ++ (if row_total_ opts then [rowtot] else [])+                                   ++ (if average_ opts then [rowavg] else [])+    addtotalrow | no_total_ opts = id+                | otherwise      = (+----+ (row "" $+                                    coltotals+                                    ++ (if row_total_ opts then [tot] else [])+                                    ++ (if average_ opts then [avg] else [])+                                    ))  -- | Render a multi-column cumulative balance report as plain text suitable for console output. cumulativeBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String-cumulativeBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, coltotals)) =+cumulativeBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =   unlines $   ([printf "Ending balances (cumulative) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $   trimborder $ lines $-   render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $+   render id (" "++) showMixedAmountOneLineWithoutPrice $     addtotalrow $      Table        (T.Group NoLine $ map (Header . padright acctswidth) accts)-       (T.Group NoLine $ map Header colspans)-       (map snd items)+       (T.Group NoLine $ map Header colheadings)+       (map rowvals items)   where     trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)+    colheadings = map (maybe "" (showDate . prevday) . spanEnd) colspans+                  ++ (if row_total_ opts then ["  Total"] else [])+                  ++ (if average_ opts then ["Average"] else [])     accts = map renderacct items-    renderacct ((a,a',i),_)+    renderacct ((a,a',i),_,_,_)       | tree_ opts = replicate ((i-1)*2) ' ' ++ a'       | otherwise  = maybeAccountNameDrop opts a     acctswidth = maximum $ map length $ accts+    rowvals (_,as,rowtot,rowavg) = as+                                   ++ (if row_total_ opts then [rowtot] else [])+                                   ++ (if average_ opts then [rowavg] else [])     addtotalrow | no_total_ opts = id-                | otherwise      = (+----+ row "" coltotals)+                | otherwise      = (+----+ (row "" $+                                    coltotals+                                    ++ (if row_total_ opts then [tot] else [])+                                    ++ (if average_ opts then [avg] else [])+                                    ))  -- | Render a multi-column historical balance report as plain text suitable for console output. historicalBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String-historicalBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, coltotals)) =+historicalBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =   unlines $   ([printf "Ending balances (historical) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $   trimborder $ lines $-   render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $+   render id (" "++) showMixedAmountOneLineWithoutPrice $     addtotalrow $      Table        (T.Group NoLine $ map (Header . padright acctswidth) accts)-       (T.Group NoLine $ map Header colspans)-       (map snd items)+       (T.Group NoLine $ map Header colheadings)+       (map rowvals items)   where     trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)+    colheadings = map (maybe "" (showDate . prevday) . spanEnd) colspans+                  ++ (if row_total_ opts then ["  Total"] else [])+                  ++ (if average_ opts then ["Average"] else [])     accts = map renderacct items-    renderacct ((a,a',i),_)+    renderacct ((a,a',i),_,_,_)       | tree_ opts = replicate ((i-1)*2) ' ' ++ a'       | otherwise  = maybeAccountNameDrop opts a     acctswidth = maximum $ map length $ accts+    rowvals (_,as,rowtot,rowavg) = as+                             ++ (if row_total_ opts then [rowtot] else [])+                             ++ (if average_ opts then [rowavg] else [])     addtotalrow | no_total_ opts = id-                | otherwise      = (+----+ row "" coltotals)+                | otherwise      = (+----+ (row "" $+                                    coltotals+                                    ++ (if row_total_ opts then [tot] else [])+                                    ++ (if average_ opts then [avg] else [])+                                    ))  -- | Figure out the overall date span of a multicolumn balance report. multiBalanceReportSpan :: MultiBalanceReport -> DateSpan
Hledger/Cli/Options.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE CPP, ScopedTypeVariables, DeriveDataTypeable, FlexibleContexts #-} {-|  Common cmdargs modes and flags, a command-line options type, and@@ -43,12 +42,10 @@   rulesFilePathFromOpts,   outputFileFromOpts,   outputFormatFromOpts,-  -- | For register:-  OutputWidth(..),-  Width(..),   defaultWidth,-  defaultWidthWithFlag,   widthFromOpts,+  -- | For register:+  registerWidthsFromOpts,   maybeAccountNameDrop,   -- | For balance:   lineFormatFromOpts,@@ -62,7 +59,9 @@ ) where -import Control.Applicative ((<$>), (<*))+#if !MIN_VERSION_base(4,8,0)+import Control.Applicative.Compat ((<$>), (<*))+#endif import qualified Control.Exception as C import Control.Monad (when) import Data.List@@ -71,6 +70,9 @@ import System.Console.CmdArgs import System.Console.CmdArgs.Explicit import System.Console.CmdArgs.Text+#ifndef mingw32_HOST_OS+import System.Console.Terminfo+#endif import System.Directory import System.Environment import System.Exit (exitSuccess)@@ -255,7 +257,11 @@     ,ignore_assertions_ :: Bool     ,debug_           :: Int            -- ^ debug level, set by @--debug[=N]@. See also 'Hledger.Utils.debugLevel'.     ,no_new_accounts_ :: Bool           -- add-    ,width_           :: Maybe String   -- register+    ,width_           :: Maybe String   -- ^ the --width value provided, if any+    ,available_width_ :: Int            -- ^ estimated usable screen width, based on+                                        -- 1. the COLUMNS env var, if set+                                        -- 2. the width reported by the terminal, if supported+                                        -- 3. the default (80)     ,reportopts_      :: ReportOpts  } deriving (Show, Data, Typeable) @@ -274,18 +280,33 @@     def     def     def+    defaultWidth     def  -- | Convert possibly encoded option values to regular unicode strings. decodeRawOpts :: RawOpts -> RawOpts decodeRawOpts = map (\(name',val) -> (name', fromSystemString val)) +-- | Default width for hledger console output, when not otherwise specified.+defaultWidth :: Int+defaultWidth = 80+ -- | Parse raw option string values to the desired final data types. -- Any relative smart dates will be converted to fixed dates based on -- today's date. Parsing failures will raise an error.+-- Also records the terminal width, if supported. rawOptsToCliOpts :: RawOpts -> IO CliOpts rawOptsToCliOpts rawopts = do   ropts <- rawOptsToReportOpts rawopts+  mcolumns <- readMay <$> getEnvSafe "COLUMNS"+  mtermwidth <-+#ifdef mingw32_HOST_OS+    return Nothing+#else+    setupTermFromEnv >>= return . flip getCapability termColumns+    -- XXX Throws a SetupTermError if the terminfo database could not be read, should catch+#endif+  let availablewidth = head $ catMaybes [mcolumns, mtermwidth, Just defaultWidth]   return defcliopts {               rawopts_         = rawopts              ,command_         = stringopt "command" rawopts@@ -297,7 +318,8 @@              ,debug_           = intopt "debug" rawopts              ,ignore_assertions_ = boolopt "ignore-assertions" rawopts              ,no_new_accounts_ = boolopt "no-new-accounts" rawopts -- add-             ,width_           = maybestringopt "width" rawopts    -- register+             ,width_           = maybestringopt "width" rawopts+             ,available_width_ = availablewidth              ,reportopts_      = ropts              } @@ -307,9 +329,7 @@   case lineFormatFromOpts ropts of     Left err -> optserror $ "could not parse format option: "++err     Right _ -> return ()-  case widthFromOpts opts of-    Left err -> optserror $ "could not parse width option: "++err-    Right _ -> return ()+  -- XXX check registerWidthsFromOpts opts   return opts  -- Currently only used by some extras/ scripts:@@ -405,6 +425,47 @@   d <- getCurrentDirectory   maybe (return Nothing) (fmap Just . expandPath d) $ rules_file_ opts +-- | Get the width in characters to use for console output.+-- This comes from the --width option, or the COLUMNS environment+-- variable, or (on posix platforms) the current terminal width, or 80.+-- Will raise a parse error for a malformed --width argument.+widthFromOpts :: CliOpts -> Int+widthFromOpts CliOpts{width_=Nothing, available_width_=w} = w+widthFromOpts CliOpts{width_=Just s}  =+    case runParser (read `fmap` many1 digit <* eof) () "(unknown)" s of+        Left e   -> optserror $ "could not parse width option: "++show e+        Right w  -> w++-- for register:++-- | Get the width in characters to use for the register command's console output,+-- and also the description column width if specified (following the main width, comma-separated).+-- The widths will be as follows:+-- @+-- no --width flag - overall width is the available width (COLUMNS, or posix terminal width, or 80); description width is unspecified (auto)+-- --width W       - overall width is W, description width is auto+-- --width W,D     - overall width is W, description width is D+-- @+-- Will raise a parse error for a malformed --width argument.+registerWidthsFromOpts :: CliOpts -> (Int, Maybe Int)+registerWidthsFromOpts CliOpts{width_=Nothing, available_width_=w} = (w, Nothing)+registerWidthsFromOpts CliOpts{width_=Just s}  =+    case runParser registerwidthp () "(unknown)" s of+        Left e   -> optserror $ "could not parse width option: "++show e+        Right ws -> ws+    where+        registerwidthp :: Stream [Char] m t => ParsecT [Char] st m (Int, Maybe Int)+        registerwidthp = do+          totalwidth <- read `fmap` many1 digit+          descwidth <- optionMaybe (char ',' >> read `fmap` many1 digit)+          eof+          return (totalwidth, descwidth)++-- | Drop leading components of accounts names as specified by --drop, but only in --flat mode.+maybeAccountNameDrop :: ReportOpts -> AccountName -> AccountName+maybeAccountNameDrop opts a | tree_ opts = a+                            | otherwise  = accountNameDrop (drop_ opts) a+ -- for balance, currently:  -- | Parse the format option if provided, possibly returning an error,@@ -421,56 +482,6 @@     , FormatField True Nothing Nothing AccountField     ] --- for register:---- | Output width configuration (for register).-data OutputWidth =-    TotalWidth Width    -- ^ specify the overall width-  | FieldWidths [Width] -- ^ specify each field's width-  deriving Show---- | A width value.-data Width =-    Width Int -- ^ set width to exactly this number of characters-  | Auto      -- ^ set width automatically from available space-  deriving Show---- | Default width of hledger console output.-defaultWidth :: Int-defaultWidth = 80---- | Width of hledger console output when the -w flag is used with no value.-defaultWidthWithFlag :: Int-defaultWidthWithFlag = 120---- | Parse the width option if provided, possibly returning an error,--- otherwise get the default value.-widthFromOpts :: CliOpts -> Either String OutputWidth-widthFromOpts CliOpts{width_=Nothing} = Right $ TotalWidth $ Width defaultWidth-widthFromOpts CliOpts{width_=Just ""} = Right $ TotalWidth $ Width defaultWidthWithFlag-widthFromOpts CliOpts{width_=Just s}  = parseWidth s--parseWidth :: String -> Either String OutputWidth-parseWidth s = case (runParser (outputwidthp <* eof) () "(unknown)") s of-    Left  e -> Left $ show e-    Right x -> Right x--outputwidthp :: Stream [Char] m t => ParsecT [Char] st m OutputWidth-outputwidthp =-  try (do w <- widthp-          ws <- many1 (char ',' >> widthp)-          return $ FieldWidths $ w:ws)-  <|> TotalWidth `fmap` widthp--widthp :: Stream [Char] m t => ParsecT [Char] st m Width-widthp = (string "auto" >> return Auto)-    <|> (Width . read) `fmap` many1 digit---- | Drop leading components of accounts names as specified by --drop, but only in --flat mode.-maybeAccountNameDrop :: ReportOpts -> AccountName -> AccountName-maybeAccountNameDrop opts a | tree_ opts = a-                            | otherwise  = accountNameDrop (drop_ opts) a- -- Other utils  -- | Get the sorted unique precise names and display names of hledger@@ -552,7 +563,7 @@   ]  getEnvSafe :: String -> IO String-getEnvSafe v = getEnv v `C.catch` (\(_::C.IOException) -> return "")+getEnvSafe v = getEnv v `C.catch` (\(_::C.IOException) -> return "") -- XXX should catch only isDoesNotExistError e  getDirectoryContentsSafe :: FilePath -> IO [String] getDirectoryContentsSafe d =
Hledger/Cli/Print.hs view
@@ -94,31 +94,31 @@  transactionToCSV :: Integer -> Transaction -> CSV transactionToCSV n t =-	map (\p -> show n:date:date2:status:code:description:comment:p)-	 (concatMap postingToCSV $ tpostings t)-	where-		description = tdescription t-		date = showDate (tdate t)-		date2 = maybe "" showDate (tdate2 t)-		status = if tstatus t then "*" else ""-		code = tcode t-		comment = chomp $ strip $ tcomment t+  map (\p -> show n:date:date2:status:code:description:comment:p)+   (concatMap postingToCSV $ tpostings t)+  where+    description = tdescription t+    date = showDate (tdate t)+    date2 = maybe "" showDate (tdate2 t)+    status = if tstatus t then "*" else ""+    code = tcode t+    comment = chomp $ strip $ tcomment t  postingToCSV :: Posting -> CSV postingToCSV p =-	map (\(a@(Amount {aquantity=q,acommodity=c})) ->-		let a_ = a{acommodity=""} in-		let amount = showAmount a_ in-		let commodity = c in-		let credit = if q < 0 then showAmount $ negate a_ else "" in-		let debit  = if q > 0 then showAmount a_ else "" in-		account:amount:commodity:credit:debit:status:comment:[])-	 amounts-	where-		Mixed amounts = pamount p-		status = if pstatus p then "*" else ""-		account = showAccountName Nothing (ptype p) (paccount p)-		comment = chomp $ strip $ pcomment p+  map (\(a@(Amount {aquantity=q,acommodity=c})) ->+    let a_ = a{acommodity=""} in+    let amount = showAmount a_ in+    let commodity = c in+    let credit = if q < 0 then showAmount $ negate a_ else "" in+    let debit  = if q > 0 then showAmount a_ else "" in+    account:amount:commodity:credit:debit:status:comment:[])+   amounts+  where+    Mixed amounts = pamount p+    status = if pstatus p then "*" else ""+    account = showAccountName Nothing (ptype p) (paccount p)+    comment = chomp $ strip $ pcomment p  tests_Hledger_Cli_Print = TestList []   -- tests_showTransactions
Hledger/Cli/Register.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-|  A ledger-compatible @register@ command.@@ -31,8 +32,17 @@       flagNone ["historical","H"] (\opts -> setboolopt "historical" opts) "include prior postings in the running total"      ,flagNone ["average","A"] (\opts -> setboolopt "average" opts) "show a running average instead of the running total (implies --empty)"      ,flagNone ["related","r"] (\opts -> setboolopt "related" opts) "show postings' siblings instead"-     ,flagReq  ["width","w"] (\s opts -> Right $ setopt "width" s opts) "N" "set output width (default: 80)"-     ]+     ,flagReq  ["width","w"] (\s opts -> Right $ setopt "width" s opts) "N"+      (unlines+       ["set output width (default:"+#ifdef mingw32_HOST_OS+       ,(show defaultWidth)+#else+       ,"terminal width"+#endif+       ,"or COLUMNS. -wN,M sets description width as well)"+       ])+    ]      ++ outputflags     ,groupHidden = []     ,groupNamed = [generalflagsgroup1]@@ -86,12 +96,22 @@  -- | Render one register report line item as plain text. Layout is like so: -- @--- <----------------------------- width (default: 80) ---------------------------->--- date (10)  description (50%)     account (50%)         amount (12)  balance (12)+-- <---------------- width (specified, terminal width, or 80) -------------------->+-- date (10)  description           account              amount (12)   balance (12) -- DDDDDDDDDD dddddddddddddddddddd  aaaaaaaaaaaaaaaaaaa  AAAAAAAAAAAA  AAAAAAAAAAAA+-- @+-- If description's width is specified, account will use the remaining space.+-- Otherwise, description and account divide up the space equally. ----- date and description are shown for the first posting of a transaction only.+-- With a reporting interval, the layout is like so: -- @+-- <---------------- width (specified, terminal width, or 80) -------------------->+-- date (21)              account                        amount (12)   balance (12)+-- DDDDDDDDDDDDDDDDDDDDD  aaaaaaaaaaaaaaaaaaaaaaaaaaaaa  AAAAAAAAAAAA  AAAAAAAAAAAA+-- @+--+-- date and description are shown for the first posting of a transaction only.+-- postingsReportItemAsText :: CliOpts -> PostingsReportItem -> String postingsReportItemAsText opts (mdate, menddate, mdesc, p, b) =   intercalate "\n" $@@ -101,11 +121,8 @@     [printf (spacer ++ "%"++amtw++"s  %"++balw++"s") a b | (a,b) <- zip amtrest balrest ]      where-      totalwidth = case widthFromOpts opts of-           Left _                       -> defaultWidth -- shouldn't happen-           Right (TotalWidth (Width w)) -> w-           Right (TotalWidth Auto)      -> defaultWidth -- XXX-           Right (FieldWidths _)        -> defaultWidth -- XXX+      -- calculate widths+      (totalwidth,mdescwidth) = registerWidthsFromOpts opts       amtwidth = 12       balwidth = 12       (datewidth, date) = case (mdate,menddate) of@@ -114,15 +131,15 @@                             (Just d, Nothing)  -> (10, showDate d)                             _                  -> (10, "")       remaining = totalwidth - (datewidth + 1 + 2 + amtwidth + 2 + balwidth)-      (descwidth, acctwidth) | isJust menddate = (0, remaining-2)-                             | even remaining  = (r2, r2)-                             | otherwise       = (r2, r2+1)+      (descwidth, acctwidth)+        | hasinterval = (0, remaining - 2)+        | otherwise   = (w, remaining - 2 - w)         where-          r2 = (remaining-2) `div` 2+            hasinterval = isJust menddate+            w = fromMaybe ((remaining - 2) `div` 2) mdescwidth       [datew,descw,acctw,amtw,balw] = map show [datewidth,descwidth,acctwidth,amtwidth,balwidth] --+      -- gather content       desc = maybe "" (take descwidth . elideRight descwidth) mdesc       acct = parenthesise $ elideAccountName awidth $ paccount p          where
hledger.cabal view
@@ -1,5 +1,5 @@ name:           hledger-version: 0.24.1+version: 0.25 stability:      stable category:       Finance, Console synopsis:       The main command-line interface for the hledger accounting tool.@@ -17,7 +17,7 @@ maintainer:     Simon Michael <simon@joyful.com> homepage:       http://hledger.org bug-reports:    http://hledger.org/bugs-tested-with:    GHC==7.2.2, GHC==7.4.2, GHC==7.6.3, GHC==7.8.2+tested-with:    GHC==7.8.2, GHC==7.10.1 cabal-version:  >= 1.10 build-type:     Simple -- data-dir:       data@@ -41,9 +41,19 @@     Description:   Build with support for multithreaded execution     Default:       True +flag curses+    Description:   On POSIX systems, enable curses support for auto-detecting terminal width.+    Default:       True +flag old-locale+  description: A compatibility flag, set automatically by cabal.+               If false then depend on time >= 1.5, +               if true then depend on time < 1.5 together with old-locale.+  default: False++ library-  cpp-options: -DVERSION="0.24.1"+  cpp-options: -DVERSION="0.25"   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@@ -65,8 +75,9 @@                   Hledger.Cli.Register                   Hledger.Cli.Stats   build-depends:-                  hledger-lib == 0.24.1+                  hledger-lib == 0.25                  ,base >= 4.3 && < 5+                 ,base-compat >= 0.5.0                  -- ,cabal-file-th                  ,containers                  ,cmdargs >= 0.10 && < 0.11@@ -77,47 +88,52 @@                  ,haskeline >= 0.6 && <= 0.8                  ,HUnit                  ,mtl-                 ,old-locale+                 ,mtl-compat                  ,old-time                  ,parsec >= 3                  ,process                  ,regex-tdfa                  ,regexpr >= 0.5.1                  ,safe >= 0.2--- http://www.yesodweb.com/blog/2014/04/consolidation-progress--- in order to support both the old and new versions of shakespeare,--- you just need to ensure that you have both the shakespeare and--- deprecated packages listed in your cabal file. In other words, if--- previously you depended on hamlet, now you should depend on hamlet--- and shakespeare. When you're ready to drop backwards compatibility,--- simply put a lower bound of >= 2.0 on shakespeare and remove the--- deprecated packages.-                 ,shakespeare-text >= 1.0 && < 1.2-                 ,shakespeare      >= 1.0 && < 2.1                  ,split >= 0.1 && < 0.3                  ,text >= 0.11                  ,tabular >= 0.2 && < 0.3-                 ,time                  ,utf8-string >= 0.3.5 && < 1.1                  ,wizards == 1.0.*+  if impl(ghc >= 7.10)+    -- 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)+    -- http://www.yesodweb.com/blog/2014/04/consolidation-progress+    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+    build-depends: time >= 1.5   if impl(ghc >= 7.4)     build-depends: pretty-show >= 1.6.4+  if !os(windows) && flag(curses)+    build-depends: terminfo   executable hledger   main-is:        hledger-cli.hs   hs-source-dirs: app   default-language: Haskell2010-  cpp-options: -DVERSION="0.24.1"+  cpp-options: -DVERSION="0.25"   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.24.1-                 ,hledger == 0.24.1+                  hledger-lib == 0.25+                 ,hledger == 0.25                  ,base >= 4.3 && < 5+                 ,base-compat >= 0.5.0                  ,containers                  ,cmdargs >= 0.10 && < 0.11                  ,csv@@ -127,7 +143,7 @@                  ,haskeline >= 0.6 && <= 0.8                  ,HUnit                  ,mtl-                 ,old-locale+                 ,mtl-compat                  ,old-time                  ,parsec >= 3                  ,process@@ -139,9 +155,12 @@                  ,split >= 0.1 && < 0.3                  ,tabular >= 0.2 && < 0.3                  ,text >= 0.11-                 ,time                  ,utf8-string >= 0.3.5 && < 1.1                  ,wizards == 1.0.*+  if flag(old-locale)+    build-depends: time < 1.5, old-locale+  else+    build-depends: time >= 1.5   if impl(ghc >= 7.4)     build-depends: pretty-show >= 1.6.4 @@ -157,6 +176,7 @@   build-depends: hledger-lib                , hledger                , base >= 4.3 && < 5+               , base-compat >= 0.5.0                , cmdargs                , containers                , csv@@ -166,7 +186,7 @@                , haskeline                , HUnit                , mtl-               , old-locale+               , mtl-compat                , old-time                , parsec >= 3                , process@@ -180,11 +200,14 @@                , test-framework                , test-framework-hunit                , text-               , time                , transformers                , wizards == 1.0.*   if impl(ghc >= 7.4)     build-depends: pretty-show >= 1.6.4+  if flag(old-locale)+    build-depends: time < 1.5, old-locale+  else+    build-depends: time >= 1.5   -- not a standard cabal bench test, I think@@ -198,11 +221,14 @@   build-depends:    hledger-lib,                     hledger,                     base >= 4.3 && < 5,-                    old-locale,-                    time,+                    base-compat >= 0.5.0,                     html,                     tabular >= 0.2 && < 0.3,                     process,                     filepath,                     directory+  if flag(old-locale)+    build-depends: time < 1.5, old-locale+  else+    build-depends: time >= 1.5