packages feed

hledger-ui 1.19.1 → 1.20

raw patch · 13 files changed

+415/−356 lines, 13 filesdep −pretty-showdep ~hledgerdep ~hledger-lib

Dependencies removed: pretty-show

Dependency ranges changed: hledger, hledger-lib

Files

CHANGES.md view
@@ -1,6 +1,23 @@ User-visible changes in hledger-ui. See also the hledger changelog. +# 1.20 2020-12-05++- When entering a query with `/`, malformed queries/regular expressions+  no longer cause the program to exit. (Stephen Morgan)++- Eliding of multicommodity amounts now makes better use of available space. (Stephen Morgan)++- `E` now parses the `HLEDGER_UI_EDITOR` or `EDITOR` environment variable+  correctly on Windows (ignoring the file extension), so if you have that set+  it should be better at opening your editor at the correct line.++- `E` now supports positioning when `HLEDGER_UI_EDITOR` or `EDITOR` +  is VS Code ("`code`") (#1359)++- hledger-ui now has a (human-powered) test suite.++ # 1.19.1 2020-09-07  - Allow megaparsec 9
Hledger/UI/AccountsScreen.hs view
@@ -53,7 +53,7 @@  asInit :: Day -> Bool -> UIState -> UIState asInit d reset ui@UIState{-  aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}},+  aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}},   ajournal=j,   aScreen=s@AccountsScreen{}   } =@@ -80,11 +80,10 @@                       where                         as = map asItemAccountName displayitems -    uopts' = uopts{cliopts_=copts{reportopts_=ropts'}}-    ropts' = ropts{accountlistmode_=if tree_ ropts then ALTree else ALFlat}--    q = And [queryFromOpts d ropts, excludeforecastq (forecast_ ropts)]+    uopts' = uopts{cliopts_=copts{reportspec_=rspec'}}+    rspec' = rspec{rsQuery=simplifyQuery $ And [rsQuery rspec, periodq, excludeforecastq (forecast_ ropts)]}       where+        periodq = Date $ periodAsDateSpan $ period_ ropts         -- Except in forecast mode, exclude future/forecast transactions.         excludeforecastq (Just _) = Any         excludeforecastq Nothing  =  -- not:date:tomorrow- not:tag:generated-transaction@@ -94,14 +93,14 @@           ]      -- run the report-    (items,_total) = balanceReport ropts' q j+    (items,_total) = balanceReport rspec' j      -- pre-render the list items     displayitem (fullacct, shortacct, indent, bal) =       AccountsScreenItem{asItemIndentLevel        = indent                         ,asItemAccountName        = fullacct-                        ,asItemDisplayAccountName = replaceHiddenAccountsNameWith "All" $ if tree_ ropts' then shortacct else fullacct-                        ,asItemRenderedAmounts    = map (showAmountWithoutPrice False) amts+                        ,asItemDisplayAccountName = replaceHiddenAccountsNameWith "All" $ if tree_ ropts then shortacct else fullacct+                        ,asItemRenderedAmounts    = map showAmountWithoutPrice amts                         }       where         Mixed amts = normaliseMixedAmountSquashPricesForDisplay $ stripPrices bal@@ -119,7 +118,7 @@ asInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:  asDraw :: UIState -> [Widget Name]-asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}+asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}               ,ajournal=j               ,aScreen=s@AccountsScreen{}               ,aMode=mode@@ -167,6 +166,7 @@       render $ defaultLayout toplabel bottomlabel $ renderList (asDrawItem colwidths) True (_asList s)        where+        ropts = rsOpts rspec         ishistorical = balancetype_ ropts == HistoricalBalance          toplabel =@@ -174,7 +174,7 @@           <+> toggles           <+> str (" account " ++ if ishistorical then "balances" else "changes")           <+> borderPeriodStr (if ishistorical then "at end of" else "in") (period_ ropts)-          <+> borderQueryStr querystr+          <+> borderQueryStr (unwords . map (quoteIfNeeded . T.unpack) $ querystring_ ropts)           <+> borderDepthStr mdepth           <+> str (" ("++curidx++"/"++totidx++")")           <+> (if ignore_assertions_ $ inputopts_ copts@@ -192,7 +192,6 @@               ,uiShowStatus copts $ statuses_ ropts               ,if real_ ropts then ["real"] else []               ]-            querystr = query_ ropts             mdepth = depth_ ropts             curidx = case _asList s ^. listSelectedL of                        Nothing -> "-"
Hledger/UI/Editor.hs view
@@ -1,7 +1,5 @@ {- | Editor integration. -} --- {-# LANGUAGE OverloadedStrings #-}- module Hledger.UI.Editor (    -- TextPosition    endPosition@@ -11,6 +9,8 @@ where  import Control.Applicative ((<|>))+import Data.List (intercalate)+import Data.Maybe (catMaybes) import Safe import System.Environment import System.Exit@@ -43,58 +43,63 @@ -- | Get a shell command line to open the user's preferred text editor -- (or a default editor) on the given file, and to focus it at the -- given text position if one is provided and if we know how.--- We know how to focus on position for: emacs, vi, nano.+-- We know how to focus on position for: emacs, vi, nano, VS code. -- We know how to focus on last line for: vi. ----- Some tests: With line and column numbers specified,+-- Some tests: -- @--- if EDITOR is:  the command should be:--- -------------  -------------------------------------- notepad        notepad FILE--- vi             vi +LINE FILE---                vi + FILE                                    # negative LINE--- emacs          emacs +LINE:COL FILE---                emacs FILE                                   # negative LINE--- (unset)        emacsclient -a '' -nw +LINE:COL FILE---                emacsclient -a '' -nw FILE                   # negative LINE+-- EDITOR program is:  LINE/COL specified ?  Command should be:               +-- ------------------  --------------------  ----------------------------------- +-- emacs, emacsclient  LINE COL              emacs +LINE:COL FILE+--                     LINE                  emacs +LINE     FILE+--                                           emacs           FILE+--+-- nano                LINE COL              nano +LINE,COL FILE+--                     LINE                  nano +LINE     FILE+--                                           nano           FILE+--+-- code                LINE COL              code --goto FILE:LINE:COL+--                     LINE                  code --goto FILE:LINE+--                                           code        FILE+--+-- vi, & variants      LINE [COL]            vi +LINE FILE+--                     LINE (negative)       vi +     FILE+--                                           vi       FILE+--+-- (other PROG)        [LINE [COL]]          PROG FILE+--+-- (not set)           LINE COL              emacsclient -a '' -nw +LINE:COL FILE+--                     LINE                  emacsclient -a '' -nw +LINE     FILE+--                                           emacsclient -a '' -nw           FILE -- @ ----- How to open editors at the last line of a file:+-- Notes on opening editors at the last line of a file: -- @--- emacs:       emacs FILE -f end-of-buffer+-- emacs:       emacs FILE -f end-of-buffer  # (-f must appear after FILE, +LINE:COL must appear before) -- emacsclient: can't -- vi:          vi + FILE -- @ -- editFileAtPositionCommand :: Maybe TextPosition -> FilePath -> IO String editFileAtPositionCommand mpos f = do-  let f' = singleQuoteIfNeeded f-  editcmd <- getEditCommand-  let editor = lowercase $ takeFileName $ headDef "" $ words' editcmd-  let positionarg =-        case mpos of-          Just (l, mc)-            | editor `elem` [-                "ex",-                "vi","vim","view","nvim","evim","eview",-                "gvim","gview","rvim","rview","rgvim","rgview"-                ] -> plusAndMaybeLine l mc-          Just (l, mc)-            | editor `elem` ["emacs", "emacsclient"] -> plusLineAndMaybeColonColumnOrEnd l mc-          Just (l, mc)-            | editor `elem` ["nano"] -> plusLineAndMaybeCommaColumn l mc-          _ -> ""-        where-          plusAndMaybeLine            l _  = "+" ++ if l >= 0 then show l else ""-          plusLineAndMaybeCommaColumn l mc = "+" ++ show l ++ maybe "" ((","++).show) mc-          plusLineAndMaybeColonColumnOrEnd l mc-            | l >= 0    = "+" ++ show l ++ maybe "" ((":"++).show) mc-            | otherwise = ""-            -- otherwise = "-f end-of-buffer"-            -- XXX Problems with this:-            -- it must appear after the filename, whereas +LINE:COL must appear before-            -- it works only with emacs, not emacsclient-  return $ unwords [editcmd, positionarg, f']+  cmd <- getEditCommand+  let+    editor = lowercase $ takeBaseName $ headDef "" $ words' cmd+    f' = singleQuoteIfNeeded f+    ml = show.fst <$> mpos+    mc = maybe Nothing (fmap show.snd) mpos+    args = case editor of+             e | e `elem` ["emacs", "emacsclient"] -> ['+' : join ":" [ml,mc], f']+             e | e `elem` ["nano"]                 -> ['+' : join "," [ml,mc], f']+             e | e `elem` ["code"]                 -> ["--goto " ++ join ":" [Just f',ml,mc]]+             e | e `elem` ["vi","vim","view","nvim","evim","eview","gvim","gview","rvim","rview",+                           "rgvim","rgview","ex"]  -> [maybe "" plusMaybeLine ml, f']+             _ -> [f']+           where+             join sep = intercalate sep . catMaybes+             plusMaybeLine l = "+" ++ if take 1 l == "-" then "" else l++  return $ unwords $ cmd:args  -- | Get the user's preferred edit command. This is the value of the -- $HLEDGER_UI_EDITOR environment variable, or of $EDITOR, or a
Hledger/UI/Main.hs view
@@ -17,7 +17,6 @@ import Control.Monad -- import Control.Monad.IO.Class (liftIO) -- import Data.Monoid              ---import Data.List import Data.List.Extra (nubSort) import Data.Maybe -- import Data.Text (Text)@@ -52,12 +51,12 @@  main :: IO () main = do-  opts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=ropts,rawopts_=rawopts}} <- getHledgerUIOpts+  opts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportspec_=rspec@ReportSpec{rsOpts=ropts},rawopts_=rawopts}} <- getHledgerUIOpts   -- when (debug_ $ cliopts_ opts) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)    -- always include forecasted periodic transactions when loading data;   -- they will be toggled on and off in the UI.-  let copts' = copts{reportopts_=ropts{forecast_=Just $ fromMaybe nulldatespan (forecast_ ropts)}}+  let copts' = copts{reportspec_=rspec{rsOpts=ropts{forecast_=Just $ fromMaybe nulldatespan (forecast_ ropts)}}}    case True of     _ | "help"            `inRawOpts` rawopts -> putStr (showModeUsage uimode)@@ -66,47 +65,68 @@     _                                         -> withJournalDo copts' (runBrickUi opts)  runBrickUi :: UIOpts -> Journal -> IO ()-runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=ropts}} j = do+runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportspec_=rspec@ReportSpec{rsOpts=ropts}}} j = do   d <- getCurrentDay    let -    -- depth: is a bit different from other queries. In hledger cli,-    -- - reportopts{depth_} indicates --depth options-    -- - reportopts{query_} is the query arguments as a string-    -- - the report query is based on both of these.-    -- For hledger-ui, for now, move depth: arguments out of reportopts{query_}-    -- and into reportopts{depth_}, so that depth and other kinds of filter query-    -- can be displayed independently.+    -- hledger-ui's query handling is currently in flux, mixing old and new approaches.+    -- Related: #1340, #1383, #1387. Some notes and terminology:++    -- The *startup query* is the Query generated at program startup, from+    -- command line options, arguments, and the current date. hledger CLI+    -- uses this.++    -- hledger-ui/hledger-web allow the query to be changed at will, creating+    -- a new *runtime query* each time.++    -- The startup query or part of it can be used as a *constraint query*,+    -- limiting all runtime queries. hledger-web does this with the startup+    -- report period, never showing transactions outside those dates.+    -- hledger-ui does not do this.++    -- A query is a combination of multiple subqueries/terms, which are+    -- generated from command line options and arguments, ui/web app runtime+    -- state, and/or the current date.++    -- Some subqueries are generated by parsing freeform user input, which+    -- can fail. We don't want hledger users to see such failures except:++    -- 1. at program startup, in which case the program exits+    -- 2. after entering a new freeform query in hledger-ui/web, in which case+    --    the change is rejected and the program keeps running++    -- So we should parse those kinds of subquery only at those times. Any+    -- subqueries which do not require parsing can be kept separate. And+    -- these can be combined to make the full query when needed, eg when+    -- hledger-ui screens are generating their data. (TODO)++    -- Some parts of the query are also kept separate for UI reasons.+    -- hledger-ui provides special UI for controlling depth (number keys), +    -- the report period (shift arrow keys), realness/status filters (RUPC keys) etc.+    -- There is also a freeform text area for extra query terms (/ key).+    -- It's cleaner and less conflicting to keep the former out of the latter.+     uopts' = uopts{       cliopts_=copts{-         reportopts_= ropts{-            -- incorporate any depth: query args into depth_,-            -- any date: query args into period_-            depth_ =queryDepth q,-            period_=periodfromoptsandargs,-            query_ =unwords -- as in ReportOptions, with same limitations-                    $ collectopts filteredQueryArg (rawopts_ copts),-            -- always disable boring account name eliding, unlike the CLI, for a more regular tree-            no_elide_=True,-            -- flip the default for items with zero amounts, show them by default-            empty_=not $ empty_ ropts,-            -- show historical balances by default, unlike the CLI-            balancetype_=HistoricalBalance+         reportspec_=rspec{+            rsQuery=filteredQuery $ rsQuery rspec,  -- query with depth/date parts removed+            rsOpts=ropts{+               depth_ =queryDepth $ rsQuery rspec,  -- query's depth part+               period_=periodfromoptsandargs,       -- query's date part+               no_elide_=True,  -- avoid squashing boring account names, for a more regular tree (unlike hledger)+               empty_=not $ empty_ ropts,  -- show zero items by default, hide them with -E (unlike hledger)+               balancetype_=HistoricalBalance  -- show historical balances by default (unlike hledger)+               }             }          }       }       where-        q = queryFromOpts d ropts-        datespanfromargs = queryDateSpan (date2_ ropts) $ fst $-                           either error' id $ parseQuery d (T.pack $ query_ ropts)  -- PARTIAL:+        datespanfromargs = queryDateSpan (date2_ ropts) $ rsQuery rspec         periodfromoptsandargs =           dateSpanAsPeriod $ spansIntersect [periodAsDateSpan $ period_ ropts, datespanfromargs]-        filteredQueryArg = \case-            ("args", v)-                | not $ any (`isPrefixOf` v) ["depth:", "date:"] -- skip depth/date passed as query-                    -> Just (quoteIfNeeded v)-            _ -> Nothing+        filteredQuery q = simplifyQuery $ And [queryFromFlags ropts, filtered q]+          where filtered = filterQuery (\x -> not $ queryIsDepth x || queryIsDate x)      -- XXX move this stuff into Options, UIOpts     theme = maybe defaultTheme (fromMaybe defaultTheme . getTheme) $
Hledger/UI/RegisterScreen.hs view
@@ -59,18 +59,17 @@ rsSetAccount _ _ scr = scr  rsInit :: Day -> Bool -> UIState -> UIState-rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportopts_=ropts}}, ajournal=j, aScreen=s@RegisterScreen{..}} =+rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}, ajournal=j, aScreen=s@RegisterScreen{..}} =   ui{aScreen=s{rsList=newitems'}}   where     -- gather arguments and queries     -- XXX temp     inclusive = tree_ ropts || rsForceInclusive     thisacctq = Acct $ (if inclusive then accountNameToAccountRegex else accountNameToAccountOnlyRegex) rsAccount-    ropts' = ropts{-               depth_=Nothing-              }-    q = And [queryFromOpts d ropts', excludeforecastq (forecast_ ropts)]+    rspec' = rspec{rsOpts=ropts{depth_=Nothing}}+    q = And [rsQuery rspec, periodq, excludeforecastq (forecast_ ropts)]       where+        periodq = Date $ periodAsDateSpan $ period_ ropts         -- Except in forecast mode, exclude future/forecast transactions.         excludeforecastq (Just _) = Any         excludeforecastq Nothing  =  -- not:date:tomorrow- not:tag:generated-transaction@@ -79,8 +78,8 @@             ,Not generatedTransactionTag           ] -    (_label,items) = accountTransactionsReport ropts' j q thisacctq-    items' = (if empty_ ropts' then id else filter (not . mixedAmountLooksZero . fifth6)) $  -- without --empty, exclude no-change txns+    (_label,items) = accountTransactionsReport rspec' j q thisacctq+    items' = (if empty_ ropts then id else filter (not . mixedAmountLooksZero . fifth6)) $  -- without --empty, exclude no-change txns              reverse  -- most recent last              items @@ -95,8 +94,8 @@                                                      [s] -> s                                                      ss  -> intercalate ", " ss                                                      -- _   -> "<split>"  -- should do this if accounts field width < 30-                            ,rsItemChangeAmount  = showMixedAmountElided False change-                            ,rsItemBalanceAmount = showMixedAmountElided False bal+                            ,rsItemChangeAmount  = showMixedOneLine showAmountWithoutPrice Nothing (Just 32) False change+                            ,rsItemBalanceAmount = showMixedOneLine showAmountWithoutPrice Nothing (Just 32) False bal                             ,rsItemTransaction   = t                             }     -- blank items are added to allow more control of scroll position; we won't allow movement over these@@ -105,8 +104,8 @@                             ,rsItemStatus        = Unmarked                             ,rsItemDescription   = ""                             ,rsItemOtherAccounts = ""-                            ,rsItemChangeAmount  = ""-                            ,rsItemBalanceAmount = ""+                            ,rsItemChangeAmount  = ("", 0)+                            ,rsItemBalanceAmount = ("", 0)                             ,rsItemTransaction   = nulltransaction                             }     -- build the List@@ -138,7 +137,7 @@ rsInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:  rsDraw :: UIState -> [Widget Name]-rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}+rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}               ,aScreen=RegisterScreen{..}               ,aMode=mode               } =@@ -164,8 +163,8 @@         whitespacewidth = 10 -- inter-column whitespace, fixed width         minnonamtcolswidth = datewidth + 1 + 2 + 2 -- date column plus at least 1 for status and 2 for desc and accts         maxamtswidth = max 0 (totalwidth - minnonamtcolswidth - whitespacewidth)-        maxchangewidthseen = maximum' $ map (strWidth . rsItemChangeAmount) displayitems-        maxbalwidthseen = maximum' $ map (strWidth . rsItemBalanceAmount) displayitems+        maxchangewidthseen = maximum' $ map (snd . rsItemChangeAmount) displayitems+        maxbalwidthseen = maximum' $ map (snd . rsItemBalanceAmount) displayitems         changewidthproportion = fromIntegral maxchangewidthseen / fromIntegral (maxchangewidthseen + maxbalwidthseen)         maxchangewidth = round $ changewidthproportion * fromIntegral maxamtswidth         maxbalwidth = maxamtswidth - maxchangewidth@@ -192,6 +191,7 @@       render $ defaultLayout toplabel bottomlabel $ renderList (rsDrawItem colwidths) True rsList        where+        ropts = rsOpts rspec         ishistorical = balancetype_ ropts == HistoricalBalance         -- inclusive = tree_ ropts || rsForceInclusive @@ -201,7 +201,7 @@           <+> togglefilters           <+> str " transactions"           -- <+> str (if ishistorical then " historical total" else " period total")-          <+> borderQueryStr (query_ ropts)+          <+> borderQueryStr (unwords . map (quoteIfNeeded . T.unpack) $ querystring_ ropts)           -- <+> str " and subs"           <+> borderPeriodStr "in" (period_ ropts)           <+> str " ("@@ -262,13 +262,13 @@       str "  " <+>       str (fitString (Just acctswidth) (Just acctswidth) True True rsItemOtherAccounts) <+>       str "   " <+>-      withAttr changeattr (str (fitString (Just changewidth) (Just changewidth) True False rsItemChangeAmount)) <+>+      withAttr changeattr (str (fitString (Just changewidth) (Just changewidth) True False $ fst rsItemChangeAmount)) <+>       str "   " <+>-      withAttr balattr (str (fitString (Just balwidth) (Just balwidth) True False rsItemBalanceAmount))+      withAttr balattr (str (fitString (Just balwidth) (Just balwidth) True False $ fst rsItemBalanceAmount))   where-    changeattr | '-' `elem` rsItemChangeAmount = sel $ "list" <> "amount" <> "decrease"+    changeattr | '-' `elem` fst rsItemChangeAmount = sel $ "list" <> "amount" <> "decrease"                | otherwise                     = sel $ "list" <> "amount" <> "increase"-    balattr    | '-' `elem` rsItemBalanceAmount = sel $ "list" <> "balance" <> "negative"+    balattr    | '-' `elem` fst rsItemBalanceAmount = sel $ "list" <> "balance" <> "negative"                | otherwise                      = sel $ "list" <> "balance" <> "positive"     sel | selected  = (<> "selected")         | otherwise = id
Hledger/UI/TransactionScreen.hs view
@@ -43,7 +43,7 @@   }  tsInit :: Day -> Bool -> UIState -> UIState-tsInit _d _reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=_ropts}}+tsInit _d _reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportspec_=_rspec}}                            ,ajournal=_j                            ,aScreen=TransactionScreen{}                            } =@@ -58,7 +58,7 @@ tsInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:  tsDraw :: UIState -> [Widget Name]-tsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}+tsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}               ,ajournal=j               ,aScreen=TransactionScreen{tsTransaction=(i,t)                                         ,tsTransactions=nts@@ -77,15 +77,14 @@         styles = journalCommodityStyles j         periodlast =           fromMaybe (error' "TransactionScreen: expected a non-empty journal") $  -- PARTIAL: shouldn't happen-          reportPeriodOrJournalLastDay ropts j-        mreportlast = reportPeriodLastDay ropts-        today = fromMaybe (error' "TransactionScreen: could not pick a valuation date, ReportOpts today_ is unset") $ today_ ropts  -- PARTIAL:+          reportPeriodOrJournalLastDay rspec j+        mreportlast = reportPeriodLastDay rspec         multiperiod = interval_ ropts /= NoInterval        render $ defaultLayout toplabel bottomlabel $ str $         showTransactionOneLineAmounts $         (if valuationTypeIsCost ropts then transactionToCost (journalCommodityStyles j) else id) $-        (if valuationTypeIsDefaultValue ropts then (\t -> transactionApplyValuation prices styles periodlast mreportlast today multiperiod t (AtDefault Nothing)) else id) $+        (if valuationTypeIsDefaultValue ropts then (\t -> transactionApplyValuation prices styles periodlast mreportlast (rsToday rspec) multiperiod t (AtDefault Nothing)) else id) $         -- (if real_ ropts then filterTransactionPostings (Real True) else id) -- filter postings by --real         t       where@@ -98,7 +97,7 @@           <+> withAttr ("border" <> "bold") (str $ show i)           <+> str (" of "++show (length nts))           <+> togglefilters-          <+> borderQueryStr (query_ ropts)+          <+> borderQueryStr (unwords . map (quoteIfNeeded . T.unpack) $ querystring_ ropts)           <+> str (" in "++T.unpack (replaceHiddenAccountsNameWith "All" acct)++")")           <+> (if ignore_assertions_ $ inputopts_ copts then withAttr ("border" <> "query") (str " ignoring balance assertions") else str "")           where@@ -133,7 +132,7 @@                                                ,tsTransactions=nts                                                ,tsAccount=acct                                                }-                   ,aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}+                   ,aopts=UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}                    ,ajournal=j                    ,aMode=mode                    }@@ -173,7 +172,7 @@             Right j' -> do               continue $                 regenerateScreens j' d $-                regenerateTransactions ropts d j' s acct i $   -- added (inline) 201512 (why ?)+                regenerateTransactions rspec j' s acct i $   -- added (inline) 201512 (why ?)                 clearCostValue $                 ui         VtyEvent (EvKey (KChar 'I') []) -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui)@@ -208,15 +207,12 @@  -- Got to redo the register screen's transactions report, to get the latest transactions list for this screen. -- XXX Duplicates rsInit. Why do we have to do this as well as regenerateScreens ?-regenerateTransactions :: ReportOpts -> Day -> Journal -> Screen -> AccountName -> Integer -> UIState -> UIState-regenerateTransactions ropts d j s acct i ui =+regenerateTransactions :: ReportSpec -> Journal -> Screen -> AccountName -> Integer -> UIState -> UIState+regenerateTransactions rspec j s acct i ui =   let-    ropts' = ropts {depth_=Nothing-                   ,balancetype_=HistoricalBalance-                   }-    q = filterQuery (not . queryIsDepth) $ queryFromOpts d ropts'+    q = filterQuery (not . queryIsDepth) $ rsQuery rspec     thisacctq = Acct $ accountNameToAccountRegex acct -- includes subs-    items = reverse $ snd $ accountTransactionsReport ropts j q thisacctq+    items = reverse $ snd $ accountTransactionsReport rspec j q thisacctq     ts = map first6 items     numberedts = zip [1..] ts     -- select the best current transaction from the new list
Hledger/UI/UIOptions.hs view
@@ -58,15 +58,16 @@  -- hledger-ui options, used in hledger-ui and above data UIOpts = UIOpts {-     watch_   :: Bool-    ,change_  :: Bool-    ,cliopts_ :: CliOpts+     watch_       :: Bool+    ,change_      :: Bool+    ,cliopts_     :: CliOpts  } deriving (Show)  defuiopts = UIOpts-    def-    def-    def+  { watch_   = False+  , change_  = False+  , cliopts_ = def+  }  -- instance Default CliOpts where def = defcliopts @@ -74,9 +75,9 @@ rawOptsToUIOpts rawopts = checkUIOpts <$> do   cliopts <- rawOptsToCliOpts rawopts   return defuiopts {-              watch_   = boolopt "watch" rawopts-             ,change_  = boolopt "change" rawopts-             ,cliopts_ = cliopts+              watch_       = boolopt "watch" rawopts+             ,change_      = boolopt "change" rawopts+             ,cliopts_     = cliopts              }  checkUIOpts :: UIOpts -> UIOpts@@ -94,4 +95,3 @@   let args' = replaceNumericFlags args   let cmdargopts = either usageError id $ process uimode args'   rawOptsToUIOpts cmdargopts-
Hledger/UI/UIState.hs view
@@ -8,10 +8,11 @@ where  import Brick.Widgets.Edit-import Data.List+import Data.List ((\\), foldl', sort)+import Data.Maybe (fromMaybe)+import qualified Data.Text as T import Data.Text.Zipper (gotoEOL) import Data.Time.Calendar (Day)-import Data.Maybe (fromMaybe)  import Hledger import Hledger.Cli.CliOptions@@ -20,18 +21,18 @@  -- | Toggle between showing only unmarked items or all items. toggleUnmarked :: UIState -> UIState-toggleUnmarked ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=reportOptsToggleStatusSomehow Unmarked copts ropts}}}+toggleUnmarked ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatusSomehow Unmarked copts rspec}}}  -- | Toggle between showing only pending items or all items. togglePending :: UIState -> UIState-togglePending ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=reportOptsToggleStatusSomehow Pending copts ropts}}}+togglePending ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatusSomehow Pending copts rspec}}}  -- | Toggle between showing only cleared items or all items. toggleCleared :: UIState -> UIState-toggleCleared ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=reportOptsToggleStatusSomehow Cleared copts ropts}}}+toggleCleared ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatusSomehow Cleared copts rspec}}}  -- TODO testing different status toggle styles @@ -51,14 +52,17 @@     showstatus Pending  = "pending"     showstatus Unmarked = "unmarked" -reportOptsToggleStatusSomehow :: Status -> CliOpts -> ReportOpts -> ReportOpts-reportOptsToggleStatusSomehow s copts ropts =-  case maybeposintopt "status-toggles" $ rawopts_ copts of-     Just 2 -> reportOptsToggleStatus2 s ropts-     Just 3 -> reportOptsToggleStatus3 s ropts---     Just 4 -> reportOptsToggleStatus4 s ropts---     Just 5 -> reportOptsToggleStatus5 s ropts-     _      -> reportOptsToggleStatus1 s ropts+reportSpecToggleStatusSomehow :: Status -> CliOpts -> ReportSpec -> ReportSpec+reportSpecToggleStatusSomehow s copts =+    either (error "reportSpecToggleStatusSomehow: updating Status should not result in an error") id  -- PARTIAL:+    . updateReportSpecFromOpts update+  where+    update = case maybeposintopt "status-toggles" $ rawopts_ copts of+      Just 2 -> reportOptsToggleStatus2 s+      Just 3 -> reportOptsToggleStatus3 s+--      Just 4 -> reportOptsToggleStatus4 s+--      Just 5 -> reportOptsToggleStatus5 s+      _      -> reportOptsToggleStatus1 s  -- 1 UPC toggles only X/all reportOptsToggleStatus1 s ropts@ReportOpts{statuses_=ss}@@ -101,26 +105,26 @@  -- | Toggle between showing all and showing only nonempty (more precisely, nonzero) items. toggleEmpty :: UIState -> UIState-toggleEmpty ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=toggleEmpty ropts}}}+toggleEmpty ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=toggleEmpty ropts}}}}   where     toggleEmpty ropts = ropts{empty_=not $ empty_ ropts}  -- | Show primary amounts, not cost or value. clearCostValue :: UIState -> UIState-clearCostValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{value_ = plog "clearing value mode" Nothing}}}}+clearCostValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{value_ = plog "clearing value mode" Nothing}}}}}  -- | Toggle between showing the primary amounts or costs. toggleCost :: UIState -> UIState-toggleCost ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{value_ = valuationToggleCost $ value_ ropts}}}}+toggleCost ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{value_ = valuationToggleCost $ value_ ropts}}}}}  -- | Toggle between showing primary amounts or default valuation. toggleValue :: UIState -> UIState-toggleValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{-    value_ = plog "toggling value mode to" $ valuationToggleValue $ value_ ropts}}}}+toggleValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{+    value_ = plog "toggling value mode to" $ valuationToggleValue $ value_ ropts}}}}}  -- | Basic toggling of -B/cost, for hledger-ui. valuationToggleCost :: Maybe ValuationType -> Maybe ValuationType@@ -134,18 +138,18 @@  -- | Set hierarchic account tree mode. setTree :: UIState -> UIState-setTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{accountlistmode_=ALTree}}}}+setTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{accountlistmode_=ALTree}}}}}  -- | Set flat account list mode. setList :: UIState -> UIState-setList ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{accountlistmode_=ALFlat}}}}+setList ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{accountlistmode_=ALFlat}}}}}  -- | Toggle between flat and tree mode. If current mode is unspecified/default, assume it's flat. toggleTree :: UIState -> UIState-toggleTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=toggleTreeMode ropts}}}+toggleTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=toggleTreeMode ropts}}}}   where     toggleTreeMode ropts       | accountlistmode_ ropts == ALTree = ropts{accountlistmode_=ALFlat}@@ -153,8 +157,8 @@  -- | Toggle between historical balances and period balances. toggleHistorical :: UIState -> UIState-toggleHistorical ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{balancetype_=b}}}}+toggleHistorical ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{balancetype_=b}}}}}   where     b | balancetype_ ropts == HistoricalBalance = PeriodChange       | otherwise                               = HistoricalBalance@@ -173,10 +177,10 @@ -- transactions with a query for their special tag. -- toggleForecast :: Day -> UIState -> UIState-toggleForecast d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =+toggleForecast d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =   ui{aopts=uopts{cliopts_=copts'}}   where-    copts' = copts{reportopts_=ropts{forecast_=forecast'}}+    copts' = copts{reportspec_=rspec{rsOpts=ropts{forecast_=forecast'}}}     forecast' =       case forecast_ ropts of         Just _  -> Nothing@@ -184,10 +188,11 @@  -- | Toggle between showing all and showing only real (non-virtual) items. toggleReal :: UIState -> UIState-toggleReal ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=toggleReal ropts}}}+toggleReal ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =+    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}   where-    toggleReal ropts = ropts{real_=not $ real_ ropts}+    update = either (error "toggleReal: updating Real should not result in an error") id  -- PARTIAL:+           . updateReportSpecFromOpts (\ropts -> ropts{real_=not $ real_ ropts})  -- | Toggle the ignoring of balance assertions. toggleIgnoreBalanceAssertions :: UIState -> UIState@@ -196,61 +201,68 @@  -- | Step through larger report periods, up to all. growReportPeriod :: Day -> UIState -> UIState-growReportPeriod _d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodGrow $ period_ ropts}}}}+growReportPeriod _d = updateReportPeriod periodGrow  -- | Step through smaller report periods, down to a day. shrinkReportPeriod :: Day -> UIState -> UIState-shrinkReportPeriod d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodShrink d $ period_ ropts}}}}+shrinkReportPeriod d = updateReportPeriod (periodShrink d)  -- | Step the report start/end dates to the next period of same duration, -- remaining inside the given enclosing span. nextReportPeriod :: DateSpan -> UIState -> UIState-nextReportPeriod enclosingspan ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{period_=p}}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodNextIn enclosingspan p}}}}+nextReportPeriod enclosingspan = updateReportPeriod (periodNextIn enclosingspan)  -- | Step the report start/end dates to the next period of same duration, -- remaining inside the given enclosing span. previousReportPeriod :: DateSpan -> UIState -> UIState-previousReportPeriod enclosingspan ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{period_=p}}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodPreviousIn enclosingspan p}}}}+previousReportPeriod enclosingspan = updateReportPeriod (periodPreviousIn enclosingspan)  -- | If a standard report period is set, step it forward/backward if needed so that -- it encloses the given date. moveReportPeriodToDate :: Day -> UIState -> UIState-moveReportPeriodToDate d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{period_=p}}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodMoveTo d p}}}}+moveReportPeriodToDate d = updateReportPeriod (periodMoveTo d)  -- | Get the report period. reportPeriod :: UIState -> Period-reportPeriod UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ReportOpts{period_=p}}}} =-  p+reportPeriod = period_ . rsOpts . reportspec_ . cliopts_ . aopts  -- | Set the report period. setReportPeriod :: Period -> UIState -> UIState-setReportPeriod p ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=p}}}}+setReportPeriod p = updateReportPeriod (const p)  -- | Clear any report period limits. resetReportPeriod :: UIState -> UIState resetReportPeriod = setReportPeriod PeriodAll +-- | Update report period by a applying a function.+updateReportPeriod :: (Period -> Period) -> UIState -> UIState+updateReportPeriod updatePeriod ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =+    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}+  where+    update = either (error "updateReportPeriod: updating period should not result in an error") id  -- PARTIAL:+           . updateReportSpecFromOpts (\ropts -> ropts{period_=updatePeriod $ period_ ropts})+ -- | Apply a new filter query. setFilter :: String -> UIState -> UIState-setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{query_=s}}}}+setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =+    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}+  where+    update = either (const rspec) id . updateReportSpecFromOpts (\ropts -> ropts{querystring_=querystring})+    querystring = words'' prefixes $ T.pack s  -- | Reset some filters & toggles. resetFilter :: UIState -> UIState-resetFilter ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{-     empty_=True-    ,statuses_=[]-    ,real_=False-    ,query_=""-    --,period_=PeriodAll-    }}}}+resetFilter ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{+     rsQuery=Any+    ,rsQueryOpts=[]+    ,rsOpts=ropts{+       empty_=True+      ,statuses_=[]+      ,real_=False+      ,querystring_=[]+      --,period_=PeriodAll+    }}}}}  -- | Reset all options state to exactly what it was at startup -- (preserving any command-line options/arguments).@@ -258,8 +270,7 @@ resetOpts ui@UIState{astartupopts} = ui{aopts=astartupopts}  resetDepth :: UIState -> UIState-resetDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=Nothing}}}}+resetDepth = updateReportDepth (const Nothing)  -- | Get the maximum account depth in the current journal. maxDepth :: UIState -> Int@@ -268,8 +279,7 @@ -- | Decrement the current depth limit towards 0. If there was no depth limit, -- set it to one less than the maximum account depth. decDepth :: UIState -> UIState-decDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}-  = ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=dec depth_}}}}+decDepth ui = updateReportDepth dec ui   where     dec (Just d) = Just $ max 0 (d-1)     dec Nothing  = Just $ maxDepth ui - 1@@ -277,35 +287,37 @@ -- | Increment the current depth limit. If this makes it equal to the -- the maximum account depth, remove the depth limit. incDepth :: UIState -> UIState-incDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}-  = ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=inc depth_}}}}-  where-    inc (Just d) | d < (maxDepth ui - 1) = Just $ d+1-    inc _ = Nothing+incDepth = updateReportDepth (fmap succ)  -- | Set the current depth limit to the specified depth, or remove the depth limit. -- Also remove the depth limit if the specified depth is greater than the current -- maximum account depth. If the specified depth is negative, reset the depth limit -- to whatever was specified at uiartup. setDepth :: Maybe Int -> UIState -> UIState-setDepth mdepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}}-  = ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=mdepth'}}}}-  where-    mdepth' = case mdepth of-                Nothing                   -> Nothing-                Just d | d < 0            -> depth_ ropts-                       | d >= maxDepth ui -> Nothing-                       | otherwise        -> mdepth+setDepth mdepth = updateReportDepth (const mdepth)  getDepth :: UIState -> Maybe Int-getDepth UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}} = depth_ ropts+getDepth = depth_ . rsOpts . reportspec_ . cliopts_ . aopts +-- | Update report depth by a applying a function. If asked to set a depth less+-- than zero, it will leave it unchanged.+updateReportDepth :: (Maybe Int -> Maybe Int) -> UIState -> UIState+updateReportDepth updateDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =+    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}+  where+    update = either (error "updateReportDepth: updating depth should not result in an error") id  -- PARTIAL:+           . updateReportSpecFromOpts (\ropts -> ropts{depth_=updateDepth (depth_ ropts) >>= clipDepth ropts})+    clipDepth ropts d | d < 0            = depth_ ropts+                      | d >= maxDepth ui = Nothing+                      | otherwise        = Just d+ -- | Open the minibuffer, setting its content to the current query with the cursor at the end. showMinibuffer :: UIState -> UIState showMinibuffer ui = setMode (Minibuffer e) ui   where     e = applyEdit gotoEOL $ editor MinibufferEditor (Just 1) oldq-    oldq = query_ $ reportopts_ $ cliopts_ $ aopts ui+    oldq = unwords . map (quoteIfNeeded . T.unpack)+         . querystring_ . rsOpts . reportspec_ . cliopts_ $ aopts ui  -- | Close the minibuffer, discarding any edit in progress. closeMinibuffer :: UIState -> UIState
Hledger/UI/UITypes.hs view
@@ -146,8 +146,8 @@   ,rsItemStatus         :: Status           -- ^ transaction status   ,rsItemDescription    :: String           -- ^ description   ,rsItemOtherAccounts  :: String           -- ^ other accounts-  ,rsItemChangeAmount   :: String           -- ^ the change to the current account from this transaction-  ,rsItemBalanceAmount  :: String           -- ^ the balance or running total after this transaction+  ,rsItemChangeAmount   :: (String, Int)    -- ^ the change to the current account from this transaction+  ,rsItemBalanceAmount  :: (String, Int)    -- ^ the balance or running total after this transaction   ,rsItemTransaction    :: Transaction      -- ^ the full transaction   }   deriving (Show)
hledger-ui.1 view
@@ -1,5 +1,5 @@ -.TH "hledger-ui" "1" "September 2020" "hledger-ui 1.18.99" "hledger User Manuals"+.TH "hledger-ui" "1" "November 2020" "hledger-ui 1.20" "hledger User Manuals"   @@ -88,6 +88,9 @@ \f[B]\f[CB]-I --ignore-assertions\f[B]\f[R] disable balance assertion checks (note: does not disable balance assignments)+.TP+\f[B]\f[CB]-s --strict\f[B]\f[R]+do extra error checking (check that all posted accounts are declared) .PP hledger reporting options: .TP
hledger-ui.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 9f306e545c5b87e192eac6bea6e0a46c9694e9844524b6ef500d2eb59e3d2fa0+-- hash: 4007bd6deffcff3c3d5a40863cfa11bddaed31c367fdf5033728ec847c292a91  name:           hledger-ui-version:        1.19.1+version:        1.20 synopsis:       Curses-style terminal interface for the hledger accounting system description:    A simple curses-style terminal user interface for the hledger accounting system.                 It can be a more convenient way to browse your accounts than the CLI.@@ -64,7 +64,7 @@   hs-source-dirs:       ./.   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-type-defaults -fno-warn-orphans-  cpp-options: -DVERSION="1.19.1"+  cpp-options: -DVERSION="1.20"   build-depends:       ansi-terminal >=0.9     , async@@ -78,12 +78,11 @@     , extra >=1.6.3     , filepath     , fsnotify >=0.2.1.2 && <0.4-    , hledger >=1.19.1 && <1.20-    , hledger-lib >=1.19.1 && <1.20+    , hledger >=1.20 && <1.21+    , hledger-lib >=1.20 && <1.21     , megaparsec >=7.0.0 && <9.1     , microlens >=0.4     , microlens-platform >=0.2.3.1-    , pretty-show >=1.6.4     , process >=1.2     , safe >=0.2     , split >=0.1
hledger-ui.info view
@@ -3,8 +3,8 @@  File: hledger-ui.info,  Node: Top,  Next: OPTIONS,  Up: (dir) -hledger-ui(1) hledger-ui 1.18.99-********************************+hledger-ui(1) hledger-ui 1.20+*****************************  hledger-ui - terminal interface for the hledger accounting tool @@ -99,7 +99,11 @@       disable balance assertion checks (note: does not disable balance      assignments)+'-s --strict' +     do extra error checking (check that all posted accounts are+     declared)+    hledger reporting options:  '-b --begin=DATE'@@ -515,26 +519,26 @@  Tag Table: Node: Top71-Node: OPTIONS1476-Ref: #options1573-Node: keys5545-Ref: #keys5640-Node: screens9972-Ref: #screens10077-Node: accounts screen10167-Ref: #accounts-screen10295-Node: Register screen12510-Ref: #register-screen12665-Node: Transaction screen14662-Ref: #transaction-screen14820-Node: Error screen15690-Ref: #error-screen15812-Node: ENVIRONMENT16056-Ref: #environment16170-Node: FILES16977-Ref: #files17076-Node: BUGS17289-Ref: #bugs17366+Node: OPTIONS1470+Ref: #options1567+Node: keys5634+Ref: #keys5729+Node: screens10061+Ref: #screens10166+Node: accounts screen10256+Ref: #accounts-screen10384+Node: Register screen12599+Ref: #register-screen12754+Node: Transaction screen14751+Ref: #transaction-screen14909+Node: Error screen15779+Ref: #error-screen15901+Node: ENVIRONMENT16145+Ref: #environment16259+Node: FILES17066+Ref: #files17165+Node: BUGS17378+Ref: #bugs17455  End Tag Table 
hledger-ui.txt view
@@ -84,6 +84,10 @@               disable balance assertion checks (note: does not disable balance               assignments) +       -s --strict+              do  extra error checking (check that all posted accounts are de-+              clared)+        hledger reporting options:         -b --begin=DATE@@ -108,7 +112,7 @@               multiperiod/multicolumn report by year         -p --period=PERIODEXP-              set  start date, end date, and/or reporting interval all at once+              set start date, end date, and/or reporting interval all at  once               using period expressions syntax         --date2@@ -131,21 +135,21 @@               hide/aggregate accounts or postings more than NUM levels deep         -E --empty-              show  items with zero amount, normally hidden (and vice-versa in+              show items with zero amount, normally hidden (and vice-versa  in               hledger-ui/hledger-web)         -B --cost               convert amounts to their cost/selling amount at transaction time         -V --market-              convert amounts to their market value in default valuation  com-+              convert  amounts to their market value in default valuation com-               modities         -X --exchange=COMM               convert amounts to their market value in commodity COMM         --value-              convert  amounts  to  cost  or  market value, more flexibly than+              convert amounts to cost or  market  value,  more  flexibly  than               -B/-V/-X         --infer-value@@ -154,15 +158,15 @@        --auto apply automated posting rules to modify transactions.         --forecast-              generate future transactions from  periodic  transaction  rules,-              for  the  next 6 months or till report end date.  In hledger-ui,+              generate  future  transactions  from periodic transaction rules,+              for the next 6 months or till report end date.   In  hledger-ui,               also make ordinary future transactions visible.         --color=WHEN (or --colour=WHEN)-              Should color-supporting commands use ANSI color  codes  in  text-              output.   'auto' (default): whenever stdout seems to be a color--              supporting terminal.  'always' or 'yes': always, useful eg  when-              piping  output  into  'less  -R'.   'never'  or  'no': never.  A+              Should  color-supporting  commands  use ANSI color codes in text+              output.  'auto' (default): whenever stdout seems to be a  color-+              supporting  terminal.  'always' or 'yes': always, useful eg when+              piping output into  'less  -R'.   'never'  or  'no':  never.   A               NO_COLOR environment variable overrides this.         When a reporting option appears more than once in the command line, the@@ -182,91 +186,91 @@               show debug output (levels 1-9, default: 1)         a @file argument will be expanded to the contents of file, which should-       contain one command line option/argument per line.  (to  prevent  this,+       contain  one  command line option/argument per line.  (to prevent this,        insert a -- argument before.)  keys-       ?  shows a help dialog listing all keys.  (some of these also appear in+       ? shows a help dialog listing all keys.  (some of these also appear  in        the quick help at the bottom of each screen.) press ? again (or escape,        or left, or q) to close it.  the following keys work on most screens:         the cursor keys navigate: right (or enter) goes deeper, left returns to-       the previous screen, up/down/page up/page  down/home/end  move  up  and+       the  previous  screen,  up/down/page  up/page down/home/end move up and        down through lists.  Emacs-style (ctrl-p/ctrl-n/ctrl-f/ctrl-b) movement-       keys are also supported (but not  vi-style  keys,  since  hledger-1.19,-       sorry!).   A  tip:  movement  speed  is limited by your keyboard repeat-       rate, to move faster you may want to adjust it.  (If you're on  a  mac,+       keys  are  also  supported  (but not vi-style keys, since hledger-1.19,+       sorry!).  A tip: movement speed is  limited  by  your  keyboard  repeat+       rate,  to  move faster you may want to adjust it.  (If you're on a mac,        the karabiner app is one way to do that.) -       with  shift pressed, the cursor keys adjust the report period, limiting-       the transactions to be shown  (by  default,  all  are  shown).   shift--       down/up  steps downward and upward through these standard report period-       durations: year, quarter, month,  week,  day.   then,  shift-left/right-       moves  to the previous/next period.  T sets the report period to today.-       with the --watch option, when viewing a "current" period  (the  current+       with shift pressed, the cursor keys adjust the report period,  limiting+       the  transactions  to  be  shown  (by  default, all are shown).  shift-+       down/up steps downward and upward through these standard report  period+       durations:  year,  quarter,  month,  week, day.  then, shift-left/right+       moves to the previous/next period.  T sets the report period to  today.+       with  the  --watch option, when viewing a "current" period (the current        day, week, month, quarter, or year), the period will move automatically        to track the current date.  to set a non-standard period, you can use /        and a date: query. -       /  lets  you  set a general filter query limiting the data shown, using-       the same query terms as in hledger and hledger-web.  while editing  the-       query,  you  can  use ctrl-a/e/d/k, bs, cursor keys; press enter to set+       / lets you set a general filter query limiting the  data  shown,  using+       the  same query terms as in hledger and hledger-web.  while editing the+       query, you can use ctrl-a/e/d/k, bs, cursor keys; press  enter  to  set        it, or escapeto cancel.  there are also keys for quickly adjusting some-       common  filters  like account depth and transaction status (see below).+       common filters like account depth and transaction status  (see  below).        backspace or delete removes all filters, showing all transactions. -       as mentioned above, by default hledger-ui hides future  transactions  -+       as  mentioned  above, by default hledger-ui hides future transactions -        both ordinary transactions recorded in the journal, and periodic trans--       actions generated by rule.  f  toggles  forecast  mode,  in  which  fu-+       actions  generated  by  rule.   f  toggles  forecast mode, in which fu-        ture/forecasted transactions are shown.  (experimental) -       escape  resets the UI state and jumps back to the top screen, restoring+       escape resets the UI state and jumps back to the top screen,  restoring        the app's initial state at startup.  Or, it cancels minibuffer data en-        try or the help dialog.         ctrl-l redraws the screen and centers the selection if possible (selec--       tions near the top won't be centered, since we don't scroll  above  the+       tions  near  the top won't be centered, since we don't scroll above the        top). -       g  reloads from the data file(s) and updates the current screen and any-       previous screens.  (with large files, this  could  cause  a  noticeable+       g reloads from the data file(s) and updates the current screen and  any+       previous  screens.   (with  large  files, this could cause a noticeable        pause.) -       i  toggles  balance  assertion  checking.  disabling balance assertions+       i toggles balance assertion  checking.   disabling  balance  assertions        temporarily can be useful for troubleshooting. -       a runs command-line hledger's add  command,  and  reloads  the  updated+       a  runs  command-line  hledger's  add  command, and reloads the updated        file.  this allows some basic data entry. -       a  is like a, but runs the hledger-iadd tool, which provides a terminal-       interface.  this key will be available if hledger-iadd is installed  in+       a is like a, but runs the hledger-iadd tool, which provides a  terminal+       interface.   this key will be available if hledger-iadd is installed in        $path. -       e  runs $hledger_ui_editor, or $editor, or a default (emacsclient -a ""-       -nw) on the journal file.  with some editors (emacs,  vi),  the  cursor-       will  be  positioned  at  the current transaction when invoked from the-       register and transaction screens, and at the error location (if  possi-+       e runs $hledger_ui_editor, or $editor, or a default (emacsclient -a  ""+       -nw)  on  the  journal file.  with some editors (emacs, vi), the cursor+       will be positioned at the current transaction  when  invoked  from  the+       register  and transaction screens, and at the error location (if possi-        ble) when invoked from the error screen. -       b  toggles cost mode, showing amounts in their transaction price's com-+       b toggles cost mode, showing amounts in their transaction price's  com-        modity (like toggling the -b/--cost flag). -       v toggles value mode, showing amounts' current market  value  in  their-       default  valuation  commodity  (like  toggling  the  -v/--market flag).-       note, "current market value" means the value on the report end date  if-       specified,  otherwise today.  to see the value on another date, you can-       temporarily set that as the report end date.  eg: to see a  transaction-       as  it  was  valued  on july 30, go to the accounts or register screen,+       v  toggles  value  mode, showing amounts' current market value in their+       default valuation  commodity  (like  toggling  the  -v/--market  flag).+       note,  "current market value" means the value on the report end date if+       specified, otherwise today.  to see the value on another date, you  can+       temporarily  set that as the report end date.  eg: to see a transaction+       as it was valued on july 30, go to the  accounts  or  register  screen,        press /, and add date:-7/30 to the query.         at most one of cost or value mode can be active at once. -       there's not yet any visual reminder when cost or value mode is  active;+       there's  not yet any visual reminder when cost or value mode is active;        for now pressing b b v should reliably reset to normal mode. -       with  --watch  active,  if  you  save an edit to the journal file while+       with --watch active, if you save an edit  to  the  journal  file  while        viewing the transaction screen in cost or value mode, the b/v keys will-       stop  working.   to  work  around, press g to force a manual reload, or+       stop working.  to work around, press g to force  a  manual  reload,  or        exit the transaction screen.         q quits the application.@@ -275,43 +279,43 @@  screens    accounts screen-       this is normally the first screen displayed.   it  lists  accounts  and-       their  balances,  like hledger's balance command.  by default, it shows-       all accounts and their latest ending balances (including  the  balances-       of  subaccounts).  if you specify a query on the command line, it shows+       this  is  normally  the  first screen displayed.  it lists accounts and+       their balances, like hledger's balance command.  by default,  it  shows+       all  accounts  and their latest ending balances (including the balances+       of subaccounts).  if you specify a query on the command line, it  shows        just the matched accounts and the balances from matched transactions. -       Account names are shown as a flat list by default; press  t  to  toggle-       tree  mode.   In  list  mode,  account balances are exclusive of subac--       counts, except where subaccounts are hidden by a depth limit  (see  be-+       Account  names  are  shown as a flat list by default; press t to toggle+       tree mode.  In list mode, account  balances  are  exclusive  of  subac-+       counts,  except  where subaccounts are hidden by a depth limit (see be-        low).  In tree mode, all account balances are inclusive of subaccounts. -       To  see  less detail, press a number key, 1 to 9, to set a depth limit.+       To see less detail, press a number key, 1 to 9, to set a  depth  limit.        Or use - to decrease and +/= to increase the depth limit.  0 shows even-       less  detail, collapsing all accounts to a single total.  To remove the+       less detail, collapsing all accounts to a single total.  To remove  the        depth limit, set it higher than the maximum account depth, or press ES-        CAPE.         H toggles between showing historical balances or period balances.  His--       torical balances (the default) are ending balances at the  end  of  the-       report  period,  taking  into account all transactions before that date-       (filtered by the filter query if any),  including  transactions  before-       the  start  of  the report period.  In other words, historical balances-       are what you would see on a bank statement  for  that  account  (unless-       disturbed  by a filter query).  Period balances ignore transactions be--       fore the report start date, so they show the change in  balance  during+       torical  balances  (the  default) are ending balances at the end of the+       report period, taking into account all transactions  before  that  date+       (filtered  by  the  filter query if any), including transactions before+       the start of the report period.  In other  words,  historical  balances+       are  what  you  would  see on a bank statement for that account (unless+       disturbed by a filter query).  Period balances ignore transactions  be-+       fore  the  report start date, so they show the change in balance during        the report period.  They are more useful eg when viewing a time log.         U toggles filtering by unmarked status, including or excluding unmarked        postings in the balances.  Similarly, P toggles pending postings, and C-       toggles  cleared postings.  (By default, balances include all postings;-       if you activate one or two status filters, only those postings are  in-+       toggles cleared postings.  (By default, balances include all  postings;+       if  you activate one or two status filters, only those postings are in-        cluded; and if you activate all three, the filter is removed.)         R toggles real mode, in which virtual postings are ignored. -       Z  toggles  nonzero  mode, in which only accounts with nonzero balances-       are shown (hledger-ui shows zero items by default, unlike  command-line+       Z toggles nonzero mode, in which only accounts  with  nonzero  balances+       are  shown (hledger-ui shows zero items by default, unlike command-line        hledger).         Press right or enter to view an account's transactions register.@@ -320,63 +324,63 @@        This screen shows the transactions affecting a particular account, like        a check register.  Each line represents one transaction and shows: -       o the other account(s) involved, in abbreviated form.   (If  there  are-         both  real  and virtual postings, it shows only the accounts affected+       o the  other  account(s)  involved, in abbreviated form.  (If there are+         both real and virtual postings, it shows only the  accounts  affected          by real postings.) -       o the overall change to the current account's balance; positive for  an+       o the  overall change to the current account's balance; positive for an          inflow to this account, negative for an outflow.         o the running historical total or period total for the current account,-         after the transaction.  This can be toggled with H.  Similar  to  the-         accounts  screen,  the  historical  total is affected by transactions-         (filtered by the filter query) before the report  start  date,  while+         after  the  transaction.  This can be toggled with H.  Similar to the+         accounts screen, the historical total  is  affected  by  transactions+         (filtered  by  the  filter query) before the report start date, while          the period total is not.  If the historical total is not disturbed by-         a filter query, it will be the running historical balance  you  would+         a  filter  query, it will be the running historical balance you would          see on a bank register for the current account. -       Transactions  affecting  this account's subaccounts will be included in+       Transactions affecting this account's subaccounts will be  included  in        the register if the accounts screen is in tree mode, or if it's in list-       mode  but  this  account  has  subaccounts which are not shown due to a-       depth limit.  In other words, the register always  shows  the  transac--       tions  contributing  to the balance shown on the accounts screen.  Tree+       mode but this account has subaccounts which are  not  shown  due  to  a+       depth  limit.   In  other words, the register always shows the transac-+       tions contributing to the balance shown on the accounts  screen.   Tree        mode/list mode can be toggled with t here also. -       U toggles filtering by unmarked  status,  showing  or  hiding  unmarked+       U  toggles  filtering  by  unmarked  status, showing or hiding unmarked        transactions.  Similarly, P toggles pending transactions, and C toggles-       cleared transactions.  (By default, transactions with all statuses  are-       shown;  if  you activate one or two status filters, only those transac-+       cleared  transactions.  (By default, transactions with all statuses are+       shown; if you activate one or two status filters, only  those  transac-        tions are shown; and if you activate all three, the filter is removed.)         R toggles real mode, in which virtual postings are ignored. -       Z toggles nonzero mode, in which only transactions  posting  a  nonzero-       change  are  shown (hledger-ui shows zero items by default, unlike com-+       Z  toggles  nonzero  mode, in which only transactions posting a nonzero+       change are shown (hledger-ui shows zero items by default,  unlike  com-        mand-line hledger).         Press right (or enter) to view the selected transaction in detail.     Transaction screen-       This screen shows a single transaction, as  a  general  journal  entry,-       similar  to  hledger's  print command and journal format (hledger_jour-+       This  screen  shows  a  single transaction, as a general journal entry,+       similar to hledger's print command and  journal  format  (hledger_jour-        nal(5)). -       The transaction's date(s) and any cleared flag, transaction  code,  de--       scription,  comments, along with all of its account postings are shown.-       Simple transactions have two postings, but there can  be  more  (or  in+       The  transaction's  date(s) and any cleared flag, transaction code, de-+       scription, comments, along with all of its account postings are  shown.+       Simple  transactions  have  two  postings, but there can be more (or in        certain cases, fewer). -       up  and  down will step through all transactions listed in the previous-       account register screen.  In the title bar, the numbers in  parentheses-       show  your  position  within that account register.  They will vary de-+       up and down will step through all transactions listed in  the  previous+       account  register screen.  In the title bar, the numbers in parentheses+       show your position within that account register.  They  will  vary  de-        pending on which account register you came from (remember most transac--       tions  appear  in multiple account registers).  The #N number preceding+       tions appear in multiple account registers).  The #N  number  preceding        them is the transaction's position within the complete unfiltered jour-        nal, which is a more stable id (at least until the next reload).     Error screen-       This  screen  will appear if there is a problem, such as a parse error,-       when you press g to reload.  Once you have fixed the problem,  press  g+       This screen will appear if there is a problem, such as a  parse  error,+       when  you  press g to reload.  Once you have fixed the problem, press g        again to reload and resume normal operation.  (Or, you can press escape        to cancel the reload attempt.) @@ -384,15 +388,15 @@        COLUMNS The screen width to use.  Default: the full terminal width.         LEDGER_FILE The journal file path when not specified with -f.  Default:-       ~/.hledger.journal  (on  windows,  perhaps C:/Users/USER/.hledger.jour-+       ~/.hledger.journal (on  windows,  perhaps  C:/Users/USER/.hledger.jour-        nal). -       A typical value is ~/DIR/YYYY.journal,  where  DIR  is  a  version-con--       trolled  finance directory and YYYY is the current year.  Or ~/DIR/cur-+       A  typical  value  is  ~/DIR/YYYY.journal,  where DIR is a version-con-+       trolled finance directory and YYYY is the current year.  Or  ~/DIR/cur-        rent.journal, where current.journal is a symbolic link to YYYY.journal.         On Mac computers, you can set this and other environment variables in a-       more  thorough  way that also affects applications started from the GUI+       more thorough way that also affects applications started from  the  GUI        (say, an Emacs dock icon).  Eg on MacOS Catalina I have a ~/.MacOSX/en-        vironment.plist file containing @@ -403,13 +407,13 @@        To see the effect you may need to killall Dock, or reboot.  FILES-       Reads  data from one or more files in hledger journal, timeclock, time--       dot,  or  CSV  format  specified   with   -f,   or   $LEDGER_FILE,   or-       $HOME/.hledger.journal           (on          windows,          perhaps+       Reads data from one or more files in hledger journal, timeclock,  time-+       dot,   or   CSV   format   specified   with  -f,  or  $LEDGER_FILE,  or+       $HOME/.hledger.journal          (on          windows,           perhaps        C:/Users/USER/.hledger.journal).  BUGS-       The need to precede options with -- when invoked from hledger  is  awk-+       The  need  to precede options with -- when invoked from hledger is awk-        ward.         -f- doesn't work (hledger-ui can't read from stdin).@@ -417,24 +421,24 @@        -V affects only the accounts screen.         When you press g, the current and all previous screens are regenerated,-       which may cause a noticeable pause with large files.  Also there is  no+       which  may cause a noticeable pause with large files.  Also there is no        visual indication that this is in progress. -       --watch  is  not yet fully robust.  It works well for normal usage, but-       many file changes in a short time (eg  saving  the  file  thousands  of-       times  with an editor macro) can cause problems at least on OSX.  Symp--       toms include: unresponsive UI, periodic resetting of the  cursor  posi-+       --watch is not yet fully robust.  It works well for normal  usage,  but+       many  file  changes  in  a  short time (eg saving the file thousands of+       times with an editor macro) can cause problems at least on OSX.   Symp-+       toms  include:  unresponsive UI, periodic resetting of the cursor posi-        tion, momentary display of parse errors, high CPU usage eventually sub-        siding, and possibly a small but persistent build-up of CPU usage until        the program is restarted. -       Also,  if  you  are viewing files mounted from another machine, --watch+       Also, if you are viewing files mounted from  another  machine,  --watch        requires that both machine clocks are roughly in step.    REPORTING BUGS-       Report bugs at http://bugs.hledger.org (or on the #hledger IRC  channel+       Report  bugs at http://bugs.hledger.org (or on the #hledger IRC channel        or hledger mail list)  @@ -448,7 +452,7 @@   SEE ALSO-       hledger(1),      hledger-ui(1),     hledger-web(1),     hledger-api(1),+       hledger(1),     hledger-ui(1),     hledger-web(1),      hledger-api(1),        hledger_csv(5), hledger_journal(5), hledger_timeclock(5), hledger_time-        dot(5), ledger(1) @@ -456,4 +460,4 @@   -hledger-ui 1.18.99              September 2020                   hledger-ui(1)+hledger-ui 1.20                  November 2020                   hledger-ui(1)