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 +77/−4
- Hledger/Cli/Add.hs +4/−2
- Hledger/Cli/Balance.hs +74/−33
- Hledger/Cli/Options.hs +74/−63
- Hledger/Cli/Print.hs +22/−22
- Hledger/Cli/Register.hs +33/−16
- hledger.cabal +51/−25
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